Updated libraries

This commit is contained in:
konrad 2019-05-07 21:42:24 +02:00
parent 2b160b73c3
commit 3d7fd9ca20
No known key found for this signature in database
GPG key ID: F40E70337AB24C9B
313 changed files with 37947 additions and 6783 deletions

51
go.mod
View file

@ -18,63 +18,56 @@ module code.vikunja.io/api
require ( require (
cloud.google.com/go v0.34.0 // indirect cloud.google.com/go v0.34.0 // indirect
code.vikunja.io/web v0.0.0-20190329170935-7dc1f4191c49 code.vikunja.io/web v0.0.0-20190507193736-edb39812af9c
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
github.com/client9/misspell v0.3.4 github.com/client9/misspell v0.3.4
github.com/d4l3k/messagediff v1.2.1 // indirect github.com/d4l3k/messagediff v1.2.1 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/fzipp/gocyclo v0.0.0-20150627053110-6acd4345c835 github.com/fzipp/gocyclo v0.0.0-20150627053110-6acd4345c835
github.com/garyburd/redigo v1.6.0 // indirect github.com/garyburd/redigo v1.6.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect github.com/go-openapi/jsonpointer v0.19.0 // indirect
github.com/go-openapi/spec v0.17.2 // indirect github.com/go-openapi/jsonreference v0.19.0 // indirect
github.com/go-openapi/swag v0.17.2 // indirect github.com/go-openapi/spec v0.19.0 // indirect
github.com/go-redis/redis v6.14.2+incompatible github.com/go-openapi/swag v0.19.0 // indirect
github.com/go-redis/redis v6.15.2+incompatible
github.com/go-sql-driver/mysql v1.4.1 github.com/go-sql-driver/mysql v1.4.1
github.com/go-xorm/builder v0.3.2 github.com/go-xorm/builder v0.3.4
github.com/go-xorm/core v0.6.0 github.com/go-xorm/core v0.6.2
github.com/go-xorm/tests v0.5.6 // indirect github.com/go-xorm/tests v0.5.6 // indirect
github.com/go-xorm/xorm v0.7.1 github.com/go-xorm/xorm v0.7.1
github.com/go-xorm/xorm-redis-cache v0.0.0-20180727005610-859b313566b2 github.com/go-xorm/xorm-redis-cache v0.0.0-20180727005610-859b313566b2
github.com/gordonklaus/ineffassign v0.0.0-20180909121442-1003c8bd00dc github.com/gordonklaus/ineffassign v0.0.0-20180909121442-1003c8bd00dc
github.com/imdario/mergo v0.3.6 github.com/imdario/mergo v0.3.7
github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jgautheron/goconst v0.0.0-20170703170152-9740945f5dcb github.com/jgautheron/goconst v0.0.0-20170703170152-9740945f5dcb
github.com/karalabe/xgo v0.0.0-20181007145344-72da7d1d3970 // indirect github.com/labstack/echo/v4 v4.1.5
github.com/kisielk/gotool v1.0.0 // indirect
github.com/labstack/echo v3.3.10+incompatible
github.com/labstack/gommon v0.2.8 github.com/labstack/gommon v0.2.8
github.com/mattn/go-colorable v0.1.1 // indirect github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983 // indirect
github.com/mattn/go-isatty v0.0.7 // indirect
github.com/mattn/go-oci8 v0.0.0-20181130072307-052f5d97b9b6 // indirect github.com/mattn/go-oci8 v0.0.0-20181130072307-052f5d97b9b6 // indirect
github.com/mattn/go-runewidth v0.0.4 // indirect github.com/mattn/go-runewidth v0.0.4 // indirect
github.com/mattn/go-sqlite3 v1.10.0 github.com/mattn/go-sqlite3 v1.10.0
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/olekukonko/tablewriter v0.0.1 github.com/olekukonko/tablewriter v0.0.1
github.com/onsi/ginkgo v1.7.0 // indirect github.com/onsi/ginkgo v1.7.0 // indirect
github.com/onsi/gomega v1.4.3 // indirect github.com/onsi/gomega v1.4.3 // indirect
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/pelletier/go-toml v1.4.0 // indirect
github.com/prometheus/client_golang v0.9.2 github.com/prometheus/client_golang v0.9.2
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/cobra v0.0.3 github.com/spf13/cobra v0.0.3
github.com/spf13/viper v1.2.0 github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/stretchr/objx v0.1.1 // indirect github.com/spf13/viper v1.3.2
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.3.0
github.com/swaggo/swag v1.4.1-0.20181210033626-0e12fd5eb026 github.com/swaggo/swag v1.5.0
github.com/urfave/cli v1.20.0 // indirect golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284
github.com/valyala/fasttemplate v1.0.1 // indirect golang.org/x/lint v0.0.0-20190409202823-959b441ac422
golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c // indirect
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3 google.golang.org/appengine v1.5.0 // indirect
golang.org/x/net v0.0.0-20190420063019-afa5a82059c6 // indirect
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 // indirect
golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/d4l3k/messagediff.v1 v1.2.1 gopkg.in/d4l3k/messagediff.v1 v1.2.1
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/testfixtures.v2 v2.5.3 gopkg.in/testfixtures.v2 v2.5.3
gopkg.in/yaml.v2 v2.2.2 // indirect
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a
src.techknowlogick.com/xgo v0.0.0-20190415010919-1502273fab15 src.techknowlogick.com/xgo v0.0.0-20190507142556-a5b29ecb0ff4
src.techknowlogick.com/xormigrate v0.0.0-20190321151057-24497c23c09c src.techknowlogick.com/xormigrate v0.0.0-20190321151057-24497c23c09c
) )

191
go.sum
View file

@ -1,37 +1,30 @@
cloud.google.com/go v0.33.1/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.33.1/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
code.vikunja.io/web v0.0.0-20190123142349-c30ef6073334 h1:a8RDvsjGxDx8w/OsADUpikHYHjZb8CoCiwEOKsQnN4w= code.vikunja.io/web v0.0.0-20190507193736-edb39812af9c h1:L8aPCsaLQe9qytRavkRqipse64EbDK8mFijm+9SKf7I=
code.vikunja.io/web v0.0.0-20190123142349-c30ef6073334/go.mod h1:PmGEu9qI7nbEKDn38H0SWgCoGO4GLdbjdlnWSzFi2PA= code.vikunja.io/web v0.0.0-20190507193736-edb39812af9c/go.mod h1:9dOotUqYZJhDhimNh4Xo4e2i+8cR+qPFEQNCUzaplsI=
code.vikunja.io/web v0.0.0-20190324075814-1ddbccd6c866 h1:12F2fgKvTpnREgw+8GNGNQbRRXXDdI6tWg0WUyoHyaU=
code.vikunja.io/web v0.0.0-20190324075814-1ddbccd6c866/go.mod h1:PmGEu9qI7nbEKDn38H0SWgCoGO4GLdbjdlnWSzFi2PA=
code.vikunja.io/web v0.0.0-20190324080654-fcc8b45b7e2c h1:j1VTb5aOEQ3y4Y+u0RzU5lj45PpzQ/oSyVE5n/dPXB8=
code.vikunja.io/web v0.0.0-20190324080654-fcc8b45b7e2c/go.mod h1:PmGEu9qI7nbEKDn38H0SWgCoGO4GLdbjdlnWSzFi2PA=
code.vikunja.io/web v0.0.0-20190324080741-7bd881d9892a h1:nB+kG5/gq0njK9/fEtYgzvLfd+U8i1I4m3CvYC+aN9k=
code.vikunja.io/web v0.0.0-20190324080741-7bd881d9892a/go.mod h1:PmGEu9qI7nbEKDn38H0SWgCoGO4GLdbjdlnWSzFi2PA=
code.vikunja.io/web v0.0.0-20190324105229-0933ac082307 h1:t2E9v+k56RbvM5WNJF5BFFJDZrzM5l1Ua8qWdZYJAdA=
code.vikunja.io/web v0.0.0-20190324105229-0933ac082307/go.mod h1:PmGEu9qI7nbEKDn38H0SWgCoGO4GLdbjdlnWSzFi2PA=
code.vikunja.io/web v0.0.0-20190324123058-62b466dd1311 h1:3VRszH3NCTNUh+8y2ImA50ALJiE1e9KNoowv9y8mzvA=
code.vikunja.io/web v0.0.0-20190324123058-62b466dd1311/go.mod h1:PmGEu9qI7nbEKDn38H0SWgCoGO4GLdbjdlnWSzFi2PA=
code.vikunja.io/web v0.0.0-20190329170935-7dc1f4191c49 h1:onS7evj9KeCnf/3kNGlY1pXCT1BDay3WlbFddH6bwIE=
code.vikunja.io/web v0.0.0-20190329170935-7dc1f4191c49/go.mod h1:PmGEu9qI7nbEKDn38H0SWgCoGO4GLdbjdlnWSzFi2PA=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4= github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cweill/gotests v1.5.2 h1:kKqmKmS2wCV3tuLnfpbiuN8OlkosQZTpCfiqmiuNAsA= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cweill/gotests v1.5.3 h1:k3t4wW/x/YNixWZJhUIn+mivmK5iV1tJVOwVYkx0UcU= github.com/cweill/gotests v1.5.3 h1:k3t4wW/x/YNixWZJhUIn+mivmK5iV1tJVOwVYkx0UcU=
github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U= github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U=
github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo= github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
@ -50,40 +43,51 @@ github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc
github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y=
github.com/go-openapi/jsonpointer v0.17.0 h1:nH6xp8XdXHx8dqveo0ZuJBluCO2qGrPbDNZ0dwoRHP0= github.com/go-openapi/jsonpointer v0.17.0 h1:nH6xp8XdXHx8dqveo0ZuJBluCO2qGrPbDNZ0dwoRHP0=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.0 h1:FTUMcX77w5rQkClIzDtTxvn6Bsa894CcrzNj2MMfeg8=
github.com/go-openapi/jsonpointer v0.19.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonreference v0.17.0 h1:yJW3HCkTHg7NOA+gZ83IPHzUSnUzGXhGmsdiCcMexbA= github.com/go-openapi/jsonreference v0.17.0 h1:yJW3HCkTHg7NOA+gZ83IPHzUSnUzGXhGmsdiCcMexbA=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/spec v0.17.2 h1:eb2NbuCnoe8cWAxhtK6CfMWUYmiFEZJ9Hx3Z2WRwJ5M= github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/spec v0.17.2/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/jsonreference v0.19.0 h1:BqWKpV1dFd+AuiKlgtddwVIFQsuMpxfBDBHGfM2yNpk=
github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.0 h1:A4SZ6IWh3lnjH0rG0Z5lkxazMGBECtrZcbyYQi+64k4=
github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.17.2 h1:K/ycE/XTUDFltNHSO32cGRUhrVGJD64o8WgAIZNyc3k= github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.17.2/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.0 h1:Kg7Wl7LkTPlmc393QZQ/5rQadPhi7pBVEMZxyTi0Ii8=
github.com/go-redis/redis v6.14.2+incompatible h1:UE9pLhzmWf+xHNmZsoccjXosPicuiNaInPgym8nzfg0= github.com/go-openapi/swag v0.19.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-xorm/builder v0.0.0-20170519032130-c8871c857d25 h1:jUX9yw6+iKrs/WuysV2M6ap/ObK/07SE/a7I2uxitwM=
github.com/go-xorm/builder v0.0.0-20170519032130-c8871c857d25/go.mod h1:M+P3wv0K2C+ynucGDEqJCeOTc+6DcAtiiqU8GrCksXY=
github.com/go-xorm/builder v0.3.2 h1:pSsZQRRzJNapKEAEhigw3xLmiLPeAYv5GFlpYZ8+a5I= github.com/go-xorm/builder v0.3.2 h1:pSsZQRRzJNapKEAEhigw3xLmiLPeAYv5GFlpYZ8+a5I=
github.com/go-xorm/builder v0.3.2/go.mod h1:v8mE3MFBgtL+RGFNfUnAMUqqfk/Y4W5KuwCFQIEpQLk= github.com/go-xorm/builder v0.3.2/go.mod h1:v8mE3MFBgtL+RGFNfUnAMUqqfk/Y4W5KuwCFQIEpQLk=
github.com/go-xorm/core v0.5.8 h1:vQ0ghlVGnlnFmm4SpHY+xNnPlH810paMcw+Hwz9BCqE= github.com/go-xorm/builder v0.3.4 h1:FxkeGB4Cggdw3tPwutLCpfjng2jugfkg6LDMrd/KsoY=
github.com/go-xorm/core v0.5.8/go.mod h1:d8FJ9Br8OGyQl12MCclmYBuBqqxsyeedpXciV5Myih8= github.com/go-xorm/builder v0.3.4/go.mod h1:KxkQkNN1DpPKTedxXyTQcmH+rXfvk4LZ9SOOBoZBAxw=
github.com/go-xorm/core v0.6.0 h1:tp6hX+ku4OD9khFZS8VGBDRY3kfVCtelPfmkgCyHxL0= github.com/go-xorm/core v0.6.0 h1:tp6hX+ku4OD9khFZS8VGBDRY3kfVCtelPfmkgCyHxL0=
github.com/go-xorm/core v0.6.0/go.mod h1:d8FJ9Br8OGyQl12MCclmYBuBqqxsyeedpXciV5Myih8= github.com/go-xorm/core v0.6.0/go.mod h1:d8FJ9Br8OGyQl12MCclmYBuBqqxsyeedpXciV5Myih8=
github.com/go-xorm/core v0.6.2 h1:EJLcSxf336POJr670wKB55Mah9f93xzvGYzNRgnT8/Y=
github.com/go-xorm/core v0.6.2/go.mod h1:bwPIfLdm/FzWgVUH8WPVlr+uJhscvNGFcaZKXsI3n2c=
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y= github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM= github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
github.com/go-xorm/tests v0.5.6 h1:E4nmVkKfHQAm+i2/pmOJ5JUej6sORVcvwl6/LQybif4= github.com/go-xorm/tests v0.5.6 h1:E4nmVkKfHQAm+i2/pmOJ5JUej6sORVcvwl6/LQybif4=
github.com/go-xorm/tests v0.5.6/go.mod h1:s8J/EnVBcXQR93dN7Jy6Dwlo92HUP5nTgKWF1wGeCDg= github.com/go-xorm/tests v0.5.6/go.mod h1:s8J/EnVBcXQR93dN7Jy6Dwlo92HUP5nTgKWF1wGeCDg=
github.com/go-xorm/xorm v0.0.0-20170930012613-29d4a0330a00 h1:jlA1XEj8QHl6my6FUkHwRCGu/J5hQ1zkW7RqULZ2XGc=
github.com/go-xorm/xorm v0.0.0-20170930012613-29d4a0330a00/go.mod h1:i7qRPD38xj/v75UV+a9pEzr5tfRaH2ndJfwt/fGbQhs=
github.com/go-xorm/xorm v0.7.1 h1:Kj7mfuqctPdX60zuxP6EoEut0f3E6K66H6hcoxiHUMc= github.com/go-xorm/xorm v0.7.1 h1:Kj7mfuqctPdX60zuxP6EoEut0f3E6K66H6hcoxiHUMc=
github.com/go-xorm/xorm v0.7.1/go.mod h1:EHS1htMQFptzMaIHKyzqpHGw6C9Rtug75nsq6DA9unI= github.com/go-xorm/xorm v0.7.1/go.mod h1:EHS1htMQFptzMaIHKyzqpHGw6C9Rtug75nsq6DA9unI=
github.com/go-xorm/xorm-redis-cache v0.0.0-20180727005610-859b313566b2 h1:57QbyUkFcFjipHJQstYR5owRxsQzgD8/OAO/hr4yl/E= github.com/go-xorm/xorm-redis-cache v0.0.0-20180727005610-859b313566b2 h1:57QbyUkFcFjipHJQstYR5owRxsQzgD8/OAO/hr4yl/E=
github.com/go-xorm/xorm-redis-cache v0.0.0-20180727005610-859b313566b2/go.mod h1:xxK9FGkFXrau9/vGdDYSOyQfSgKXBV7iHXpQfNuv6B0= github.com/go-xorm/xorm-redis-cache v0.0.0-20180727005610-859b313566b2/go.mod h1:xxK9FGkFXrau9/vGdDYSOyQfSgKXBV7iHXpQfNuv6B0=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/gordonklaus/ineffassign v0.0.0-20180909121442-1003c8bd00dc h1:cJlkeAx1QYgO5N80aF5xRGstVsRQwgLR7uA2FnP1ZjY= github.com/gordonklaus/ineffassign v0.0.0-20180909121442-1003c8bd00dc h1:cJlkeAx1QYgO5N80aF5xRGstVsRQwgLR7uA2FnP1ZjY=
@ -92,8 +96,8 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc= github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc=
@ -104,19 +108,14 @@ github.com/jgautheron/goconst v0.0.0-20170703170152-9740945f5dcb h1:D5s1HIu80AcM
github.com/jgautheron/goconst v0.0.0-20170703170152-9740945f5dcb/go.mod h1:82TxjOpWQiPmywlbIaB2ZkqJoSYJdLGPgAJDvM3PbKc= github.com/jgautheron/goconst v0.0.0-20170703170152-9740945f5dcb/go.mod h1:82TxjOpWQiPmywlbIaB2ZkqJoSYJdLGPgAJDvM3PbKc=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/karalabe/xgo v0.0.0-20181007145344-72da7d1d3970 h1:0+1ZURVRim6FxA/jhWhJklsgoWc69q1sxlIu2Ztnhy0= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/karalabe/xgo v0.0.0-20181007145344-72da7d1d3970/go.mod h1:iYGcTYIPUvEWhFo6aKUuLchs+AV4ssYdyuBbQJZGcBk=
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/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 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/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/labstack/echo v3.3.5+incompatible h1:9PfxPUmasKzeJor9uQTaXLT6WUG/r+vSTmvXxvv3JO4= github.com/labstack/echo/v4 v4.1.5 h1:RztCXCvfMljychg0G/IzW5T7hL6ADqqwREwcX279Q1g=
github.com/labstack/echo v3.3.5+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= github.com/labstack/echo/v4 v4.1.5/go.mod h1:3LbYC6VkwmUnmLPZ8WFdHdQHG77e9GQbjyhWdb1QvC4=
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/gommon v0.2.8 h1:JvRqmeZcfrHC5u6uVleB4NxxNbzx6gpbJiQknDbKQu0= github.com/labstack/gommon v0.2.8 h1:JvRqmeZcfrHC5u6uVleB4NxxNbzx6gpbJiQknDbKQu0=
github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4= github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
@ -125,8 +124,9 @@ github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDe
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983 h1:wL11wNW7dhKIcRCHSm4sHKPWz0tt4mwBsVodG7+Xyqg=
github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
@ -144,12 +144,10 @@ github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK86
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
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/mapstructure v1.0.0 h1:vVpGvMXJPqSDh2VYHF7gsfQj8Ncx+Xw5Y1KHeTRY+7I=
github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88= github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@ -161,8 +159,12 @@ github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0C
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg=
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740=
@ -179,87 +181,89 @@ github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t4
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg= github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/viper v1.2.0 h1:M4Rzxlu+RgU4pyBRKhKaVN1VeYOm8h2jgyXnAseDgCc= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/viper v1.2.0/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/swaggo/swag v1.4.1-0.20181210033626-0e12fd5eb026 h1:XAOjF3QgjDUkVrPMO4rYvNptSHQgUlHwQsEdJOTxHQ8= github.com/swaggo/gin-swagger v1.1.0/go.mod h1:FQlm07YuT1glfN3hQiO11UQ2m39vOCZ/aa3WWr5E+XU=
github.com/swaggo/swag v1.4.1-0.20181210033626-0e12fd5eb026/go.mod h1:hog2WgeMOrQ/LvQ+o1YGTeT+vWVrbi0SiIslBtxKTyM= github.com/swaggo/swag v1.4.0/go.mod h1:hog2WgeMOrQ/LvQ+o1YGTeT+vWVrbi0SiIslBtxKTyM=
github.com/swaggo/swag v1.5.0 h1:haK8VG3hj+v/c8hQ4f3U+oYpkdI/26m9LAUTXHOv+2U=
github.com/swaggo/swag v1.5.0/go.mod h1:+xZrnu5Ut3GcUkKAJm9spnOooIS1WB1cUOkLNPrvrE0=
github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 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/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 h1:gKMu1Bf6QINDnvyZuTaACm9ofY+PRh+5vFz4oxBZeF8=
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw=
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8= github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85 h1:et7+NAX3lLIk5qUCTA9QelBjGE/NkhzYw/mhnr0s7nI= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ56NFcDtcBNkYP7yv8YbUE=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576 h1:aUX/1G2gFSs4AsJJg2cL3HuoRhCSCz733FE5GUSuaT4= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284 h1:rlLehGeYg6jfoyz/eDqDU1iRXLKfR42nnNh57ytKEWo=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/lint v0.0.0-20190409202823-959b441ac422 h1:QzoH/1pFpZguR8NrRHLcO6jKqfv2zpuSqZLgdm7ZmjI=
golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd h1:sMHc2rZHuzQmrbVoSpt9HgerkXPyIeCSO6k0zUMGfFk= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3 h1:x/bBzNauLQAlE3fLku/xy92Y8QwKX5HZymrMz2IiKFc=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58 h1:otZG8yDCO4LVps5+9bxOeNiCvgmOyt96J3roHTYs7oE= golang.org/x/net v0.0.0-20181005035420-146acd28ed58 h1:otZG8yDCO4LVps5+9bxOeNiCvgmOyt96J3roHTYs7oE=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181217023233-e147a9138326 h1:iCzOf0xz39Tstp+Tu/WwyGjUXCk34QhQORRxBeXXTA4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181217023233-e147a9138326/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-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190322120337-addf6b3196f6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190420063019-afa5a82059c6 h1:HdqqaWmYAUI7/dmByKKEw+yxDksGSo+9GjkUc9Zp34E= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw=
golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992 h1:BH3eQWeGbwRU2+wxxuuPOdFBmaiBH81O8BugSjHeTFg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 h1:YAFjXN64LMvktoUZH9zgY4lGc/msGN7HQfoSuKCgaDU= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190123074212-c6b37f3e9285 h1:b5t9HsJXzMmseFB6KtTJWSEtPP8SlVI5nFdf4hnoRFY=
golang.org/x/sys v0.0.0-20190123074212-c6b37f3e9285/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc h1:4gbWbmmPFp4ySWICouJl6emP0MyS31yy9SrTlAGFT+g=
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190329044733-9eb1bfa1ce65 h1:hOY+O8MxdkPV10pNf7/XEHaySCiPKxixMKUshfHsGn0=
golang.org/x/sys v0.0.0-20190329044733-9eb1bfa1ce65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20181026183834-f60e5f99f081 h1:QJP9sxq2/KbTxFnGduVryxJOt6r/UVGyom3tLaqu7tc= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/tools v0.0.0-20181026183834-f60e5f99f081/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b h1:NVD8gBK33xpdqCaZVVtd6OFJp+3dxkXuz7+U7KaVN6s= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190110015856-aa033095749b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c h1:97SnQk1GYRXJgvwZ8fadnxDOWfKvkNQHH3CtZntPSrM=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
google.golang.org/appengine v1.3.0 h1:FBSsiFRMz3LBeXIomRnVzrQwSDj4ibvcRexLG0LZGQk= google.golang.org/appengine v1.3.0 h1:FBSsiFRMz3LBeXIomRnVzrQwSDj4ibvcRexLG0LZGQk=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
@ -270,8 +274,11 @@ gopkg.in/d4l3k/messagediff.v1 v1.2.1 h1:70AthpjunwzUiarMHyED52mj9UwtAnE89l1Gmrt3
gopkg.in/d4l3k/messagediff.v1 v1.2.1/go.mod h1:EUzikiKadqXWcD1AzJLagx0j/BeeWGtn++04Xniyg44= gopkg.in/d4l3k/messagediff.v1 v1.2.1/go.mod h1:EUzikiKadqXWcD1AzJLagx0j/BeeWGtn++04Xniyg44=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
gopkg.in/stretchr/testify.v1 v1.2.2 h1:yhQC6Uy5CqibAIlk1wlusa/MJ3iAN49/BsR/dCCKz3M=
gopkg.in/stretchr/testify.v1 v1.2.2/go.mod h1:QI5V/q6UbPmuhtm10CaFZxED9NreB8PnFYN9JcR6TxU= gopkg.in/stretchr/testify.v1 v1.2.2/go.mod h1:QI5V/q6UbPmuhtm10CaFZxED9NreB8PnFYN9JcR6TxU=
gopkg.in/testfixtures.v2 v2.5.3 h1:P8gDACSLJGxutzBqbzvfiXYgmQ2s00LIr4uAvWBCPAg= gopkg.in/testfixtures.v2 v2.5.3 h1:P8gDACSLJGxutzBqbzvfiXYgmQ2s00LIr4uAvWBCPAg=
gopkg.in/testfixtures.v2 v2.5.3/go.mod h1:rGPtsOtPcZhs7AsHYf1WmufW1hEsM6DXdLrYz60nrQQ= gopkg.in/testfixtures.v2 v2.5.3/go.mod h1:rGPtsOtPcZhs7AsHYf1WmufW1hEsM6DXdLrYz60nrQQ=
@ -281,15 +288,9 @@ gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3 h1:LyX67rVB0kBUFoROrQfzKwdrYLH1cRzHibxdJW85J1c=
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190128043916-71123fcbb8fe h1:/GZ/onp6W295MEgrIwtlbnxmFSKGavFp7/D7tMVyuaM=
honnef.co/go/tools v0.0.0-20190128043916-71123fcbb8fe/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190215041234-466a0476246c h1:z+UFwlQ7KVwdlQTE5JjvDvfZmyyAVrEiiwau20b7X8k=
honnef.co/go/tools v0.0.0-20190215041234-466a0476246c/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a h1:LJwr7TCTghdatWv40WobzlKXc9c4s8oGa7QKJUtHhWA= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a h1:LJwr7TCTghdatWv40WobzlKXc9c4s8oGa7QKJUtHhWA=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
src.techknowlogick.com/xgo v0.0.0-20190415010919-1502273fab15 h1:pHKgCq4abc5TAZRZGcSCxuJOTvRwzGfnbZdgTsFDgng= src.techknowlogick.com/xgo v0.0.0-20190507142556-a5b29ecb0ff4 h1:DZKMg4qnT7UIyB5ZaC6ZqltF2K5KhA1oQ2PdxOLZ3jg=
src.techknowlogick.com/xgo v0.0.0-20190415010919-1502273fab15/go.mod h1:Ood88figJtEukTnU20P1IrXhyAkbOIGi4YzmeHVtGH0= src.techknowlogick.com/xgo v0.0.0-20190507142556-a5b29ecb0ff4/go.mod h1:Ood88figJtEukTnU20P1IrXhyAkbOIGi4YzmeHVtGH0=
src.techknowlogick.com/xormigrate v0.0.0-20190321151057-24497c23c09c h1:fTwL7EZ3ouk3xeiPiRBYEjSPWTREb9T57bjzpRBNOpQ= src.techknowlogick.com/xormigrate v0.0.0-20190321151057-24497c23c09c h1:fTwL7EZ3ouk3xeiPiRBYEjSPWTREb9T57bjzpRBNOpQ=
src.techknowlogick.com/xormigrate v0.0.0-20190321151057-24497c23c09c/go.mod h1:B2NutmcRaDDw4EGe7DoCwyWCELA8W+KxXPhLtgqFUaU= src.techknowlogick.com/xormigrate v0.0.0-20190321151057-24497c23c09c/go.mod h1:B2NutmcRaDDw4EGe7DoCwyWCELA8W+KxXPhLtgqFUaU=

View file

@ -24,7 +24,7 @@ import (
"code.vikunja.io/web" "code.vikunja.io/web"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"net/http" "net/http"

View file

@ -19,7 +19,7 @@ package integrations
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"net/url" "net/url"
"testing" "testing"

View file

@ -19,7 +19,7 @@ package integrations
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"net/url" "net/url"
"testing" "testing"

View file

@ -19,7 +19,7 @@ package integrations
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
apiv1 "code.vikunja.io/api/pkg/routes/api/v1" apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"net/http" "net/http"
"testing" "testing"

View file

@ -19,7 +19,7 @@ package integrations
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
apiv1 "code.vikunja.io/api/pkg/routes/api/v1" apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"net/http" "net/http"
"testing" "testing"

View file

@ -19,7 +19,7 @@ package integrations
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
apiv1 "code.vikunja.io/api/pkg/routes/api/v1" apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"net/http" "net/http"
"testing" "testing"

View file

@ -22,7 +22,7 @@ import (
"code.vikunja.io/web" "code.vikunja.io/web"
"fmt" "fmt"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"reflect" "reflect"
"time" "time"

View file

@ -20,7 +20,7 @@ import (
"code.vikunja.io/api/pkg/caldav" "code.vikunja.io/api/pkg/caldav"
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
"time" "time"
) )

View file

@ -20,7 +20,7 @@ package v1
import ( import (
"code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/log"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"github.com/swaggo/swag" "github.com/swaggo/swag"
"net/http" "net/http"
) )

View file

@ -18,7 +18,7 @@ package v1
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
"strconv" "strconv"
) )

View file

@ -22,7 +22,7 @@ import (
"crypto/md5" "crypto/md5"
"encoding/hex" "encoding/hex"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"github.com/spf13/viper" "github.com/spf13/viper"
"net/http" "net/http"
"time" "time"

View file

@ -20,7 +20,7 @@ import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"fmt" "fmt"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
) )
// CheckToken checks prints a message if the token is valid or not. Currently only used for testing pourposes. // CheckToken checks prints a message if the token is valid or not. Currently only used for testing pourposes.

View file

@ -19,7 +19,7 @@ package v1
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
) )

View file

@ -19,7 +19,7 @@ package v1
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
) )

View file

@ -19,7 +19,7 @@ package v1
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
"strconv" "strconv"
) )

View file

@ -19,7 +19,7 @@ package v1
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
) )

View file

@ -19,7 +19,7 @@ package v1
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
) )

View file

@ -19,7 +19,7 @@ package v1
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
) )

View file

@ -19,7 +19,7 @@ package v1
import ( import (
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
) )

View file

@ -47,8 +47,8 @@ import (
"code.vikunja.io/web" "code.vikunja.io/web"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/asaskevich/govalidator" "github.com/asaskevich/govalidator"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"github.com/labstack/echo/middleware" "github.com/labstack/echo/v4/middleware"
elog "github.com/labstack/gommon/log" elog "github.com/labstack/gommon/log"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/spf13/viper" "github.com/spf13/viper"

15
vendor/code.vikunja.io/web/go.mod generated vendored
View file

@ -2,15 +2,10 @@ module code.vikunja.io/web
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/labstack/echo v3.3.5+incompatible github.com/labstack/echo/v4 v4.1.5
github.com/labstack/gommon v0.2.8 // indirect
github.com/mattn/go-colorable v0.0.9 // indirect
github.com/mattn/go-isatty v0.0.4 // indirect
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284 // indirect
github.com/stretchr/testify v1.2.2 // indirect golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b // indirect
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 // indirect golang.org/x/text v0.3.2 // indirect
golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85 // indirect
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 // indirect
) )

44
vendor/code.vikunja.io/web/go.sum generated vendored
View file

@ -1,24 +1,40 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/labstack/echo v3.3.5+incompatible h1:9PfxPUmasKzeJor9uQTaXLT6WUG/r+vSTmvXxvv3JO4= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/labstack/echo v3.3.5+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= github.com/labstack/echo/v4 v4.1.5 h1:RztCXCvfMljychg0G/IzW5T7hL6ADqqwREwcX279Q1g=
github.com/labstack/echo/v4 v4.1.5/go.mod h1:3LbYC6VkwmUnmLPZ8WFdHdQHG77e9GQbjyhWdb1QvC4=
github.com/labstack/gommon v0.2.8 h1:JvRqmeZcfrHC5u6uVleB4NxxNbzx6gpbJiQknDbKQu0= github.com/labstack/gommon v0.2.8 h1:JvRqmeZcfrHC5u6uVleB4NxxNbzx6gpbJiQknDbKQu0=
github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4= github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 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/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 h1:gKMu1Bf6QINDnvyZuTaACm9ofY+PRh+5vFz4oxBZeF8= github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85 h1:et7+NAX3lLIk5qUCTA9QelBjGE/NkhzYw/mhnr0s7nI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 h1:YAFjXN64LMvktoUZH9zgY4lGc/msGN7HQfoSuKCgaDU= golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284 h1:rlLehGeYg6jfoyz/eDqDU1iRXLKfR42nnNh57ytKEWo=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View file

@ -16,7 +16,7 @@
package handler package handler
import ( import (
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
) )

View file

@ -16,7 +16,7 @@
package handler package handler
import ( import (
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
) )

View file

@ -17,7 +17,7 @@ package handler
import ( import (
"code.vikunja.io/web" "code.vikunja.io/web"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
) )

View file

@ -17,7 +17,7 @@ package handler
import ( import (
"errors" "errors"
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"

View file

@ -16,7 +16,7 @@
package handler package handler
import ( import (
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
"strconv" "strconv"
) )

View file

@ -16,7 +16,7 @@
package handler package handler
import ( import (
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
) )

View file

@ -16,7 +16,7 @@
package handler package handler
import ( import (
"github.com/labstack/echo" "github.com/labstack/echo/v4"
"net/http" "net/http"
) )

2
vendor/code.vikunja.io/web/web.go generated vendored
View file

@ -15,7 +15,7 @@
package web package web
import "github.com/labstack/echo" import "github.com/labstack/echo/v4"
// Rights defines rights methods // Rights defines rights methods
type Rights interface { type Rights interface {

View file

@ -1,7 +1,12 @@
language: go language: go
go: go:
- 1.4 - 1.4.x
- 1.5 - 1.5.x
- 1.6 - 1.6.x
- 1.7.x
- 1.8.x
- 1.9.x
- "1.10.x"
- "1.11.x"
- tip - tip

View file

@ -4,7 +4,7 @@ Purell is a tiny Go library to normalize URLs. It returns a pure URL. Pure-ell.
Based on the [wikipedia paper][wiki] and the [RFC 3986 document][rfc]. Based on the [wikipedia paper][wiki] and the [RFC 3986 document][rfc].
[![build status](https://secure.travis-ci.org/PuerkitoBio/purell.png)](http://travis-ci.org/PuerkitoBio/purell) [![build status](https://travis-ci.org/PuerkitoBio/purell.svg?branch=master)](http://travis-ci.org/PuerkitoBio/purell)
## Install ## Install
@ -12,6 +12,7 @@ Based on the [wikipedia paper][wiki] and the [RFC 3986 document][rfc].
## Changelog ## Changelog
* **v1.1.1** : Fix failing test due to Go1.12 changes (thanks to @ianlancetaylor).
* **2016-11-14 (v1.1.0)** : IDN: Conform to RFC 5895: Fold character width (thanks to @beeker1121). * **2016-11-14 (v1.1.0)** : IDN: Conform to RFC 5895: Fold character width (thanks to @beeker1121).
* **2016-07-27 (v1.0.0)** : Normalize IDN to ASCII (thanks to @zenovich). * **2016-07-27 (v1.0.0)** : Normalize IDN to ASCII (thanks to @zenovich).
* **2015-02-08** : Add fix for relative paths issue ([PR #5][pr5]) and add fix for unnecessary encoding of reserved characters ([see issue #7][iss7]). * **2015-02-08** : Add fix for relative paths issue ([PR #5][pr5]) and add fix for unnecessary encoding of reserved characters ([see issue #7][iss7]).

View file

@ -299,7 +299,7 @@ func sortQuery(u *url.URL) {
if len(q) > 0 { if len(q) > 0 {
arKeys := make([]string, len(q)) arKeys := make([]string, len(q))
i := 0 i := 0
for k, _ := range q { for k := range q {
arKeys[i] = k arKeys[i] = k
i++ i++
} }

View file

@ -330,8 +330,10 @@ Validators with parameters
"range(min|max)": Range, "range(min|max)": Range,
"length(min|max)": ByteLength, "length(min|max)": ByteLength,
"runelength(min|max)": RuneLength, "runelength(min|max)": RuneLength,
"stringlength(min|max)": StringLength,
"matches(pattern)": StringMatches, "matches(pattern)": StringMatches,
"in(string1|string2|...|stringN)": IsIn, "in(string1|string2|...|stringN)": IsIn,
"rsapub(keylength)" : IsRsaPub,
``` ```
And here is small example of usage: And here is small example of usage:
@ -339,12 +341,14 @@ And here is small example of usage:
type Post struct { type Post struct {
Title string `valid:"alphanum,required"` Title string `valid:"alphanum,required"`
Message string `valid:"duck,ascii"` Message string `valid:"duck,ascii"`
Message2 string `valid:"animal(dog)"`
AuthorIP string `valid:"ipv4"` AuthorIP string `valid:"ipv4"`
Date string `valid:"-"` Date string `valid:"-"`
} }
post := &Post{ post := &Post{
Title: "My Example Post", Title: "My Example Post",
Message: "duck", Message: "duck",
Message2: "dog",
AuthorIP: "123.234.54.3", AuthorIP: "123.234.54.3",
} }
@ -353,6 +357,13 @@ govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
return str == "duck" return str == "duck"
}) })
// Add your own struct validation tags with parameter
govalidator.ParamTagMap["animal"] = govalidator.ParamValidator(func(str string, params ...string) bool {
species := params[0]
return str == species
})
govalidator.ParamTagRegexMap["animal"] = regexp.MustCompile("^animal\\((\\w+)\\)$")
result, err := govalidator.ValidateStruct(post) result, err := govalidator.ValidateStruct(post)
if err != nil { if err != nil {
println("error: " + err.Error()) println("error: " + err.Error())

View file

@ -4,7 +4,7 @@ linters-settings:
golint: golint:
min-confidence: 0 min-confidence: 0
gocyclo: gocyclo:
min-complexity: 25 min-complexity: 45
maligned: maligned:
suggest-new: true suggest-new: true
dupl: dupl:
@ -19,3 +19,5 @@ linters:
- maligned - maligned
- unparam - unparam
- lll - lll
- gochecknoinits
- gochecknoglobals

View file

@ -1,14 +1,14 @@
// Code generated by go-bindata. // Code generated by go-bindata. DO NOT EDIT.
// sources: // sources:
// schemas/jsonschema-draft-04.json // schemas/jsonschema-draft-04.json (4.357kB)
// schemas/v2/schema.json // schemas/v2/schema.json (40.249kB)
// DO NOT EDIT!
package spec package spec
import ( import (
"bytes" "bytes"
"compress/gzip" "compress/gzip"
"crypto/sha256"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -39,8 +39,9 @@ func bindataRead(data []byte, name string) ([]byte, error) {
} }
type asset struct { type asset struct {
bytes []byte bytes []byte
info os.FileInfo info os.FileInfo
digest [sha256.Size]byte
} }
type bindataFileInfo struct { type bindataFileInfo struct {
@ -84,8 +85,8 @@ func jsonschemaDraft04JSON() (*asset, error) {
return nil, err return nil, err
} }
info := bindataFileInfo{name: "jsonschema-draft-04.json", size: 4357, mode: os.FileMode(420), modTime: time.Unix(1523760398, 0)} info := bindataFileInfo{name: "jsonschema-draft-04.json", size: 4357, mode: os.FileMode(436), modTime: time.Unix(1540282154, 0)}
a := &asset{bytes: bytes, info: info} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe1, 0x48, 0x9d, 0xb, 0x47, 0x55, 0xf0, 0x27, 0x93, 0x30, 0x25, 0x91, 0xd3, 0xfc, 0xb8, 0xf0, 0x7b, 0x68, 0x93, 0xa8, 0x2a, 0x94, 0xf2, 0x48, 0x95, 0xf8, 0xe4, 0xed, 0xf1, 0x1b, 0x82, 0xe2}}
return a, nil return a, nil
} }
@ -104,8 +105,8 @@ func v2SchemaJSON() (*asset, error) {
return nil, err return nil, err
} }
info := bindataFileInfo{name: "v2/schema.json", size: 40249, mode: os.FileMode(420), modTime: time.Unix(1523760397, 0)} info := bindataFileInfo{name: "v2/schema.json", size: 40249, mode: os.FileMode(436), modTime: time.Unix(1540282154, 0)}
a := &asset{bytes: bytes, info: info} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xcb, 0x25, 0x27, 0xe8, 0x46, 0xae, 0x22, 0xc4, 0xf4, 0x8b, 0x1, 0x32, 0x4d, 0x1f, 0xf8, 0xdf, 0x75, 0x15, 0xc8, 0x2d, 0xc7, 0xed, 0xe, 0x7e, 0x0, 0x75, 0xc0, 0xf9, 0xd2, 0x1f, 0x75, 0x57}}
return a, nil return a, nil
} }
@ -113,8 +114,8 @@ func v2SchemaJSON() (*asset, error) {
// It returns an error if the asset could not be found or // It returns an error if the asset could not be found or
// could not be loaded. // could not be loaded.
func Asset(name string) ([]byte, error) { func Asset(name string) ([]byte, error) {
cannonicalName := strings.Replace(name, "\\", "/", -1) canonicalName := strings.Replace(name, "\\", "/", -1)
if f, ok := _bindata[cannonicalName]; ok { if f, ok := _bindata[canonicalName]; ok {
a, err := f() a, err := f()
if err != nil { if err != nil {
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
@ -124,6 +125,12 @@ func Asset(name string) ([]byte, error) {
return nil, fmt.Errorf("Asset %s not found", name) return nil, fmt.Errorf("Asset %s not found", name)
} }
// AssetString returns the asset contents as a string (instead of a []byte).
func AssetString(name string) (string, error) {
data, err := Asset(name)
return string(data), err
}
// MustAsset is like Asset but panics when Asset would return an error. // MustAsset is like Asset but panics when Asset would return an error.
// It simplifies safe initialization of global variables. // It simplifies safe initialization of global variables.
func MustAsset(name string) []byte { func MustAsset(name string) []byte {
@ -135,12 +142,18 @@ func MustAsset(name string) []byte {
return a return a
} }
// MustAssetString is like AssetString but panics when Asset would return an
// error. It simplifies safe initialization of global variables.
func MustAssetString(name string) string {
return string(MustAsset(name))
}
// AssetInfo loads and returns the asset info for the given name. // AssetInfo loads and returns the asset info for the given name.
// It returns an error if the asset could not be found or // It returns an error if the asset could not be found or
// could not be loaded. // could not be loaded.
func AssetInfo(name string) (os.FileInfo, error) { func AssetInfo(name string) (os.FileInfo, error) {
cannonicalName := strings.Replace(name, "\\", "/", -1) canonicalName := strings.Replace(name, "\\", "/", -1)
if f, ok := _bindata[cannonicalName]; ok { if f, ok := _bindata[canonicalName]; ok {
a, err := f() a, err := f()
if err != nil { if err != nil {
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
@ -150,6 +163,33 @@ func AssetInfo(name string) (os.FileInfo, error) {
return nil, fmt.Errorf("AssetInfo %s not found", name) return nil, fmt.Errorf("AssetInfo %s not found", name)
} }
// AssetDigest returns the digest of the file with the given name. It returns an
// error if the asset could not be found or the digest could not be loaded.
func AssetDigest(name string) ([sha256.Size]byte, error) {
canonicalName := strings.Replace(name, "\\", "/", -1)
if f, ok := _bindata[canonicalName]; ok {
a, err := f()
if err != nil {
return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err)
}
return a.digest, nil
}
return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name)
}
// Digests returns a map of all known files and their checksums.
func Digests() (map[string][sha256.Size]byte, error) {
mp := make(map[string][sha256.Size]byte, len(_bindata))
for name := range _bindata {
a, err := _bindata[name]()
if err != nil {
return nil, err
}
mp[name] = a.digest
}
return mp, nil
}
// AssetNames returns the names of the assets. // AssetNames returns the names of the assets.
func AssetNames() []string { func AssetNames() []string {
names := make([]string, 0, len(_bindata)) names := make([]string, 0, len(_bindata))
@ -162,7 +202,8 @@ func AssetNames() []string {
// _bindata is a table, holding each asset generator, mapped to its name. // _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){ var _bindata = map[string]func() (*asset, error){
"jsonschema-draft-04.json": jsonschemaDraft04JSON, "jsonschema-draft-04.json": jsonschemaDraft04JSON,
"v2/schema.json": v2SchemaJSON,
"v2/schema.json": v2SchemaJSON,
} }
// AssetDir returns the file names below a certain // AssetDir returns the file names below a certain
@ -174,15 +215,15 @@ var _bindata = map[string]func() (*asset, error){
// img/ // img/
// a.png // a.png
// b.png // b.png
// then AssetDir("data") would return []string{"foo.txt", "img"} // then AssetDir("data") would return []string{"foo.txt", "img"},
// AssetDir("data/img") would return []string{"a.png", "b.png"} // AssetDir("data/img") would return []string{"a.png", "b.png"},
// AssetDir("foo.txt") and AssetDir("notexist") would return an error // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and
// AssetDir("") will return []string{"data"}. // AssetDir("") will return []string{"data"}.
func AssetDir(name string) ([]string, error) { func AssetDir(name string) ([]string, error) {
node := _bintree node := _bintree
if len(name) != 0 { if len(name) != 0 {
cannonicalName := strings.Replace(name, "\\", "/", -1) canonicalName := strings.Replace(name, "\\", "/", -1)
pathList := strings.Split(cannonicalName, "/") pathList := strings.Split(canonicalName, "/")
for _, p := range pathList { for _, p := range pathList {
node = node.Children[p] node = node.Children[p]
if node == nil { if node == nil {
@ -212,7 +253,7 @@ var _bintree = &bintree{nil, map[string]*bintree{
}}, }},
}} }}
// RestoreAsset restores an asset under the given directory // RestoreAsset restores an asset under the given directory.
func RestoreAsset(dir, name string) error { func RestoreAsset(dir, name string) error {
data, err := Asset(name) data, err := Asset(name)
if err != nil { if err != nil {
@ -230,14 +271,10 @@ func RestoreAsset(dir, name string) error {
if err != nil { if err != nil {
return err return err
} }
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
if err != nil {
return err
}
return nil
} }
// RestoreAssets restores an asset under the given directory recursively // RestoreAssets restores an asset under the given directory recursively.
func RestoreAssets(dir, name string) error { func RestoreAssets(dir, name string) error {
children, err := AssetDir(name) children, err := AssetDir(name)
// File // File
@ -255,6 +292,6 @@ func RestoreAssets(dir, name string) error {
} }
func _filePath(dir, name string) string { func _filePath(dir, name string) string {
cannonicalName := strings.Replace(name, "\\", "/", -1) canonicalName := strings.Replace(name, "\\", "/", -1)
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
} }

60
vendor/github.com/go-openapi/spec/cache.go generated vendored Normal file
View file

@ -0,0 +1,60 @@
// Copyright 2015 go-swagger maintainers
//
// 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.
package spec
import "sync"
// ResolutionCache a cache for resolving urls
type ResolutionCache interface {
Get(string) (interface{}, bool)
Set(string, interface{})
}
type simpleCache struct {
lock sync.RWMutex
store map[string]interface{}
}
// Get retrieves a cached URI
func (s *simpleCache) Get(uri string) (interface{}, bool) {
debugLog("getting %q from resolution cache", uri)
s.lock.RLock()
v, ok := s.store[uri]
debugLog("got %q from resolution cache: %t", uri, ok)
s.lock.RUnlock()
return v, ok
}
// Set caches a URI
func (s *simpleCache) Set(uri string, data interface{}) {
s.lock.Lock()
s.store[uri] = data
s.lock.Unlock()
}
var resCache ResolutionCache
func init() {
resCache = initResolutionCache()
}
// initResolutionCache initializes the URI resolution cache
func initResolutionCache() ResolutionCache {
return &simpleCache{store: map[string]interface{}{
"http://swagger.io/v2/schema.json": MustLoadSwagger20Schema(),
"http://json-schema.org/draft-04/schema": MustLoadJSONSchemaDraft04(),
}}
}

View file

@ -24,9 +24,9 @@ import (
var ( var (
// Debug is true when the SWAGGER_DEBUG env var is not empty. // Debug is true when the SWAGGER_DEBUG env var is not empty.
// It enables a more verbose logging of validators. // It enables a more verbose logging of this package.
Debug = os.Getenv("SWAGGER_DEBUG") != "" Debug = os.Getenv("SWAGGER_DEBUG") != ""
// validateLogger is a debug logger for this package // specLogger is a debug logger for this package
specLogger *log.Logger specLogger *log.Logger
) )

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,10 @@ import (
"github.com/go-openapi/swag" "github.com/go-openapi/swag"
) )
const (
jsonArray = "array"
)
// HeaderProps describes a response header // HeaderProps describes a response header
type HeaderProps struct { type HeaderProps struct {
Description string `json:"description,omitempty"` Description string `json:"description,omitempty"`
@ -57,7 +61,7 @@ func (h *Header) Typed(tpe, format string) *Header {
// CollectionOf a fluent builder method for an array item // CollectionOf a fluent builder method for an array item
func (h *Header) CollectionOf(items *Items, format string) *Header { func (h *Header) CollectionOf(items *Items, format string) *Header {
h.Type = "array" h.Type = jsonArray
h.Items = items h.Items = items
h.CollectionFormat = format h.CollectionFormat = format
return h return h

View file

@ -161,8 +161,5 @@ func (i *Info) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &i.InfoProps); err != nil { if err := json.Unmarshal(data, &i.InfoProps); err != nil {
return err return err
} }
if err := json.Unmarshal(data, &i.VendorExtensible); err != nil { return json.Unmarshal(data, &i.VendorExtensible)
return err
}
return nil
} }

View file

@ -22,6 +22,10 @@ import (
"github.com/go-openapi/swag" "github.com/go-openapi/swag"
) )
const (
jsonRef = "$ref"
)
// SimpleSchema describe swagger simple schemas for parameters and headers // SimpleSchema describe swagger simple schemas for parameters and headers
type SimpleSchema struct { type SimpleSchema struct {
Type string `json:"type,omitempty"` Type string `json:"type,omitempty"`
@ -89,7 +93,7 @@ func (i *Items) Typed(tpe, format string) *Items {
// CollectionOf a fluent builder method for an array item // CollectionOf a fluent builder method for an array item
func (i *Items) CollectionOf(items *Items, format string) *Items { func (i *Items) CollectionOf(items *Items, format string) *Items {
i.Type = "array" i.Type = jsonArray
i.Items = items i.Items = items
i.CollectionFormat = format i.CollectionFormat = format
return i return i
@ -217,7 +221,7 @@ func (i Items) MarshalJSON() ([]byte, error) {
// JSONLookup look up a value by the json property name // JSONLookup look up a value by the json property name
func (i Items) JSONLookup(token string) (interface{}, error) { func (i Items) JSONLookup(token string) (interface{}, error) {
if token == "$ref" { if token == jsonRef {
return &i.Ref, nil return &i.Ref, nil
} }

152
vendor/github.com/go-openapi/spec/normalizer.go generated vendored Normal file
View file

@ -0,0 +1,152 @@
// Copyright 2015 go-swagger maintainers
//
// 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.
package spec
import (
"fmt"
"net/url"
"os"
"path"
"path/filepath"
"strings"
)
// normalize absolute path for cache.
// on Windows, drive letters should be converted to lower as scheme in net/url.URL
func normalizeAbsPath(path string) string {
u, err := url.Parse(path)
if err != nil {
debugLog("normalize absolute path failed: %s", err)
return path
}
return u.String()
}
// base or refPath could be a file path or a URL
// given a base absolute path and a ref path, return the absolute path of refPath
// 1) if refPath is absolute, return it
// 2) if refPath is relative, join it with basePath keeping the scheme, hosts, and ports if exists
// base could be a directory or a full file path
func normalizePaths(refPath, base string) string {
refURL, _ := url.Parse(refPath)
if path.IsAbs(refURL.Path) || filepath.IsAbs(refPath) {
// refPath is actually absolute
if refURL.Host != "" {
return refPath
}
parts := strings.Split(refPath, "#")
result := filepath.FromSlash(parts[0])
if len(parts) == 2 {
result += "#" + parts[1]
}
return result
}
// relative refPath
baseURL, _ := url.Parse(base)
if !strings.HasPrefix(refPath, "#") {
// combining paths
if baseURL.Host != "" {
baseURL.Path = path.Join(path.Dir(baseURL.Path), refURL.Path)
} else { // base is a file
newBase := fmt.Sprintf("%s#%s", filepath.Join(filepath.Dir(base), filepath.FromSlash(refURL.Path)), refURL.Fragment)
return newBase
}
}
// copying fragment from ref to base
baseURL.Fragment = refURL.Fragment
return baseURL.String()
}
// denormalizePaths returns to simplest notation on file $ref,
// i.e. strips the absolute path and sets a path relative to the base path.
//
// This is currently used when we rewrite ref after a circular ref has been detected
func denormalizeFileRef(ref *Ref, relativeBase, originalRelativeBase string) *Ref {
debugLog("denormalizeFileRef for: %s", ref.String())
if ref.String() == "" || ref.IsRoot() || ref.HasFragmentOnly {
return ref
}
// strip relativeBase from URI
relativeBaseURL, _ := url.Parse(relativeBase)
relativeBaseURL.Fragment = ""
if relativeBaseURL.IsAbs() && strings.HasPrefix(ref.String(), relativeBase) {
// this should work for absolute URI (e.g. http://...): we have an exact match, just trim prefix
r, _ := NewRef(strings.TrimPrefix(ref.String(), relativeBase))
return &r
}
if relativeBaseURL.IsAbs() {
// other absolute URL get unchanged (i.e. with a non-empty scheme)
return ref
}
// for relative file URIs:
originalRelativeBaseURL, _ := url.Parse(originalRelativeBase)
originalRelativeBaseURL.Fragment = ""
if strings.HasPrefix(ref.String(), originalRelativeBaseURL.String()) {
// the resulting ref is in the expanded spec: return a local ref
r, _ := NewRef(strings.TrimPrefix(ref.String(), originalRelativeBaseURL.String()))
return &r
}
// check if we may set a relative path, considering the original base path for this spec.
// Example:
// spec is located at /mypath/spec.json
// my normalized ref points to: /mypath/item.json#/target
// expected result: item.json#/target
parts := strings.Split(ref.String(), "#")
relativePath, err := filepath.Rel(path.Dir(originalRelativeBaseURL.String()), parts[0])
if err != nil {
// there is no common ancestor (e.g. different drives on windows)
// leaves the ref unchanged
return ref
}
if len(parts) == 2 {
relativePath += "#" + parts[1]
}
r, _ := NewRef(relativePath)
return &r
}
// relativeBase could be an ABSOLUTE file path or an ABSOLUTE URL
func normalizeFileRef(ref *Ref, relativeBase string) *Ref {
// This is important for when the reference is pointing to the root schema
if ref.String() == "" {
r, _ := NewRef(relativeBase)
return &r
}
debugLog("normalizing %s against %s", ref.String(), relativeBase)
s := normalizePaths(ref.String(), relativeBase)
r, _ := NewRef(s)
return &r
}
// absPath returns the absolute path of a file
func absPath(fname string) (string, error) {
if strings.HasPrefix(fname, "http") {
return fname, nil
}
if filepath.IsAbs(fname) {
return fname, nil
}
wd, err := os.Getwd()
return filepath.Join(wd, fname), err
}

View file

@ -15,24 +15,37 @@
package spec package spec
import ( import (
"bytes"
"encoding/gob"
"encoding/json" "encoding/json"
"sort"
"github.com/go-openapi/jsonpointer" "github.com/go-openapi/jsonpointer"
"github.com/go-openapi/swag" "github.com/go-openapi/swag"
) )
func init() {
//gob.Register(map[string][]interface{}{})
gob.Register(map[string]interface{}{})
gob.Register([]interface{}{})
}
// OperationProps describes an operation // OperationProps describes an operation
//
// NOTES:
// - schemes, when present must be from [http, https, ws, wss]: see validate
// - Security is handled as a special case: see MarshalJSON function
type OperationProps struct { type OperationProps struct {
Description string `json:"description,omitempty"` Description string `json:"description,omitempty"`
Consumes []string `json:"consumes,omitempty"` Consumes []string `json:"consumes,omitempty"`
Produces []string `json:"produces,omitempty"` Produces []string `json:"produces,omitempty"`
Schemes []string `json:"schemes,omitempty"` // the scheme, when present must be from [http, https, ws, wss] Schemes []string `json:"schemes,omitempty"`
Tags []string `json:"tags,omitempty"` Tags []string `json:"tags,omitempty"`
Summary string `json:"summary,omitempty"` Summary string `json:"summary,omitempty"`
ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"` ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
ID string `json:"operationId,omitempty"` ID string `json:"operationId,omitempty"`
Deprecated bool `json:"deprecated,omitempty"` Deprecated bool `json:"deprecated,omitempty"`
Security []map[string][]string `json:"security,omitempty"` //Special case, see MarshalJSON function Security []map[string][]string `json:"security,omitempty"`
Parameters []Parameter `json:"parameters,omitempty"` Parameters []Parameter `json:"parameters,omitempty"`
Responses *Responses `json:"responses,omitempty"` Responses *Responses `json:"responses,omitempty"`
} }
@ -76,11 +89,17 @@ func (o *Operation) SuccessResponse() (*Response, int, bool) {
return nil, 0, false return nil, 0, false
} }
for k, v := range o.Responses.StatusCodeResponses { responseCodes := make([]int, 0, len(o.Responses.StatusCodeResponses))
if k/100 == 2 { for k := range o.Responses.StatusCodeResponses {
return &v, k, true if k >= 200 && k < 300 {
responseCodes = append(responseCodes, k)
} }
} }
if len(responseCodes) > 0 {
sort.Ints(responseCodes)
v := o.Responses.StatusCodeResponses[responseCodes[0]]
return &v, responseCodes[0], true
}
return o.Responses.Default, 0, false return o.Responses.Default, 0, false
} }
@ -99,10 +118,7 @@ func (o *Operation) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &o.OperationProps); err != nil { if err := json.Unmarshal(data, &o.OperationProps); err != nil {
return err return err
} }
if err := json.Unmarshal(data, &o.VendorExtensible); err != nil { return json.Unmarshal(data, &o.VendorExtensible)
return err
}
return nil
} }
// MarshalJSON converts this items object to JSON // MarshalJSON converts this items object to JSON
@ -216,7 +232,7 @@ func (o *Operation) AddParam(param *Parameter) *Operation {
// RemoveParam removes a parameter from the operation // RemoveParam removes a parameter from the operation
func (o *Operation) RemoveParam(name, in string) *Operation { func (o *Operation) RemoveParam(name, in string) *Operation {
for i, p := range o.Parameters { for i, p := range o.Parameters {
if p.Name == name && p.In == name { if p.Name == name && p.In == in {
o.Parameters = append(o.Parameters[:i], o.Parameters[i+1:]...) o.Parameters = append(o.Parameters[:i], o.Parameters[i+1:]...)
return o return o
} }
@ -257,3 +273,126 @@ func (o *Operation) RespondsWith(code int, response *Response) *Operation {
o.Responses.StatusCodeResponses[code] = *response o.Responses.StatusCodeResponses[code] = *response
return o return o
} }
type opsAlias OperationProps
type gobAlias struct {
Security []map[string]struct {
List []string
Pad bool
}
Alias *opsAlias
SecurityIsEmpty bool
}
// GobEncode provides a safe gob encoder for Operation, including empty security requirements
func (o Operation) GobEncode() ([]byte, error) {
raw := struct {
Ext VendorExtensible
Props OperationProps
}{
Ext: o.VendorExtensible,
Props: o.OperationProps,
}
var b bytes.Buffer
err := gob.NewEncoder(&b).Encode(raw)
return b.Bytes(), err
}
// GobDecode provides a safe gob decoder for Operation, including empty security requirements
func (o *Operation) GobDecode(b []byte) error {
var raw struct {
Ext VendorExtensible
Props OperationProps
}
buf := bytes.NewBuffer(b)
err := gob.NewDecoder(buf).Decode(&raw)
if err != nil {
return err
}
o.VendorExtensible = raw.Ext
o.OperationProps = raw.Props
return nil
}
// GobEncode provides a safe gob encoder for Operation, including empty security requirements
func (op OperationProps) GobEncode() ([]byte, error) {
raw := gobAlias{
Alias: (*opsAlias)(&op),
}
var b bytes.Buffer
if op.Security == nil {
// nil security requirement
err := gob.NewEncoder(&b).Encode(raw)
return b.Bytes(), err
}
if len(op.Security) == 0 {
// empty, but non-nil security requirement
raw.SecurityIsEmpty = true
raw.Alias.Security = nil
err := gob.NewEncoder(&b).Encode(raw)
return b.Bytes(), err
}
raw.Security = make([]map[string]struct {
List []string
Pad bool
}, 0, len(op.Security))
for _, req := range op.Security {
v := make(map[string]struct {
List []string
Pad bool
}, len(req))
for k, val := range req {
v[k] = struct {
List []string
Pad bool
}{
List: val,
}
}
raw.Security = append(raw.Security, v)
}
err := gob.NewEncoder(&b).Encode(raw)
return b.Bytes(), err
}
// GobDecode provides a safe gob decoder for Operation, including empty security requirements
func (op *OperationProps) GobDecode(b []byte) error {
var raw gobAlias
buf := bytes.NewBuffer(b)
err := gob.NewDecoder(buf).Decode(&raw)
if err != nil {
return err
}
if raw.Alias == nil {
return nil
}
switch {
case raw.SecurityIsEmpty:
// empty, but non-nil security requirement
raw.Alias.Security = []map[string][]string{}
case len(raw.Alias.Security) == 0:
// nil security requirement
raw.Alias.Security = nil
default:
raw.Alias.Security = make([]map[string][]string, 0, len(raw.Security))
for _, req := range raw.Security {
v := make(map[string][]string, len(req))
for k, val := range req {
v[k] = make([]string, 0, len(val.List))
v[k] = append(v[k], val.List...)
}
raw.Alias.Security = append(raw.Alias.Security, v)
}
}
*op = *(*OperationProps)(raw.Alias)
return nil
}

View file

@ -39,7 +39,8 @@ func PathParam(name string) *Parameter {
// BodyParam creates a body parameter // BodyParam creates a body parameter
func BodyParam(name string, schema *Schema) *Parameter { func BodyParam(name string, schema *Schema) *Parameter {
return &Parameter{ParamProps: ParamProps{Name: name, In: "body", Schema: schema}, SimpleSchema: SimpleSchema{Type: "object"}} return &Parameter{ParamProps: ParamProps{Name: name, In: "body", Schema: schema},
SimpleSchema: SimpleSchema{Type: "object"}}
} }
// FormDataParam creates a body parameter // FormDataParam creates a body parameter
@ -49,12 +50,15 @@ func FormDataParam(name string) *Parameter {
// FileParam creates a body parameter // FileParam creates a body parameter
func FileParam(name string) *Parameter { func FileParam(name string) *Parameter {
return &Parameter{ParamProps: ParamProps{Name: name, In: "formData"}, SimpleSchema: SimpleSchema{Type: "file"}} return &Parameter{ParamProps: ParamProps{Name: name, In: "formData"},
SimpleSchema: SimpleSchema{Type: "file"}}
} }
// SimpleArrayParam creates a param for a simple array (string, int, date etc) // SimpleArrayParam creates a param for a simple array (string, int, date etc)
func SimpleArrayParam(name, tpe, fmt string) *Parameter { func SimpleArrayParam(name, tpe, fmt string) *Parameter {
return &Parameter{ParamProps: ParamProps{Name: name}, SimpleSchema: SimpleSchema{Type: "array", CollectionFormat: "csv", Items: &Items{SimpleSchema: SimpleSchema{Type: "string", Format: fmt}}}} return &Parameter{ParamProps: ParamProps{Name: name},
SimpleSchema: SimpleSchema{Type: jsonArray, CollectionFormat: "csv",
Items: &Items{SimpleSchema: SimpleSchema{Type: "string", Format: fmt}}}}
} }
// ParamRef creates a parameter that's a json reference // ParamRef creates a parameter that's a json reference
@ -65,25 +69,43 @@ func ParamRef(uri string) *Parameter {
} }
// ParamProps describes the specific attributes of an operation parameter // ParamProps describes the specific attributes of an operation parameter
//
// NOTE:
// - Schema is defined when "in" == "body": see validate
// - AllowEmptyValue is allowed where "in" == "query" || "formData"
type ParamProps struct { type ParamProps struct {
Description string `json:"description,omitempty"` Description string `json:"description,omitempty"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
In string `json:"in,omitempty"` In string `json:"in,omitempty"`
Required bool `json:"required,omitempty"` Required bool `json:"required,omitempty"`
Schema *Schema `json:"schema,omitempty"` // when in == "body" Schema *Schema `json:"schema,omitempty"`
AllowEmptyValue bool `json:"allowEmptyValue,omitempty"` // when in == "query" || "formData" AllowEmptyValue bool `json:"allowEmptyValue,omitempty"`
} }
// Parameter a unique parameter is defined by a combination of a [name](#parameterName) and [location](#parameterIn). // Parameter a unique parameter is defined by a combination of a [name](#parameterName) and [location](#parameterIn).
// //
// There are five possible parameter types. // There are five possible parameter types.
// * Path - Used together with [Path Templating](#pathTemplating), where the parameter value is actually part of the operation's URL. This does not include the host or base path of the API. For example, in `/items/{itemId}`, the path parameter is `itemId`. // * Path - Used together with [Path Templating](#pathTemplating), where the parameter value is actually part
// of the operation's URL. This does not include the host or base path of the API. For example, in `/items/{itemId}`,
// the path parameter is `itemId`.
// * Query - Parameters that are appended to the URL. For example, in `/items?id=###`, the query parameter is `id`. // * Query - Parameters that are appended to the URL. For example, in `/items?id=###`, the query parameter is `id`.
// * Header - Custom headers that are expected as part of the request. // * Header - Custom headers that are expected as part of the request.
// * Body - The payload that's appended to the HTTP request. Since there can only be one payload, there can only be *one* body parameter. The name of the body parameter has no effect on the parameter itself and is used for documentation purposes only. Since Form parameters are also in the payload, body and form parameters cannot exist together for the same operation. // * Body - The payload that's appended to the HTTP request. Since there can only be one payload, there can only be
// * Form - Used to describe the payload of an HTTP request when either `application/x-www-form-urlencoded` or `multipart/form-data` are used as the content type of the request (in Swagger's definition, the [`consumes`](#operationConsumes) property of an operation). This is the only parameter type that can be used to send files, thus supporting the `file` type. Since form parameters are sent in the payload, they cannot be declared together with a body parameter for the same operation. Form parameters have a different format based on the content-type used (for further details, consult http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4): // _one_ body parameter. The name of the body parameter has no effect on the parameter itself and is used for
// * `application/x-www-form-urlencoded` - Similar to the format of Query parameters but as a payload. For example, `foo=1&bar=swagger` - both `foo` and `bar` are form parameters. This is normally used for simple parameters that are being transferred. // documentation purposes only. Since Form parameters are also in the payload, body and form parameters cannot exist
// * `multipart/form-data` - each parameter takes a section in the payload with an internal header. For example, for the header `Content-Disposition: form-data; name="submit-name"` the name of the parameter is `submit-name`. This type of form parameters is more commonly used for file transfers. // together for the same operation.
// * Form - Used to describe the payload of an HTTP request when either `application/x-www-form-urlencoded` or
// `multipart/form-data` are used as the content type of the request (in Swagger's definition,
// the [`consumes`](#operationConsumes) property of an operation). This is the only parameter type that can be used
// to send files, thus supporting the `file` type. Since form parameters are sent in the payload, they cannot be
// declared together with a body parameter for the same operation. Form parameters have a different format based on
// the content-type used (for further details, consult http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4).
// * `application/x-www-form-urlencoded` - Similar to the format of Query parameters but as a payload.
// For example, `foo=1&bar=swagger` - both `foo` and `bar` are form parameters. This is normally used for simple
// parameters that are being transferred.
// * `multipart/form-data` - each parameter takes a section in the payload with an internal header.
// For example, for the header `Content-Disposition: form-data; name="submit-name"` the name of the parameter is
// `submit-name`. This type of form parameters is more commonly used for file transfers.
// //
// For more information: http://goo.gl/8us55a#parameterObject // For more information: http://goo.gl/8us55a#parameterObject
type Parameter struct { type Parameter struct {
@ -99,7 +121,7 @@ func (p Parameter) JSONLookup(token string) (interface{}, error) {
if ex, ok := p.Extensions[token]; ok { if ex, ok := p.Extensions[token]; ok {
return &ex, nil return &ex, nil
} }
if token == "$ref" { if token == jsonRef {
return &p.Ref, nil return &p.Ref, nil
} }
@ -148,7 +170,7 @@ func (p *Parameter) Typed(tpe, format string) *Parameter {
// CollectionOf a fluent builder method for an array parameter // CollectionOf a fluent builder method for an array parameter
func (p *Parameter) CollectionOf(items *Items, format string) *Parameter { func (p *Parameter) CollectionOf(items *Items, format string) *Parameter {
p.Type = "array" p.Type = jsonArray
p.Items = items p.Items = items
p.CollectionFormat = format p.CollectionFormat = format
return p return p
@ -270,10 +292,7 @@ func (p *Parameter) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &p.VendorExtensible); err != nil { if err := json.Unmarshal(data, &p.VendorExtensible); err != nil {
return err return err
} }
if err := json.Unmarshal(data, &p.ParamProps); err != nil { return json.Unmarshal(data, &p.ParamProps)
return err
}
return nil
} }
// MarshalJSON converts this items object to JSON // MarshalJSON converts this items object to JSON

View file

@ -50,7 +50,7 @@ func (p PathItem) JSONLookup(token string) (interface{}, error) {
if ex, ok := p.Extensions[token]; ok { if ex, ok := p.Extensions[token]; ok {
return &ex, nil return &ex, nil
} }
if token == "$ref" { if token == jsonRef {
return &p.Ref, nil return &p.Ref, nil
} }
r, _, err := jsonpointer.GetForToken(p.PathItemProps, token) r, _, err := jsonpointer.GetForToken(p.PathItemProps, token)
@ -65,10 +65,7 @@ func (p *PathItem) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &p.VendorExtensible); err != nil { if err := json.Unmarshal(data, &p.VendorExtensible); err != nil {
return err return err
} }
if err := json.Unmarshal(data, &p.PathItemProps); err != nil { return json.Unmarshal(data, &p.PathItemProps)
return err
}
return nil
} }
// MarshalJSON converts this items object to JSON // MarshalJSON converts this items object to JSON

View file

@ -15,6 +15,8 @@
package spec package spec
import ( import (
"bytes"
"encoding/gob"
"encoding/json" "encoding/json"
"net/http" "net/http"
"os" "os"
@ -148,6 +150,28 @@ func (r *Ref) UnmarshalJSON(d []byte) error {
return r.fromMap(v) return r.fromMap(v)
} }
// GobEncode provides a safe gob encoder for Ref
func (r Ref) GobEncode() ([]byte, error) {
var b bytes.Buffer
raw, err := r.MarshalJSON()
if err != nil {
return nil, err
}
err = gob.NewEncoder(&b).Encode(raw)
return b.Bytes(), err
}
// GobDecode provides a safe gob decoder for Ref
func (r *Ref) GobDecode(b []byte) error {
var raw []byte
buf := bytes.NewBuffer(b)
err := gob.NewDecoder(buf).Decode(&raw)
if err != nil {
return err
}
return json.Unmarshal(raw, r)
}
func (r *Ref) fromMap(v map[string]interface{}) error { func (r *Ref) fromMap(v map[string]interface{}) error {
if v == nil { if v == nil {
return nil return nil

View file

@ -58,10 +58,7 @@ func (r *Response) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &r.Refable); err != nil { if err := json.Unmarshal(data, &r.Refable); err != nil {
return err return err
} }
if err := json.Unmarshal(data, &r.VendorExtensible); err != nil { return json.Unmarshal(data, &r.VendorExtensible)
return err
}
return nil
} }
// MarshalJSON converts this items object to JSON // MarshalJSON converts this items object to JSON

View file

@ -89,7 +89,8 @@ func DateTimeProperty() *Schema {
// MapProperty creates a map property // MapProperty creates a map property
func MapProperty(property *Schema) *Schema { func MapProperty(property *Schema) *Schema {
return &Schema{SchemaProps: SchemaProps{Type: []string{"object"}, AdditionalProperties: &SchemaOrBool{Allows: true, Schema: property}}} return &Schema{SchemaProps: SchemaProps{Type: []string{"object"},
AdditionalProperties: &SchemaOrBool{Allows: true, Schema: property}}}
} }
// RefProperty creates a ref property // RefProperty creates a ref property
@ -155,54 +156,6 @@ func (r *SchemaURL) fromMap(v map[string]interface{}) error {
return nil return nil
} }
// type ExtraSchemaProps map[string]interface{}
// // JSONSchema represents a structure that is a json schema draft 04
// type JSONSchema struct {
// SchemaProps
// ExtraSchemaProps
// }
// // MarshalJSON marshal this to JSON
// func (s JSONSchema) MarshalJSON() ([]byte, error) {
// b1, err := json.Marshal(s.SchemaProps)
// if err != nil {
// return nil, err
// }
// b2, err := s.Ref.MarshalJSON()
// if err != nil {
// return nil, err
// }
// b3, err := s.Schema.MarshalJSON()
// if err != nil {
// return nil, err
// }
// b4, err := json.Marshal(s.ExtraSchemaProps)
// if err != nil {
// return nil, err
// }
// return swag.ConcatJSON(b1, b2, b3, b4), nil
// }
// // UnmarshalJSON marshal this from JSON
// func (s *JSONSchema) UnmarshalJSON(data []byte) error {
// var sch JSONSchema
// if err := json.Unmarshal(data, &sch.SchemaProps); err != nil {
// return err
// }
// if err := json.Unmarshal(data, &sch.Ref); err != nil {
// return err
// }
// if err := json.Unmarshal(data, &sch.Schema); err != nil {
// return err
// }
// if err := json.Unmarshal(data, &sch.ExtraSchemaProps); err != nil {
// return err
// }
// *s = sch
// return nil
// }
// SchemaProps describes a JSON schema (draft 4) // SchemaProps describes a JSON schema (draft 4)
type SchemaProps struct { type SchemaProps struct {
ID string `json:"id,omitempty"` ID string `json:"id,omitempty"`
@ -351,7 +304,7 @@ func (s *Schema) AddType(tpe, format string) *Schema {
// CollectionOf a fluent builder method for an array parameter // CollectionOf a fluent builder method for an array parameter
func (s *Schema) CollectionOf(items Schema) *Schema { func (s *Schema) CollectionOf(items Schema) *Schema {
s.Type = []string{"array"} s.Type = []string{jsonArray}
s.Items = &SchemaOrArray{Schema: &items} s.Items = &SchemaOrArray{Schema: &items}
return s return s
} }

275
vendor/github.com/go-openapi/spec/schema_loader.go generated vendored Normal file
View file

@ -0,0 +1,275 @@
// Copyright 2015 go-swagger maintainers
//
// 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.
package spec
import (
"encoding/json"
"fmt"
"log"
"net/url"
"reflect"
"strings"
"github.com/go-openapi/swag"
)
// PathLoader function to use when loading remote refs
var PathLoader func(string) (json.RawMessage, error)
func init() {
PathLoader = func(path string) (json.RawMessage, error) {
data, err := swag.LoadFromFileOrHTTP(path)
if err != nil {
return nil, err
}
return json.RawMessage(data), nil
}
}
// resolverContext allows to share a context during spec processing.
// At the moment, it just holds the index of circular references found.
type resolverContext struct {
// circulars holds all visited circular references, which allows shortcuts.
// NOTE: this is not just a performance improvement: it is required to figure out
// circular references which participate several cycles.
// This structure is privately instantiated and needs not be locked against
// concurrent access, unless we chose to implement a parallel spec walking.
circulars map[string]bool
basePath string
}
func newResolverContext(originalBasePath string) *resolverContext {
return &resolverContext{
circulars: make(map[string]bool),
basePath: originalBasePath, // keep the root base path in context
}
}
type schemaLoader struct {
root interface{}
options *ExpandOptions
cache ResolutionCache
context *resolverContext
loadDoc func(string) (json.RawMessage, error)
}
func (r *schemaLoader) transitiveResolver(basePath string, ref Ref) (*schemaLoader, error) {
if ref.IsRoot() || ref.HasFragmentOnly {
return r, nil
}
baseRef, _ := NewRef(basePath)
currentRef := normalizeFileRef(&ref, basePath)
if strings.HasPrefix(currentRef.String(), baseRef.String()) {
return r, nil
}
// Set a new root to resolve against
rootURL := currentRef.GetURL()
rootURL.Fragment = ""
root, _ := r.cache.Get(rootURL.String())
// shallow copy of resolver options to set a new RelativeBase when
// traversing multiple documents
newOptions := r.options
newOptions.RelativeBase = rootURL.String()
debugLog("setting new root: %s", newOptions.RelativeBase)
resolver, err := defaultSchemaLoader(root, newOptions, r.cache, r.context)
if err != nil {
return nil, err
}
return resolver, nil
}
func (r *schemaLoader) updateBasePath(transitive *schemaLoader, basePath string) string {
if transitive != r {
debugLog("got a new resolver")
if transitive.options != nil && transitive.options.RelativeBase != "" {
basePath, _ = absPath(transitive.options.RelativeBase)
debugLog("new basePath = %s", basePath)
}
}
return basePath
}
func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string) error {
tgt := reflect.ValueOf(target)
if tgt.Kind() != reflect.Ptr {
return fmt.Errorf("resolve ref: target needs to be a pointer")
}
refURL := ref.GetURL()
if refURL == nil {
return nil
}
var res interface{}
var data interface{}
var err error
// Resolve against the root if it isn't nil, and if ref is pointing at the root, or has a fragment only which means
// it is pointing somewhere in the root.
root := r.root
if (ref.IsRoot() || ref.HasFragmentOnly) && root == nil && basePath != "" {
if baseRef, erb := NewRef(basePath); erb == nil {
root, _, _, _ = r.load(baseRef.GetURL())
}
}
if (ref.IsRoot() || ref.HasFragmentOnly) && root != nil {
data = root
} else {
baseRef := normalizeFileRef(ref, basePath)
debugLog("current ref is: %s", ref.String())
debugLog("current ref normalized file: %s", baseRef.String())
data, _, _, err = r.load(baseRef.GetURL())
if err != nil {
return err
}
}
res = data
if ref.String() != "" {
res, _, err = ref.GetPointer().Get(data)
if err != nil {
return err
}
}
return swag.DynamicJSONToStruct(res, target)
}
func (r *schemaLoader) load(refURL *url.URL) (interface{}, url.URL, bool, error) {
debugLog("loading schema from url: %s", refURL)
toFetch := *refURL
toFetch.Fragment = ""
normalized := normalizeAbsPath(toFetch.String())
data, fromCache := r.cache.Get(normalized)
if !fromCache {
b, err := r.loadDoc(normalized)
if err != nil {
return nil, url.URL{}, false, err
}
if err := json.Unmarshal(b, &data); err != nil {
return nil, url.URL{}, false, err
}
r.cache.Set(normalized, data)
}
return data, toFetch, fromCache, nil
}
// isCircular detects cycles in sequences of $ref.
// It relies on a private context (which needs not be locked).
func (r *schemaLoader) isCircular(ref *Ref, basePath string, parentRefs ...string) (foundCycle bool) {
normalizedRef := normalizePaths(ref.String(), basePath)
if _, ok := r.context.circulars[normalizedRef]; ok {
// circular $ref has been already detected in another explored cycle
foundCycle = true
return
}
foundCycle = swag.ContainsStringsCI(parentRefs, normalizedRef)
if foundCycle {
r.context.circulars[normalizedRef] = true
}
return
}
// Resolve resolves a reference against basePath and stores the result in target
// Resolve is not in charge of following references, it only resolves ref by following its URL
// if the schema that ref is referring to has more refs in it. Resolve doesn't resolve them
// if basePath is an empty string, ref is resolved against the root schema stored in the schemaLoader struct
func (r *schemaLoader) Resolve(ref *Ref, target interface{}, basePath string) error {
return r.resolveRef(ref, target, basePath)
}
func (r *schemaLoader) deref(input interface{}, parentRefs []string, basePath string) error {
var ref *Ref
switch refable := input.(type) {
case *Schema:
ref = &refable.Ref
case *Parameter:
ref = &refable.Ref
case *Response:
ref = &refable.Ref
case *PathItem:
ref = &refable.Ref
default:
return fmt.Errorf("deref: unsupported type %T", input)
}
curRef := ref.String()
if curRef != "" {
normalizedRef := normalizeFileRef(ref, basePath)
normalizedBasePath := normalizedRef.RemoteURI()
if r.isCircular(normalizedRef, basePath, parentRefs...) {
return nil
}
if err := r.resolveRef(ref, input, basePath); r.shouldStopOnError(err) {
return err
}
// NOTE(fredbi): removed basePath check => needs more testing
if ref.String() != "" && ref.String() != curRef {
parentRefs = append(parentRefs, normalizedRef.String())
return r.deref(input, parentRefs, normalizedBasePath)
}
}
return nil
}
func (r *schemaLoader) shouldStopOnError(err error) bool {
if err != nil && !r.options.ContinueOnError {
return true
}
if err != nil {
log.Println(err)
}
return false
}
func defaultSchemaLoader(
root interface{},
expandOptions *ExpandOptions,
cache ResolutionCache,
context *resolverContext) (*schemaLoader, error) {
if cache == nil {
cache = resCache
}
if expandOptions == nil {
expandOptions = &ExpandOptions{}
}
absBase, _ := absPath(expandOptions.RelativeBase)
if context == nil {
context = newResolverContext(absBase)
}
return &schemaLoader{
root: root,
options: expandOptions,
cache: cache,
context: context,
loadDoc: func(path string) (json.RawMessage, error) {
debugLog("fetching document at %q", path)
return PathLoader(path)
},
}, nil
}

View file

@ -136,8 +136,5 @@ func (s *SecurityScheme) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &s.SecuritySchemeProps); err != nil { if err := json.Unmarshal(data, &s.SecuritySchemeProps); err != nil {
return err return err
} }
if err := json.Unmarshal(data, &s.VendorExtensible); err != nil { return json.Unmarshal(data, &s.VendorExtensible)
return err
}
return nil
} }

View file

@ -24,7 +24,8 @@ import (
) )
// Swagger this is the root document object for the API specification. // Swagger this is the root document object for the API specification.
// It combines what previously was the Resource Listing and API Declaration (version 1.2 and earlier) together into one document. // It combines what previously was the Resource Listing and API Declaration (version 1.2 and earlier)
// together into one document.
// //
// For more information: http://goo.gl/8us55a#swagger-object- // For more information: http://goo.gl/8us55a#swagger-object-
type Swagger struct { type Swagger struct {
@ -68,16 +69,21 @@ func (s *Swagger) UnmarshalJSON(data []byte) error {
} }
// SwaggerProps captures the top-level properties of an Api specification // SwaggerProps captures the top-level properties of an Api specification
//
// NOTE: validation rules
// - the scheme, when present must be from [http, https, ws, wss]
// - BasePath must start with a leading "/"
// - Paths is required
type SwaggerProps struct { type SwaggerProps struct {
ID string `json:"id,omitempty"` ID string `json:"id,omitempty"`
Consumes []string `json:"consumes,omitempty"` Consumes []string `json:"consumes,omitempty"`
Produces []string `json:"produces,omitempty"` Produces []string `json:"produces,omitempty"`
Schemes []string `json:"schemes,omitempty"` // the scheme, when present must be from [http, https, ws, wss] Schemes []string `json:"schemes,omitempty"`
Swagger string `json:"swagger,omitempty"` Swagger string `json:"swagger,omitempty"`
Info *Info `json:"info,omitempty"` Info *Info `json:"info,omitempty"`
Host string `json:"host,omitempty"` Host string `json:"host,omitempty"`
BasePath string `json:"basePath,omitempty"` // must start with a leading "/" BasePath string `json:"basePath,omitempty"`
Paths *Paths `json:"paths"` // required Paths *Paths `json:"paths"`
Definitions Definitions `json:"definitions,omitempty"` Definitions Definitions `json:"definitions,omitempty"`
Parameters map[string]Parameter `json:"parameters,omitempty"` Parameters map[string]Parameter `json:"parameters,omitempty"`
Responses map[string]Response `json:"responses,omitempty"` Responses map[string]Response `json:"responses,omitempty"`
@ -244,9 +250,9 @@ func (s *StringOrArray) UnmarshalJSON(data []byte) error {
if single == nil { if single == nil {
return nil return nil
} }
switch single.(type) { switch v := single.(type) {
case string: case string:
*s = StringOrArray([]string{single.(string)}) *s = StringOrArray([]string{v})
return nil return nil
default: default:
return fmt.Errorf("only string or array is allowed, not %T", single) return fmt.Errorf("only string or array is allowed, not %T", single)

View file

@ -30,10 +30,11 @@ type TagProps struct {
// NewTag creates a new tag // NewTag creates a new tag
func NewTag(name, description string, externalDocs *ExternalDocumentation) Tag { func NewTag(name, description string, externalDocs *ExternalDocumentation) Tag {
return Tag{TagProps: TagProps{description, name, externalDocs}} return Tag{TagProps: TagProps{Description: description, Name: name, ExternalDocs: externalDocs}}
} }
// Tag allows adding meta data to a single tag that is used by the [Operation Object](http://goo.gl/8us55a#operationObject). // Tag allows adding meta data to a single tag that is used by the
// [Operation Object](http://goo.gl/8us55a#operationObject).
// It is not mandatory to have a Tag Object per tag used there. // It is not mandatory to have a Tag Object per tag used there.
// //
// For more information: http://goo.gl/8us55a#tagObject // For more information: http://goo.gl/8us55a#tagObject

174
vendor/github.com/go-openapi/spec/unused.go generated vendored Normal file
View file

@ -0,0 +1,174 @@
// Copyright 2015 go-swagger maintainers
//
// 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.
package spec
/*
import (
"net/url"
"os"
"path"
"path/filepath"
"github.com/go-openapi/jsonpointer"
)
// Some currently unused functions and definitions that
// used to be part of the expander.
// Moved here for the record and possible future reuse
var (
idPtr, _ = jsonpointer.New("/id")
refPtr, _ = jsonpointer.New("/$ref")
)
func idFromNode(node interface{}) (*Ref, error) {
if idValue, _, err := idPtr.Get(node); err == nil {
if refStr, ok := idValue.(string); ok && refStr != "" {
idRef, err := NewRef(refStr)
if err != nil {
return nil, err
}
return &idRef, nil
}
}
return nil, nil
}
func nextRef(startingNode interface{}, startingRef *Ref, ptr *jsonpointer.Pointer) *Ref {
if startingRef == nil {
return nil
}
if ptr == nil {
return startingRef
}
ret := startingRef
var idRef *Ref
node := startingNode
for _, tok := range ptr.DecodedTokens() {
node, _, _ = jsonpointer.GetForToken(node, tok)
if node == nil {
break
}
idRef, _ = idFromNode(node)
if idRef != nil {
nw, err := ret.Inherits(*idRef)
if err != nil {
break
}
ret = nw
}
refRef, _, _ := refPtr.Get(node)
if refRef != nil {
var rf Ref
switch value := refRef.(type) {
case string:
rf, _ = NewRef(value)
}
nw, err := ret.Inherits(rf)
if err != nil {
break
}
nwURL := nw.GetURL()
if nwURL.Scheme == "file" || (nwURL.Scheme == "" && nwURL.Host == "") {
nwpt := filepath.ToSlash(nwURL.Path)
if filepath.IsAbs(nwpt) {
_, err := os.Stat(nwpt)
if err != nil {
nwURL.Path = filepath.Join(".", nwpt)
}
}
}
ret = nw
}
}
return ret
}
// basePathFromSchemaID returns a new basePath based on an existing basePath and a schema ID
func basePathFromSchemaID(oldBasePath, id string) string {
u, err := url.Parse(oldBasePath)
if err != nil {
panic(err)
}
uid, err := url.Parse(id)
if err != nil {
panic(err)
}
if path.IsAbs(uid.Path) {
return id
}
u.Path = path.Join(path.Dir(u.Path), uid.Path)
return u.String()
}
*/
// type ExtraSchemaProps map[string]interface{}
// // JSONSchema represents a structure that is a json schema draft 04
// type JSONSchema struct {
// SchemaProps
// ExtraSchemaProps
// }
// // MarshalJSON marshal this to JSON
// func (s JSONSchema) MarshalJSON() ([]byte, error) {
// b1, err := json.Marshal(s.SchemaProps)
// if err != nil {
// return nil, err
// }
// b2, err := s.Ref.MarshalJSON()
// if err != nil {
// return nil, err
// }
// b3, err := s.Schema.MarshalJSON()
// if err != nil {
// return nil, err
// }
// b4, err := json.Marshal(s.ExtraSchemaProps)
// if err != nil {
// return nil, err
// }
// return swag.ConcatJSON(b1, b2, b3, b4), nil
// }
// // UnmarshalJSON marshal this from JSON
// func (s *JSONSchema) UnmarshalJSON(data []byte) error {
// var sch JSONSchema
// if err := json.Unmarshal(data, &sch.SchemaProps); err != nil {
// return err
// }
// if err := json.Unmarshal(data, &sch.Ref); err != nil {
// return err
// }
// if err := json.Unmarshal(data, &sch.Schema); err != nil {
// return err
// }
// if err := json.Unmarshal(data, &sch.ExtraSchemaProps); err != nil {
// return err
// }
// *s = sch
// return nil
// }

View file

@ -18,3 +18,5 @@ linters:
disable: disable:
- maligned - maligned
- lll - lll
- gochecknoinits
- gochecknoglobals

View file

@ -68,15 +68,16 @@ func WriteJSON(data interface{}) ([]byte, error) {
// ReadJSON reads json data, prefers finding an appropriate interface to short-circuit the unmarshaller // ReadJSON reads json data, prefers finding an appropriate interface to short-circuit the unmarshaller
// so it takes the fastes option available // so it takes the fastes option available
func ReadJSON(data []byte, value interface{}) error { func ReadJSON(data []byte, value interface{}) error {
trimmedData := bytes.Trim(data, "\x00")
if d, ok := value.(ejUnmarshaler); ok { if d, ok := value.(ejUnmarshaler); ok {
jl := &jlexer.Lexer{Data: data} jl := &jlexer.Lexer{Data: trimmedData}
d.UnmarshalEasyJSON(jl) d.UnmarshalEasyJSON(jl)
return jl.Error() return jl.Error()
} }
if d, ok := value.(json.Unmarshaler); ok { if d, ok := value.(json.Unmarshaler); ok {
return d.UnmarshalJSON(data) return d.UnmarshalJSON(trimmedData)
} }
return json.Unmarshal(data, value) return json.Unmarshal(trimmedData, value)
} }
// DynamicJSONToStruct converts an untyped json structure into a struct // DynamicJSONToStruct converts an untyped json structure into a struct

View file

@ -1,3 +1,17 @@
// Copyright 2015 go-swagger maintainers
//
// 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.
package swag package swag
import ( import (

View file

@ -1,3 +1,17 @@
// Copyright 2015 go-swagger maintainers
//
// 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.
// +build go1.8 // +build go1.8
package swag package swag

View file

@ -1,3 +1,17 @@
// Copyright 2015 go-swagger maintainers
//
// 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.
// +build go1.9 // +build go1.9
package swag package swag
@ -48,6 +62,6 @@ func (m *indexOfInitialisms) sorted() (result []string) {
result = append(result, k) result = append(result, k)
return true return true
}) })
sort.Sort(sort.Reverse(byLength(result))) sort.Sort(sort.Reverse(byInitialism(result)))
return return
} }

View file

@ -1,3 +1,17 @@
// Copyright 2015 go-swagger maintainers
//
// 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.
// +build !go1.8 // +build !go1.8
package swag package swag

View file

@ -1,3 +1,17 @@
// Copyright 2015 go-swagger maintainers
//
// 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.
// +build !go1.9 // +build !go1.9
package swag package swag
@ -50,6 +64,6 @@ func (m *indexOfInitialisms) sorted() (result []string) {
for k := range m.index { for k := range m.index {
result = append(result, k) result = append(result, k)
} }
sort.Sort(sort.Reverse(byLength(result))) sort.Sort(sort.Reverse(byInitialism(result)))
return return
} }

View file

@ -33,6 +33,12 @@ var once sync.Once
var isInitialism func(string) bool var isInitialism func(string) bool
var (
splitRex1 *regexp.Regexp
splitRex2 *regexp.Regexp
splitReplacer *strings.Replacer
)
func init() { func init() {
// Taken from https://github.com/golang/lint/blob/3390df4df2787994aea98de825b964ac7944b817/lint.go#L732-L769 // Taken from https://github.com/golang/lint/blob/3390df4df2787994aea98de825b964ac7944b817/lint.go#L732-L769
var configuredInitialisms = map[string]bool{ var configuredInitialisms = map[string]bool{
@ -153,49 +159,54 @@ func SplitByFormat(data, format string) []string {
return result return result
} }
type byLength []string type byInitialism []string
func (s byLength) Len() int { func (s byInitialism) Len() int {
return len(s) return len(s)
} }
func (s byLength) Swap(i, j int) { func (s byInitialism) Swap(i, j int) {
s[i], s[j] = s[j], s[i] s[i], s[j] = s[j], s[i]
} }
func (s byLength) Less(i, j int) bool { func (s byInitialism) Less(i, j int) bool {
return len(s[i]) < len(s[j]) if len(s[i]) != len(s[j]) {
return len(s[i]) < len(s[j])
}
return strings.Compare(s[i], s[j]) > 0
} }
// Prepares strings by splitting by caps, spaces, dashes, and underscore // Prepares strings by splitting by caps, spaces, dashes, and underscore
func split(str string) []string { func split(str string) []string {
repl := strings.NewReplacer( // check if consecutive single char things make up an initialism
"@", "At ", once.Do(func() {
"&", "And ", splitRex1 = regexp.MustCompile(`(\p{Lu})`)
"|", "Pipe ", splitRex2 = regexp.MustCompile(`(\pL|\pM|\pN|\p{Pc})+`)
"$", "Dollar ", splitReplacer = strings.NewReplacer(
"!", "Bang ", "@", "At ",
"-", " ", "&", "And ",
"_", " ", "|", "Pipe ",
) "$", "Dollar ",
"!", "Bang ",
rex1 := regexp.MustCompile(`(\p{Lu})`) "-", " ",
rex2 := regexp.MustCompile(`(\pL|\pM|\pN|\p{Pc})+`) "_", " ",
)
ensureSorted()
})
str = trim(str) str = trim(str)
// Convert dash and underscore to spaces // Convert dash and underscore to spaces
str = repl.Replace(str) str = splitReplacer.Replace(str)
// Split when uppercase is found (needed for Snake) // Split when uppercase is found (needed for Snake)
str = rex1.ReplaceAllString(str, " $1") str = splitRex1.ReplaceAllString(str, " $1")
// check if consecutive single char things make up an initialism
once.Do(ensureSorted)
for _, k := range initialisms { for _, k := range initialisms {
str = strings.Replace(str, rex1.ReplaceAllString(k, " $1"), " "+k, -1) str = strings.Replace(str, splitRex1.ReplaceAllString(k, " $1"), " "+k, -1)
} }
// Get the final list of words // Get the final list of words
//words = rex2.FindAllString(str, -1) //words = rex2.FindAllString(str, -1)
return rex2.FindAllString(str, -1) return splitRex2.FindAllString(str, -1)
} }
// Removes leading whitespaces // Removes leading whitespaces
@ -215,7 +226,7 @@ func lower(str string) string {
// Camelize an uppercased word // Camelize an uppercased word
func Camelize(word string) (camelized string) { func Camelize(word string) (camelized string) {
for pos, ru := range word { for pos, ru := range []rune(word) {
if pos > 0 { if pos > 0 {
camelized += string(unicode.ToLower(ru)) camelized += string(unicode.ToLower(ru))
} else { } else {
@ -271,7 +282,7 @@ func ToHumanNameTitle(name string) string {
for _, w := range in { for _, w := range in {
uw := upper(w) uw := upper(w)
if !isInitialism(uw) { if !isInitialism(uw) {
out = append(out, upper(w[:1])+lower(w[1:])) out = append(out, Camelize(w))
} else { } else {
out = append(out, w) out = append(out, w)
} }
@ -289,7 +300,7 @@ func ToJSONName(name string) string {
out = append(out, lower(w)) out = append(out, lower(w))
continue continue
} }
out = append(out, upper(w[:1])+lower(w[1:])) out = append(out, Camelize(w))
} }
return strings.Join(out, "") return strings.Join(out, "")
} }
@ -315,19 +326,15 @@ func ToGoName(name string) string {
uw := upper(w) uw := upper(w)
mod := int(math.Min(float64(len(uw)), 2)) mod := int(math.Min(float64(len(uw)), 2))
if !isInitialism(uw) && !isInitialism(uw[:len(uw)-mod]) { if !isInitialism(uw) && !isInitialism(uw[:len(uw)-mod]) {
uw = upper(w[:1]) + lower(w[1:]) uw = Camelize(w)
} }
out = append(out, uw) out = append(out, uw)
} }
result := strings.Join(out, "") result := strings.Join(out, "")
if len(result) > 0 { if len(result) > 0 {
ud := upper(result[:1]) if !unicode.IsUpper([]rune(result)[0]) {
ru := []rune(ud) result = "X" + result
if unicode.IsUpper(ru[0]) {
result = ud + result[1:]
} else {
result = "X" + ud + result[1:]
} }
} }
return result return result

View file

@ -22,7 +22,6 @@ import (
"github.com/mailru/easyjson/jlexer" "github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter" "github.com/mailru/easyjson/jwriter"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )

View file

@ -5,8 +5,6 @@ services:
- redis-server - redis-server
go: go:
- 1.7.x
- 1.8.x
- 1.9.x - 1.9.x
- 1.10.x - 1.10.x
- 1.11.x - 1.11.x

View file

@ -3,6 +3,8 @@ all: testdeps
go test ./... -short -race go test ./... -short -race
env GOOS=linux GOARCH=386 go test ./... env GOOS=linux GOARCH=386 go test ./...
go vet go vet
go get github.com/gordonklaus/ineffassign
ineffassign .
testdeps: testdata/redis/src/redis-server testdeps: testdata/redis/src/redis-server
@ -13,7 +15,7 @@ bench: testdeps
testdata/redis: testdata/redis:
mkdir -p $@ mkdir -p $@
wget -qO- https://github.com/antirez/redis/archive/unstable.tar.gz | tar xvz --strip-components=1 -C $@ wget -qO- https://github.com/antirez/redis/archive/5.0.tar.gz | tar xvz --strip-components=1 -C $@
testdata/redis/src/redis-server: testdata/redis testdata/redis/src/redis-server: testdata/redis
sed -i.bak 's/libjemalloc.a/libjemalloc.a -lrt/g' $</src/Makefile sed -i.bak 's/libjemalloc.a/libjemalloc.a -lrt/g' $</src/Makefile

View file

@ -3,7 +3,6 @@ package redis
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"math" "math"
"math/rand" "math/rand"
@ -18,7 +17,6 @@ import (
"github.com/go-redis/redis/internal/hashtag" "github.com/go-redis/redis/internal/hashtag"
"github.com/go-redis/redis/internal/pool" "github.com/go-redis/redis/internal/pool"
"github.com/go-redis/redis/internal/proto" "github.com/go-redis/redis/internal/proto"
"github.com/go-redis/redis/internal/singleflight"
) )
var errClusterNoNodes = fmt.Errorf("redis: cluster has no nodes") var errClusterNoNodes = fmt.Errorf("redis: cluster has no nodes")
@ -50,6 +48,9 @@ type ClusterOptions struct {
// and Cluster.ReloadState to manually trigger state reloading. // and Cluster.ReloadState to manually trigger state reloading.
ClusterSlots func() ([]ClusterSlot, error) ClusterSlots func() ([]ClusterSlot, error)
// Optional hook that is called when a new node is created.
OnNewNode func(*Client)
// Following options are copied from Options struct. // Following options are copied from Options struct.
OnConnect func(*Conn) error OnConnect func(*Conn) error
@ -166,6 +167,10 @@ func newClusterNode(clOpt *ClusterOptions, addr string) *clusterNode {
go node.updateLatency() go node.updateLatency()
} }
if clOpt.OnNewNode != nil {
clOpt.OnNewNode(node.Client)
}
return &node return &node
} }
@ -237,8 +242,6 @@ type clusterNodes struct {
clusterAddrs []string clusterAddrs []string
closed bool closed bool
nodeCreateGroup singleflight.Group
_generation uint32 // atomic _generation uint32 // atomic
} }
@ -341,11 +344,6 @@ func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) {
return node, nil return node, nil
} }
v, err := c.nodeCreateGroup.Do(addr, func() (interface{}, error) {
node := newClusterNode(c.opt, addr)
return node, nil
})
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
@ -355,15 +353,13 @@ func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) {
node, ok := c.allNodes[addr] node, ok := c.allNodes[addr]
if ok { if ok {
_ = v.(*clusterNode).Close()
return node, err return node, err
} }
node = v.(*clusterNode)
node = newClusterNode(c.opt, addr)
c.allAddrs = appendIfNotExists(c.allAddrs, addr) c.allAddrs = appendIfNotExists(c.allAddrs, addr)
if err == nil { c.clusterAddrs = append(c.clusterAddrs, addr)
c.clusterAddrs = append(c.clusterAddrs, addr)
}
c.allNodes[addr] = node c.allNodes[addr] = node
return node, err return node, err
@ -533,10 +529,12 @@ func (c *clusterState) slotSlaveNode(slot int) (*clusterNode, error) {
n := rand.Intn(len(nodes)-1) + 1 n := rand.Intn(len(nodes)-1) + 1
slave = nodes[n] slave = nodes[n]
if !slave.Loading() { if !slave.Loading() {
break return slave, nil
} }
} }
return slave, nil
// All slaves are loading - use master.
return nodes[0], nil
} }
} }
@ -580,23 +578,12 @@ func (c *clusterState) slotNodes(slot int) []*clusterNode {
return nil return nil
} }
func (c *clusterState) IsConsistent() bool {
if c.nodes.opt.ClusterSlots != nil {
return true
}
return len(c.Masters) <= len(c.Slaves)
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
type clusterStateHolder struct { type clusterStateHolder struct {
load func() (*clusterState, error) load func() (*clusterState, error)
state atomic.Value state atomic.Value
firstErrMu sync.RWMutex
firstErr error
reloading uint32 // atomic reloading uint32 // atomic
} }
@ -607,24 +594,8 @@ func newClusterStateHolder(fn func() (*clusterState, error)) *clusterStateHolder
} }
func (c *clusterStateHolder) Reload() (*clusterState, error) { func (c *clusterStateHolder) Reload() (*clusterState, error) {
state, err := c.reload()
if err != nil {
return nil, err
}
if !state.IsConsistent() {
time.AfterFunc(time.Second, c.LazyReload)
}
return state, nil
}
func (c *clusterStateHolder) reload() (*clusterState, error) {
state, err := c.load() state, err := c.load()
if err != nil { if err != nil {
c.firstErrMu.Lock()
if c.firstErr == nil {
c.firstErr = err
}
c.firstErrMu.Unlock()
return nil, err return nil, err
} }
c.state.Store(state) c.state.Store(state)
@ -638,16 +609,11 @@ func (c *clusterStateHolder) LazyReload() {
go func() { go func() {
defer atomic.StoreUint32(&c.reloading, 0) defer atomic.StoreUint32(&c.reloading, 0)
for { _, err := c.Reload()
state, err := c.reload() if err != nil {
if err != nil { return
return
}
time.Sleep(100 * time.Millisecond)
if state.IsConsistent() {
return
}
} }
time.Sleep(100 * time.Millisecond)
}() }()
} }
@ -660,15 +626,7 @@ func (c *clusterStateHolder) Get() (*clusterState, error) {
} }
return state, nil return state, nil
} }
return c.Reload()
c.firstErrMu.RLock()
err := c.firstErr
c.firstErrMu.RUnlock()
if err != nil {
return nil, err
}
return nil, errors.New("redis: cluster has no state")
} }
func (c *clusterStateHolder) ReloadOrGet() (*clusterState, error) { func (c *clusterStateHolder) ReloadOrGet() (*clusterState, error) {
@ -716,10 +674,6 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient {
c.processTxPipeline = c.defaultProcessTxPipeline c.processTxPipeline = c.defaultProcessTxPipeline
c.init() c.init()
_, _ = c.state.Reload()
_, _ = c.cmdsInfoCache.Get()
if opt.IdleCheckFrequency > 0 { if opt.IdleCheckFrequency > 0 {
go c.reaper(opt.IdleCheckFrequency) go c.reaper(opt.IdleCheckFrequency)
} }
@ -727,17 +681,17 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient {
return c return c
} }
// ReloadState reloads cluster state. It calls ClusterSlots func func (c *ClusterClient) init() {
c.cmdable.setProcessor(c.Process)
}
// ReloadState reloads cluster state. If available it calls ClusterSlots func
// to get cluster slots information. // to get cluster slots information.
func (c *ClusterClient) ReloadState() error { func (c *ClusterClient) ReloadState() error {
_, err := c.state.Reload() _, err := c.state.Reload()
return err return err
} }
func (c *ClusterClient) init() {
c.cmdable.setProcessor(c.Process)
}
func (c *ClusterClient) Context() context.Context { func (c *ClusterClient) Context() context.Context {
if c.ctx != nil { if c.ctx != nil {
return c.ctx return c.ctx
@ -818,6 +772,11 @@ func cmdSlot(cmd Cmder, pos int) int {
} }
func (c *ClusterClient) cmdSlot(cmd Cmder) int { func (c *ClusterClient) cmdSlot(cmd Cmder) int {
args := cmd.Args()
if args[0] == "cluster" && args[1] == "getkeysinslot" {
return args[2].(int)
}
cmdInfo := c.cmdInfo(cmd.Name()) cmdInfo := c.cmdInfo(cmd.Name())
return cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo)) return cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo))
} }
@ -829,7 +788,7 @@ func (c *ClusterClient) cmdSlotAndNode(cmd Cmder) (int, *clusterNode, error) {
} }
cmdInfo := c.cmdInfo(cmd.Name()) cmdInfo := c.cmdInfo(cmd.Name())
slot := cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo)) slot := c.cmdSlot(cmd)
if c.opt.ReadOnly && cmdInfo != nil && cmdInfo.ReadOnly { if c.opt.ReadOnly && cmdInfo != nil && cmdInfo.ReadOnly {
if c.opt.RouteByLatency { if c.opt.RouteByLatency {
@ -890,15 +849,12 @@ func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error {
if err == nil { if err == nil {
break break
} }
if err != Nil {
if internal.IsRetryableError(err, true) {
c.state.LazyReload() c.state.LazyReload()
continue
} }
moved, ask, addr := internal.IsMovedError(err) moved, ask, addr := internal.IsMovedError(err)
if moved || ask { if moved || ask {
c.state.LazyReload()
node, err = c.nodes.GetOrCreate(addr) node, err = c.nodes.GetOrCreate(addr)
if err != nil { if err != nil {
return err return err
@ -906,7 +862,7 @@ func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error {
continue continue
} }
if err == pool.ErrClosed { if err == pool.ErrClosed || internal.IsReadOnlyError(err) {
node, err = c.slotMasterNode(slot) node, err = c.slotMasterNode(slot)
if err != nil { if err != nil {
return err return err
@ -914,6 +870,10 @@ func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error {
continue continue
} }
if internal.IsRetryableError(err, true) {
continue
}
return err return err
} }
@ -978,16 +938,34 @@ func (c *ClusterClient) defaultProcess(cmd Cmder) error {
if err == nil { if err == nil {
break break
} }
if err != Nil {
c.state.LazyReload()
}
// If slave is loading - read from master. // If slave is loading - pick another node.
if c.opt.ReadOnly && internal.IsLoadingError(err) { if c.opt.ReadOnly && internal.IsLoadingError(err) {
node.MarkAsLoading() node.MarkAsLoading()
node = nil
continue
}
var moved bool
var addr string
moved, ask, addr = internal.IsMovedError(err)
if moved || ask {
node, err = c.nodes.GetOrCreate(addr)
if err != nil {
break
}
continue
}
if err == pool.ErrClosed || internal.IsReadOnlyError(err) {
node = nil
continue continue
} }
if internal.IsRetryableError(err, true) { if internal.IsRetryableError(err, true) {
c.state.LazyReload()
// First retry the same node. // First retry the same node.
if attempt == 0 { if attempt == 0 {
continue continue
@ -1001,24 +979,6 @@ func (c *ClusterClient) defaultProcess(cmd Cmder) error {
continue continue
} }
var moved bool
var addr string
moved, ask, addr = internal.IsMovedError(err)
if moved || ask {
c.state.LazyReload()
node, err = c.nodes.GetOrCreate(addr)
if err != nil {
break
}
continue
}
if err == pool.ErrClosed {
node = nil
continue
}
break break
} }
@ -1349,14 +1309,15 @@ func (c *ClusterClient) pipelineProcessCmds(
} }
err = cn.WithReader(c.opt.ReadTimeout, func(rd *proto.Reader) error { err = cn.WithReader(c.opt.ReadTimeout, func(rd *proto.Reader) error {
return c.pipelineReadCmds(rd, cmds, failedCmds) return c.pipelineReadCmds(node, rd, cmds, failedCmds)
}) })
return err return err
} }
func (c *ClusterClient) pipelineReadCmds( func (c *ClusterClient) pipelineReadCmds(
rd *proto.Reader, cmds []Cmder, failedCmds *cmdsMap, node *clusterNode, rd *proto.Reader, cmds []Cmder, failedCmds *cmdsMap,
) error { ) error {
var firstErr error
for _, cmd := range cmds { for _, cmd := range cmds {
err := cmd.readReply(rd) err := cmd.readReply(rd)
if err == nil { if err == nil {
@ -1371,9 +1332,14 @@ func (c *ClusterClient) pipelineReadCmds(
continue continue
} }
return err failedCmds.mu.Lock()
failedCmds.m[node] = append(failedCmds.m[node], cmd)
failedCmds.mu.Unlock()
if firstErr == nil {
firstErr = err
}
} }
return nil return firstErr
} }
func (c *ClusterClient) checkMovedErr( func (c *ClusterClient) checkMovedErr(
@ -1561,40 +1527,46 @@ func (c *ClusterClient) txPipelineReadQueued(
return nil return nil
} }
func (c *ClusterClient) pubSub(channels []string) *PubSub { func (c *ClusterClient) pubSub() *PubSub {
var node *clusterNode var node *clusterNode
pubsub := &PubSub{ pubsub := &PubSub{
opt: c.opt.clientOptions(), opt: c.opt.clientOptions(),
newConn: func(channels []string) (*pool.Conn, error) { newConn: func(channels []string) (*pool.Conn, error) {
if node == nil { if node != nil {
var slot int panic("node != nil")
if len(channels) > 0 {
slot = hashtag.Slot(channels[0])
} else {
slot = -1
}
masterNode, err := c.slotMasterNode(slot)
if err != nil {
return nil, err
}
node = masterNode
} }
return node.Client.newConn()
slot := hashtag.Slot(channels[0])
var err error
node, err = c.slotMasterNode(slot)
if err != nil {
return nil, err
}
cn, err := node.Client.newConn()
if err != nil {
return nil, err
}
return cn, nil
}, },
closeConn: func(cn *pool.Conn) error { closeConn: func(cn *pool.Conn) error {
return node.Client.connPool.CloseConn(cn) err := node.Client.connPool.CloseConn(cn)
node = nil
return err
}, },
} }
pubsub.init() pubsub.init()
return pubsub return pubsub
} }
// Subscribe subscribes the client to the specified channels. // Subscribe subscribes the client to the specified channels.
// Channels can be omitted to create empty subscription. // Channels can be omitted to create empty subscription.
func (c *ClusterClient) Subscribe(channels ...string) *PubSub { func (c *ClusterClient) Subscribe(channels ...string) *PubSub {
pubsub := c.pubSub(channels) pubsub := c.pubSub()
if len(channels) > 0 { if len(channels) > 0 {
_ = pubsub.Subscribe(channels...) _ = pubsub.Subscribe(channels...)
} }
@ -1604,7 +1576,7 @@ func (c *ClusterClient) Subscribe(channels ...string) *PubSub {
// PSubscribe subscribes the client to the given patterns. // PSubscribe subscribes the client to the given patterns.
// Patterns can be omitted to create empty subscription. // Patterns can be omitted to create empty subscription.
func (c *ClusterClient) PSubscribe(channels ...string) *PubSub { func (c *ClusterClient) PSubscribe(channels ...string) *PubSub {
pubsub := c.pubSub(channels) pubsub := c.pubSub()
if len(channels) > 0 { if len(channels) > 0 {
_ = pubsub.PSubscribe(channels...) _ = pubsub.PSubscribe(channels...)
} }

View file

@ -1337,6 +1337,68 @@ func zSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
type ZWithKeyCmd struct {
baseCmd
val ZWithKey
}
var _ Cmder = (*ZWithKeyCmd)(nil)
func NewZWithKeyCmd(args ...interface{}) *ZWithKeyCmd {
return &ZWithKeyCmd{
baseCmd: baseCmd{_args: args},
}
}
func (cmd *ZWithKeyCmd) Val() ZWithKey {
return cmd.val
}
func (cmd *ZWithKeyCmd) Result() (ZWithKey, error) {
return cmd.Val(), cmd.Err()
}
func (cmd *ZWithKeyCmd) String() string {
return cmdString(cmd, cmd.val)
}
func (cmd *ZWithKeyCmd) readReply(rd *proto.Reader) error {
var v interface{}
v, cmd.err = rd.ReadArrayReply(zWithKeyParser)
if cmd.err != nil {
return cmd.err
}
cmd.val = v.(ZWithKey)
return nil
}
// Implements proto.MultiBulkParse
func zWithKeyParser(rd *proto.Reader, n int64) (interface{}, error) {
if n != 3 {
return nil, fmt.Errorf("got %d elements, expected 3", n)
}
var z ZWithKey
var err error
z.Key, err = rd.ReadString()
if err != nil {
return nil, err
}
z.Member, err = rd.ReadString()
if err != nil {
return nil, err
}
z.Score, err = rd.ReadFloatReply()
if err != nil {
return nil, err
}
return z, nil
}
//------------------------------------------------------------------------------
type ScanCmd struct { type ScanCmd struct {
baseCmd baseCmd

View file

@ -166,6 +166,7 @@ type Cmdable interface {
SUnion(keys ...string) *StringSliceCmd SUnion(keys ...string) *StringSliceCmd
SUnionStore(destination string, keys ...string) *IntCmd SUnionStore(destination string, keys ...string) *IntCmd
XAdd(a *XAddArgs) *StringCmd XAdd(a *XAddArgs) *StringCmd
XDel(stream string, ids ...string) *IntCmd
XLen(stream string) *IntCmd XLen(stream string) *IntCmd
XRange(stream, start, stop string) *XMessageSliceCmd XRange(stream, start, stop string) *XMessageSliceCmd
XRangeN(stream, start, stop string, count int64) *XMessageSliceCmd XRangeN(stream, start, stop string, count int64) *XMessageSliceCmd
@ -174,6 +175,7 @@ type Cmdable interface {
XRead(a *XReadArgs) *XStreamSliceCmd XRead(a *XReadArgs) *XStreamSliceCmd
XReadStreams(streams ...string) *XStreamSliceCmd XReadStreams(streams ...string) *XStreamSliceCmd
XGroupCreate(stream, group, start string) *StatusCmd XGroupCreate(stream, group, start string) *StatusCmd
XGroupCreateMkStream(stream, group, start string) *StatusCmd
XGroupSetID(stream, group, start string) *StatusCmd XGroupSetID(stream, group, start string) *StatusCmd
XGroupDestroy(stream, group string) *IntCmd XGroupDestroy(stream, group string) *IntCmd
XGroupDelConsumer(stream, group, consumer string) *IntCmd XGroupDelConsumer(stream, group, consumer string) *IntCmd
@ -185,6 +187,8 @@ type Cmdable interface {
XClaimJustID(a *XClaimArgs) *StringSliceCmd XClaimJustID(a *XClaimArgs) *StringSliceCmd
XTrim(key string, maxLen int64) *IntCmd XTrim(key string, maxLen int64) *IntCmd
XTrimApprox(key string, maxLen int64) *IntCmd XTrimApprox(key string, maxLen int64) *IntCmd
BZPopMax(timeout time.Duration, keys ...string) *ZWithKeyCmd
BZPopMin(timeout time.Duration, keys ...string) *ZWithKeyCmd
ZAdd(key string, members ...Z) *IntCmd ZAdd(key string, members ...Z) *IntCmd
ZAddNX(key string, members ...Z) *IntCmd ZAddNX(key string, members ...Z) *IntCmd
ZAddXX(key string, members ...Z) *IntCmd ZAddXX(key string, members ...Z) *IntCmd
@ -228,6 +232,7 @@ type Cmdable interface {
ClientKillByFilter(keys ...string) *IntCmd ClientKillByFilter(keys ...string) *IntCmd
ClientList() *StringCmd ClientList() *StringCmd
ClientPause(dur time.Duration) *BoolCmd ClientPause(dur time.Duration) *BoolCmd
ClientID() *IntCmd
ConfigGet(parameter string) *SliceCmd ConfigGet(parameter string) *SliceCmd
ConfigResetStat() *StatusCmd ConfigResetStat() *StatusCmd
ConfigSet(parameter, value string) *StatusCmd ConfigSet(parameter, value string) *StatusCmd
@ -265,6 +270,7 @@ type Cmdable interface {
ClusterResetHard() *StatusCmd ClusterResetHard() *StatusCmd
ClusterInfo() *StringCmd ClusterInfo() *StringCmd
ClusterKeySlot(key string) *IntCmd ClusterKeySlot(key string) *IntCmd
ClusterGetKeysInSlot(slot int, count int) *StringSliceCmd
ClusterCountFailureReports(nodeID string) *IntCmd ClusterCountFailureReports(nodeID string) *IntCmd
ClusterCountKeysInSlot(slot int) *IntCmd ClusterCountKeysInSlot(slot int) *IntCmd
ClusterDelSlots(slots ...int) *StatusCmd ClusterDelSlots(slots ...int) *StatusCmd
@ -1337,6 +1343,16 @@ func (c *cmdable) XAdd(a *XAddArgs) *StringCmd {
return cmd return cmd
} }
func (c *cmdable) XDel(stream string, ids ...string) *IntCmd {
args := []interface{}{"xdel", stream}
for _, id := range ids {
args = append(args, id)
}
cmd := NewIntCmd(args...)
c.process(cmd)
return cmd
}
func (c *cmdable) XLen(stream string) *IntCmd { func (c *cmdable) XLen(stream string) *IntCmd {
cmd := NewIntCmd("xlen", stream) cmd := NewIntCmd("xlen", stream)
c.process(cmd) c.process(cmd)
@ -1410,6 +1426,12 @@ func (c *cmdable) XGroupCreate(stream, group, start string) *StatusCmd {
return cmd return cmd
} }
func (c *cmdable) XGroupCreateMkStream(stream, group, start string) *StatusCmd {
cmd := NewStatusCmd("xgroup", "create", stream, group, start, "mkstream")
c.process(cmd)
return cmd
}
func (c *cmdable) XGroupSetID(stream, group, start string) *StatusCmd { func (c *cmdable) XGroupSetID(stream, group, start string) *StatusCmd {
cmd := NewStatusCmd("xgroup", "setid", stream, group, start) cmd := NewStatusCmd("xgroup", "setid", stream, group, start)
c.process(cmd) c.process(cmd)
@ -1431,9 +1453,11 @@ func (c *cmdable) XGroupDelConsumer(stream, group, consumer string) *IntCmd {
type XReadGroupArgs struct { type XReadGroupArgs struct {
Group string Group string
Consumer string Consumer string
Streams []string // List of streams and ids.
Count int64 Streams []string
Block time.Duration Count int64
Block time.Duration
NoAck bool
} }
func (c *cmdable) XReadGroup(a *XReadGroupArgs) *XStreamSliceCmd { func (c *cmdable) XReadGroup(a *XReadGroupArgs) *XStreamSliceCmd {
@ -1445,6 +1469,9 @@ func (c *cmdable) XReadGroup(a *XReadGroupArgs) *XStreamSliceCmd {
if a.Block >= 0 { if a.Block >= 0 {
args = append(args, "block", int64(a.Block/time.Millisecond)) args = append(args, "block", int64(a.Block/time.Millisecond))
} }
if a.NoAck {
args = append(args, "noack")
}
args = append(args, "streams") args = append(args, "streams")
for _, s := range a.Streams { for _, s := range a.Streams {
args = append(args, s) args = append(args, s)
@ -1550,6 +1577,12 @@ type Z struct {
Member interface{} Member interface{}
} }
// ZWithKey represents sorted set member including the name of the key where it was popped.
type ZWithKey struct {
Z
Key string
}
// ZStore is used as an arg to ZInterStore and ZUnionStore. // ZStore is used as an arg to ZInterStore and ZUnionStore.
type ZStore struct { type ZStore struct {
Weights []float64 Weights []float64
@ -1557,6 +1590,34 @@ type ZStore struct {
Aggregate string Aggregate string
} }
// Redis `BZPOPMAX key [key ...] timeout` command.
func (c *cmdable) BZPopMax(timeout time.Duration, keys ...string) *ZWithKeyCmd {
args := make([]interface{}, 1+len(keys)+1)
args[0] = "bzpopmax"
for i, key := range keys {
args[1+i] = key
}
args[len(args)-1] = formatSec(timeout)
cmd := NewZWithKeyCmd(args...)
cmd.setReadTimeout(timeout)
c.process(cmd)
return cmd
}
// Redis `BZPOPMIN key [key ...] timeout` command.
func (c *cmdable) BZPopMin(timeout time.Duration, keys ...string) *ZWithKeyCmd {
args := make([]interface{}, 1+len(keys)+1)
args[0] = "bzpopmin"
for i, key := range keys {
args[1+i] = key
}
args[len(args)-1] = formatSec(timeout)
cmd := NewZWithKeyCmd(args...)
cmd.setReadTimeout(timeout)
c.process(cmd)
return cmd
}
func (c *cmdable) zAdd(a []interface{}, n int, members ...Z) *IntCmd { func (c *cmdable) zAdd(a []interface{}, n int, members ...Z) *IntCmd {
for i, m := range members { for i, m := range members {
a[n+2*i] = m.Score a[n+2*i] = m.Score
@ -2010,6 +2071,24 @@ func (c *cmdable) ClientPause(dur time.Duration) *BoolCmd {
return cmd return cmd
} }
func (c *cmdable) ClientID() *IntCmd {
cmd := NewIntCmd("client", "id")
c.process(cmd)
return cmd
}
func (c *cmdable) ClientUnblock(id int64) *IntCmd {
cmd := NewIntCmd("client", "unblock", id)
c.process(cmd)
return cmd
}
func (c *cmdable) ClientUnblockWithError(id int64) *IntCmd {
cmd := NewIntCmd("client", "unblock", id, "error")
c.process(cmd)
return cmd
}
// ClientSetName assigns a name to the connection. // ClientSetName assigns a name to the connection.
func (c *statefulCmdable) ClientSetName(name string) *BoolCmd { func (c *statefulCmdable) ClientSetName(name string) *BoolCmd {
cmd := NewBoolCmd("client", "setname", name) cmd := NewBoolCmd("client", "setname", name)
@ -2325,6 +2404,12 @@ func (c *cmdable) ClusterKeySlot(key string) *IntCmd {
return cmd return cmd
} }
func (c *cmdable) ClusterGetKeysInSlot(slot int, count int) *StringSliceCmd {
cmd := NewStringSliceCmd("cluster", "getkeysinslot", slot, count)
c.process(cmd)
return cmd
}
func (c *cmdable) ClusterCountFailureReports(nodeID string) *IntCmd { func (c *cmdable) ClusterCountFailureReports(nodeID string) *IntCmd {
cmd := NewIntCmd("cluster", "count-failure-reports", nodeID) cmd := NewIntCmd("cluster", "count-failure-reports", nodeID)
c.process(cmd) c.process(cmd)

View file

@ -47,7 +47,8 @@ func IsBadConn(err error, allowTimeout bool) bool {
return false return false
} }
if IsRedisError(err) { if IsRedisError(err) {
return strings.HasPrefix(err.Error(), "READONLY ") // #790
return IsReadOnlyError(err)
} }
if allowTimeout { if allowTimeout {
if netErr, ok := err.(net.Error); ok && netErr.Timeout() { if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
@ -82,3 +83,7 @@ func IsMovedError(err error) (moved bool, ask bool, addr string) {
func IsLoadingError(err error) bool { func IsLoadingError(err error) bool {
return strings.HasPrefix(err.Error(), "LOADING ") return strings.HasPrefix(err.Error(), "LOADING ")
} }
func IsReadOnlyError(err error) bool {
return strings.HasPrefix(err.Error(), "READONLY ")
}

View file

@ -1,64 +0,0 @@
/*
Copyright 2013 Google Inc.
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.
*/
// Package singleflight provides a duplicate function call suppression
// mechanism.
package singleflight
import "sync"
// call is an in-flight or completed Do call
type call struct {
wg sync.WaitGroup
val interface{}
err error
}
// Group represents a class of work and forms a namespace in which
// units of work can be executed with duplicate suppression.
type Group struct {
mu sync.Mutex // protects m
m map[string]*call // lazily initialized
}
// Do executes and returns the results of the given function, making
// sure that only one execution is in-flight for a given key at a
// time. If a duplicate comes in, the duplicate caller waits for the
// original to complete and receives the same results.
func (g *Group) Do(key string, fn func() (interface{}, error)) (interface{}, error) {
g.mu.Lock()
if g.m == nil {
g.m = make(map[string]*call)
}
if c, ok := g.m[key]; ok {
g.mu.Unlock()
c.wg.Wait()
return c.val, c.err
}
c := new(call)
c.wg.Add(1)
g.m[key] = c
g.mu.Unlock()
c.val, c.err = fn()
c.wg.Done()
g.mu.Lock()
delete(g.m, key)
g.mu.Unlock()
return c.val, c.err
}

View file

@ -14,6 +14,17 @@ import (
"github.com/go-redis/redis/internal/pool" "github.com/go-redis/redis/internal/pool"
) )
// Limiter is the interface of a rate limiter or a circuit breaker.
type Limiter interface {
// Allow returns a nil if operation is allowed or an error otherwise.
// If operation is allowed client must report the result of operation
// whether is a success or a failure.
Allow() error
// ReportResult reports the result of previously allowed operation.
// nil indicates a success, non-nil error indicates a failure.
ReportResult(result error)
}
type Options struct { type Options struct {
// The network type, either tcp or unix. // The network type, either tcp or unix.
// Default is tcp. // Default is tcp.
@ -90,6 +101,9 @@ func (opt *Options) init() {
if opt.Network == "" { if opt.Network == "" {
opt.Network = "tcp" opt.Network = "tcp"
} }
if opt.Addr == "" {
opt.Addr = "localhost:6379"
}
if opt.Dialer == nil { if opt.Dialer == nil {
opt.Dialer = func() (net.Conn, error) { opt.Dialer = func() (net.Conn, error) {
netDialer := &net.Dialer{ netDialer := &net.Dialer{

View file

@ -10,6 +10,7 @@ type pipelineExecer func([]Cmder) error
type Pipeliner interface { type Pipeliner interface {
StatefulCmdable StatefulCmdable
Do(args ...interface{}) *Cmd
Process(cmd Cmder) error Process(cmd Cmder) error
Close() error Close() error
Discard() error Discard() error
@ -31,6 +32,12 @@ type Pipeline struct {
closed bool closed bool
} }
func (c *Pipeline) Do(args ...interface{}) *Cmd {
cmd := NewCmd(args...)
_ = c.Process(cmd)
return cmd
}
// Process queues the cmd for later execution. // Process queues the cmd for later execution.
func (c *Pipeline) Process(cmd Cmder) error { func (c *Pipeline) Process(cmd Cmder) error {
c.mu.Lock() c.mu.Lock()

View file

@ -26,6 +26,7 @@ func SetLogger(logger *log.Logger) {
type baseClient struct { type baseClient struct {
opt *Options opt *Options
connPool pool.Pooler connPool pool.Pooler
limiter Limiter
process func(Cmder) error process func(Cmder) error
processPipeline func([]Cmder) error processPipeline func([]Cmder) error
@ -61,6 +62,24 @@ func (c *baseClient) newConn() (*pool.Conn, error) {
} }
func (c *baseClient) getConn() (*pool.Conn, error) { func (c *baseClient) getConn() (*pool.Conn, error) {
if c.limiter != nil {
err := c.limiter.Allow()
if err != nil {
return nil, err
}
}
cn, err := c._getConn()
if err != nil {
if c.limiter != nil {
c.limiter.ReportResult(err)
}
return nil, err
}
return cn, nil
}
func (c *baseClient) _getConn() (*pool.Conn, error) {
cn, err := c.connPool.Get() cn, err := c.connPool.Get()
if err != nil { if err != nil {
return nil, err return nil, err
@ -78,6 +97,10 @@ func (c *baseClient) getConn() (*pool.Conn, error) {
} }
func (c *baseClient) releaseConn(cn *pool.Conn, err error) { func (c *baseClient) releaseConn(cn *pool.Conn, err error) {
if c.limiter != nil {
c.limiter.ReportResult(err)
}
if internal.IsBadConn(err, false) { if internal.IsBadConn(err, false) {
c.connPool.Remove(cn) c.connPool.Remove(cn)
} else { } else {
@ -86,6 +109,10 @@ func (c *baseClient) releaseConn(cn *pool.Conn, err error) {
} }
func (c *baseClient) releaseConnStrict(cn *pool.Conn, err error) { func (c *baseClient) releaseConnStrict(cn *pool.Conn, err error) {
if c.limiter != nil {
c.limiter.ReportResult(err)
}
if err == nil || internal.IsRedisError(err) { if err == nil || internal.IsRedisError(err) {
c.connPool.Put(cn) c.connPool.Put(cn)
} else { } else {
@ -132,7 +159,7 @@ func (c *baseClient) initConn(cn *pool.Conn) error {
// Do creates a Cmd from the args and processes the cmd. // Do creates a Cmd from the args and processes the cmd.
func (c *baseClient) Do(args ...interface{}) *Cmd { func (c *baseClient) Do(args ...interface{}) *Cmd {
cmd := NewCmd(args...) cmd := NewCmd(args...)
c.Process(cmd) _ = c.Process(cmd)
return cmd return cmd
} }
@ -396,12 +423,12 @@ func (c *Client) WithContext(ctx context.Context) *Client {
if ctx == nil { if ctx == nil {
panic("nil context") panic("nil context")
} }
c2 := c.copy() c2 := c.clone()
c2.ctx = ctx c2.ctx = ctx
return c2 return c2
} }
func (c *Client) copy() *Client { func (c *Client) clone() *Client {
cp := *c cp := *c
cp.init() cp.init()
return &cp return &cp
@ -412,6 +439,11 @@ func (c *Client) Options() *Options {
return c.opt return c.opt
} }
func (c *Client) SetLimiter(l Limiter) *Client {
c.limiter = l
return c
}
type PoolStats pool.Stats type PoolStats pool.Stats
// PoolStats returns connection pool stats. // PoolStats returns connection pool stats.
@ -460,6 +492,30 @@ func (c *Client) pubSub() *PubSub {
// Subscribe subscribes the client to the specified channels. // Subscribe subscribes the client to the specified channels.
// Channels can be omitted to create empty subscription. // Channels can be omitted to create empty subscription.
// Note that this method does not wait on a response from Redis, so the
// subscription may not be active immediately. To force the connection to wait,
// you may call the Receive() method on the returned *PubSub like so:
//
// sub := client.Subscribe(queryResp)
// iface, err := sub.Receive()
// if err != nil {
// // handle error
// }
//
// // Should be *Subscription, but others are possible if other actions have been
// // taken on sub since it was created.
// switch iface.(type) {
// case *Subscription:
// // subscribe succeeded
// case *Message:
// // received first message
// case *Pong:
// // pong received
// default:
// // handle error
// }
//
// ch := sub.Channel()
func (c *Client) Subscribe(channels ...string) *PubSub { func (c *Client) Subscribe(channels ...string) *PubSub {
pubsub := c.pubSub() pubsub := c.pubSub()
if len(channels) > 0 { if len(channels) > 0 {

View file

@ -319,12 +319,12 @@ func (c *ringShards) Close() error {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Ring is a Redis client that uses constistent hashing to distribute // Ring is a Redis client that uses consistent hashing to distribute
// keys across multiple Redis servers (shards). It's safe for // keys across multiple Redis servers (shards). It's safe for
// concurrent use by multiple goroutines. // concurrent use by multiple goroutines.
// //
// Ring monitors the state of each shard and removes dead shards from // Ring monitors the state of each shard and removes dead shards from
// the ring. When shard comes online it is added back to the ring. This // the ring. When a shard comes online it is added back to the ring. This
// gives you maximum availability and partition tolerance, but no // gives you maximum availability and partition tolerance, but no
// consistency between different shards or even clients. Each client // consistency between different shards or even clients. Each client
// uses shards that are available to the client and does not do any // uses shards that are available to the client and does not do any

View file

@ -164,6 +164,24 @@ func (c *SentinelClient) Sentinels(name string) *SliceCmd {
return cmd return cmd
} }
// Failover forces a failover as if the master was not reachable, and without
// asking for agreement to other Sentinels.
func (c *SentinelClient) Failover(name string) *StatusCmd {
cmd := NewStatusCmd("sentinel", "failover", name)
c.Process(cmd)
return cmd
}
// Reset resets all the masters with matching name. The pattern argument is a
// glob-style pattern. The reset process clears any previous state in a master
// (including a failover in progress), and removes every slave and sentinel
// already discovered and associated with the master.
func (c *SentinelClient) Reset(pattern string) *IntCmd {
cmd := NewIntCmd("sentinel", "reset", pattern)
c.Process(cmd)
return cmd
}
type sentinelFailover struct { type sentinelFailover struct {
sentinelAddrs []string sentinelAddrs []string
@ -176,6 +194,7 @@ type sentinelFailover struct {
masterName string masterName string
_masterAddr string _masterAddr string
sentinel *SentinelClient sentinel *SentinelClient
pubsub *PubSub
} }
func (c *sentinelFailover) Close() error { func (c *sentinelFailover) Close() error {
@ -304,13 +323,27 @@ func (c *sentinelFailover) switchMaster(addr string) {
func (c *sentinelFailover) setSentinel(sentinel *SentinelClient) { func (c *sentinelFailover) setSentinel(sentinel *SentinelClient) {
c.discoverSentinels(sentinel) c.discoverSentinels(sentinel)
c.sentinel = sentinel c.sentinel = sentinel
go c.listen(sentinel)
c.pubsub = sentinel.Subscribe("+switch-master")
go c.listen(c.pubsub)
} }
func (c *sentinelFailover) closeSentinel() error { func (c *sentinelFailover) closeSentinel() error {
err := c.sentinel.Close() var firstErr error
err := c.pubsub.Close()
if err != nil && firstErr == err {
firstErr = err
}
c.pubsub = nil
err = c.sentinel.Close()
if err != nil && firstErr == err {
firstErr = err
}
c.sentinel = nil c.sentinel = nil
return err
return firstErr
} }
func (c *sentinelFailover) discoverSentinels(sentinel *SentinelClient) { func (c *sentinelFailover) discoverSentinels(sentinel *SentinelClient) {
@ -335,10 +368,7 @@ func (c *sentinelFailover) discoverSentinels(sentinel *SentinelClient) {
} }
} }
func (c *sentinelFailover) listen(sentinel *SentinelClient) { func (c *sentinelFailover) listen(pubsub *PubSub) {
pubsub := sentinel.Subscribe("+switch-master")
defer pubsub.Close()
ch := pubsub.Channel() ch := pubsub.Channel()
for { for {
msg, ok := <-ch msg, ok := <-ch

View file

@ -29,10 +29,10 @@ func (c *Client) newTx() *Tx {
return &tx return &tx
} }
// Watch prepares a transcaction and marks the keys to be watched // Watch prepares a transaction and marks the keys to be watched
// for conditional execution if there are any keys. // for conditional execution if there are any keys.
// //
// The transaction is automatically closed when the fn exits. // The transaction is automatically closed when fn exits.
func (c *Client) Watch(fn func(*Tx) error, keys ...string) error { func (c *Client) Watch(fn func(*Tx) error, keys ...string) error {
tx := c.newTx() tx := c.newTx()
if len(keys) > 0 { if len(keys) > 0 {

View file

@ -245,6 +245,23 @@ func (b *Builder) Or(cond Cond) *Builder {
return b return b
} }
type insertColsSorter struct {
cols []string
vals []interface{}
}
func (s insertColsSorter) Len() int {
return len(s.cols)
}
func (s insertColsSorter) Swap(i, j int) {
s.cols[i], s.cols[j] = s.cols[j], s.cols[i]
s.vals[i], s.vals[j] = s.vals[j], s.vals[i]
}
func (s insertColsSorter) Less(i, j int) bool {
return s.cols[i] < s.cols[j]
}
// Insert sets insert SQL // Insert sets insert SQL
func (b *Builder) Insert(eq ...interface{}) *Builder { func (b *Builder) Insert(eq ...interface{}) *Builder {
if len(eq) > 0 { if len(eq) > 0 {
@ -275,10 +292,10 @@ func (b *Builder) Insert(eq ...interface{}) *Builder {
} }
if len(b.insertCols) == len(b.insertVals) { if len(b.insertCols) == len(b.insertVals) {
sort.Slice(b.insertVals, func(i, j int) bool { sort.Sort(insertColsSorter{
return b.insertCols[i] < b.insertCols[j] cols: b.insertCols,
vals: b.insertVals,
}) })
sort.Strings(b.insertCols)
} }
b.optype = insertType b.optype = insertType
return b return b

View file

@ -1 +1,6 @@
module "github.com/go-xorm/builder" module github.com/go-xorm/builder
require (
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a
github.com/stretchr/testify v1.3.0
)

9
vendor/github.com/go-xorm/builder/go.sum generated vendored Normal file
View file

@ -0,0 +1,9 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
import ( import (

View file

@ -1,15 +0,0 @@
dependencies:
override:
# './...' is a relative pattern which means all subdirectories
- go get -t -d -v ./...
- go build -v
database:
override:
- mysql -u root -e "CREATE DATABASE core_test DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci"
test:
override:
# './...' is a relative pattern which means all subdirectories
- go test -v -race
- go test -v -race --dbtype=sqlite3

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
import ( import (
@ -41,6 +45,7 @@ type Column struct {
Comment string Comment string
} }
// NewColumn creates a new column
func NewColumn(name, fieldName string, sqlType SQLType, len1, len2 int, nullable bool) *Column { func NewColumn(name, fieldName string, sqlType SQLType, len1, len2 int, nullable bool) *Column {
return &Column{ return &Column{
Name: name, Name: name,
@ -66,7 +71,7 @@ func NewColumn(name, fieldName string, sqlType SQLType, len1, len2 int, nullable
} }
} }
// generate column description string according dialect // String generate column description string according dialect
func (col *Column) String(d Dialect) string { func (col *Column) String(d Dialect) string {
sql := d.QuoteStr() + col.Name + d.QuoteStr() + " " sql := d.QuoteStr() + col.Name + d.QuoteStr() + " "
@ -94,6 +99,7 @@ func (col *Column) String(d Dialect) string {
return sql return sql
} }
// StringNoPk generate column description string according dialect without primary keys
func (col *Column) StringNoPk(d Dialect) string { func (col *Column) StringNoPk(d Dialect) string {
sql := d.QuoteStr() + col.Name + d.QuoteStr() + " " sql := d.QuoteStr() + col.Name + d.QuoteStr() + " "
@ -114,12 +120,13 @@ func (col *Column) StringNoPk(d Dialect) string {
return sql return sql
} }
// return col's filed of struct's value // ValueOf returns column's filed of struct's value
func (col *Column) ValueOf(bean interface{}) (*reflect.Value, error) { func (col *Column) ValueOf(bean interface{}) (*reflect.Value, error) {
dataStruct := reflect.Indirect(reflect.ValueOf(bean)) dataStruct := reflect.Indirect(reflect.ValueOf(bean))
return col.ValueOfV(&dataStruct) return col.ValueOfV(&dataStruct)
} }
// ValueOfV returns column's filed of struct's value accept reflevt value
func (col *Column) ValueOfV(dataStruct *reflect.Value) (*reflect.Value, error) { func (col *Column) ValueOfV(dataStruct *reflect.Value) (*reflect.Value, error) {
var fieldValue reflect.Value var fieldValue reflect.Value
fieldPath := strings.Split(col.FieldName, ".") fieldPath := strings.Split(col.FieldName, ".")

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
// Conversion is an interface. A type implements Conversion will according // Conversion is an interface. A type implements Conversion will according

296
vendor/github.com/go-xorm/core/db.go generated vendored
View file

@ -1,9 +1,13 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
import ( import (
"context"
"database/sql" "database/sql"
"database/sql/driver" "database/sql/driver"
"errors"
"fmt" "fmt"
"reflect" "reflect"
"regexp" "regexp"
@ -68,6 +72,7 @@ type cacheStruct struct {
idx int idx int
} }
// DB is a wrap of sql.DB with extra contents
type DB struct { type DB struct {
*sql.DB *sql.DB
Mapper IMapper Mapper IMapper
@ -75,6 +80,7 @@ type DB struct {
reflectCacheMutex sync.RWMutex reflectCacheMutex sync.RWMutex
} }
// Open opens a database
func Open(driverName, dataSourceName string) (*DB, error) { func Open(driverName, dataSourceName string) (*DB, error) {
db, err := sql.Open(driverName, dataSourceName) db, err := sql.Open(driverName, dataSourceName)
if err != nil { if err != nil {
@ -87,6 +93,7 @@ func Open(driverName, dataSourceName string) (*DB, error) {
}, nil }, nil
} }
// FromDB creates a DB from a sql.DB
func FromDB(db *sql.DB) *DB { func FromDB(db *sql.DB) *DB {
return &DB{ return &DB{
DB: db, DB: db,
@ -108,8 +115,9 @@ func (db *DB) reflectNew(typ reflect.Type) reflect.Value {
return cs.value.Index(cs.idx).Addr() return cs.value.Index(cs.idx).Addr()
} }
func (db *DB) Query(query string, args ...interface{}) (*Rows, error) { // QueryContext overwrites sql.DB.QueryContext
rows, err := db.DB.Query(query, args...) func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) {
rows, err := db.DB.QueryContext(ctx, query, args...)
if err != nil { if err != nil {
if rows != nil { if rows != nil {
rows.Close() rows.Close()
@ -119,161 +127,69 @@ func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
return &Rows{rows, db}, nil return &Rows{rows, db}, nil
} }
func (db *DB) QueryMap(query string, mp interface{}) (*Rows, error) { // Query overwrites sql.DB.Query
func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
return db.QueryContext(context.Background(), query, args...)
}
func (db *DB) QueryMapContext(ctx context.Context, query string, mp interface{}) (*Rows, error) {
query, args, err := MapToSlice(query, mp) query, args, err := MapToSlice(query, mp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return db.Query(query, args...) return db.QueryContext(ctx, query, args...)
} }
func (db *DB) QueryStruct(query string, st interface{}) (*Rows, error) { func (db *DB) QueryMap(query string, mp interface{}) (*Rows, error) {
return db.QueryMapContext(context.Background(), query, mp)
}
func (db *DB) QueryStructContext(ctx context.Context, query string, st interface{}) (*Rows, error) {
query, args, err := StructToSlice(query, st) query, args, err := StructToSlice(query, st)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return db.Query(query, args...) return db.QueryContext(ctx, query, args...)
} }
func (db *DB) QueryRow(query string, args ...interface{}) *Row { func (db *DB) QueryStruct(query string, st interface{}) (*Rows, error) {
rows, err := db.Query(query, args...) return db.QueryStructContext(context.Background(), query, st)
}
func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row {
rows, err := db.QueryContext(ctx, query, args...)
if err != nil { if err != nil {
return &Row{nil, err} return &Row{nil, err}
} }
return &Row{rows, nil} return &Row{rows, nil}
} }
func (db *DB) QueryRowMap(query string, mp interface{}) *Row { func (db *DB) QueryRow(query string, args ...interface{}) *Row {
return db.QueryRowContext(context.Background(), query, args...)
}
func (db *DB) QueryRowMapContext(ctx context.Context, query string, mp interface{}) *Row {
query, args, err := MapToSlice(query, mp) query, args, err := MapToSlice(query, mp)
if err != nil { if err != nil {
return &Row{nil, err} return &Row{nil, err}
} }
return db.QueryRow(query, args...) return db.QueryRowContext(ctx, query, args...)
} }
func (db *DB) QueryRowStruct(query string, st interface{}) *Row { func (db *DB) QueryRowMap(query string, mp interface{}) *Row {
return db.QueryRowMapContext(context.Background(), query, mp)
}
func (db *DB) QueryRowStructContext(ctx context.Context, query string, st interface{}) *Row {
query, args, err := StructToSlice(query, st) query, args, err := StructToSlice(query, st)
if err != nil { if err != nil {
return &Row{nil, err} return &Row{nil, err}
} }
return db.QueryRow(query, args...) return db.QueryRowContext(ctx, query, args...)
} }
type Stmt struct { func (db *DB) QueryRowStruct(query string, st interface{}) *Row {
*sql.Stmt return db.QueryRowStructContext(context.Background(), query, st)
db *DB
names map[string]int
}
func (db *DB) Prepare(query string) (*Stmt, error) {
names := make(map[string]int)
var i int
query = re.ReplaceAllStringFunc(query, func(src string) string {
names[src[1:]] = i
i += 1
return "?"
})
stmt, err := db.DB.Prepare(query)
if err != nil {
return nil, err
}
return &Stmt{stmt, db, names}, nil
}
func (s *Stmt) ExecMap(mp interface{}) (sql.Result, error) {
vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return nil, errors.New("mp should be a map's pointer")
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
}
return s.Stmt.Exec(args...)
}
func (s *Stmt) ExecStruct(st interface{}) (sql.Result, error) {
vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return nil, errors.New("mp should be a map's pointer")
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface()
}
return s.Stmt.Exec(args...)
}
func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
rows, err := s.Stmt.Query(args...)
if err != nil {
return nil, err
}
return &Rows{rows, s.db}, nil
}
func (s *Stmt) QueryMap(mp interface{}) (*Rows, error) {
vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return nil, errors.New("mp should be a map's pointer")
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
}
return s.Query(args...)
}
func (s *Stmt) QueryStruct(st interface{}) (*Rows, error) {
vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return nil, errors.New("mp should be a map's pointer")
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface()
}
return s.Query(args...)
}
func (s *Stmt) QueryRow(args ...interface{}) *Row {
rows, err := s.Query(args...)
return &Row{rows, err}
}
func (s *Stmt) QueryRowMap(mp interface{}) *Row {
vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return &Row{nil, errors.New("mp should be a map's pointer")}
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
}
return s.QueryRow(args...)
}
func (s *Stmt) QueryRowStruct(st interface{}) *Row {
vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return &Row{nil, errors.New("st should be a struct's pointer")}
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface()
}
return s.QueryRow(args...)
} }
var ( var (
@ -282,120 +198,26 @@ var (
// insert into (name) values (?) // insert into (name) values (?)
// insert into (name) values (?name) // insert into (name) values (?name)
func (db *DB) ExecMap(query string, mp interface{}) (sql.Result, error) { func (db *DB) ExecMapContext(ctx context.Context, query string, mp interface{}) (sql.Result, error) {
query, args, err := MapToSlice(query, mp) query, args, err := MapToSlice(query, mp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return db.DB.Exec(query, args...) return db.DB.ExecContext(ctx, query, args...)
}
func (db *DB) ExecMap(query string, mp interface{}) (sql.Result, error) {
return db.ExecMapContext(context.Background(), query, mp)
}
func (db *DB) ExecStructContext(ctx context.Context, query string, st interface{}) (sql.Result, error) {
query, args, err := StructToSlice(query, st)
if err != nil {
return nil, err
}
return db.DB.ExecContext(ctx, query, args...)
} }
func (db *DB) ExecStruct(query string, st interface{}) (sql.Result, error) { func (db *DB) ExecStruct(query string, st interface{}) (sql.Result, error) {
query, args, err := StructToSlice(query, st) return db.ExecStructContext(context.Background(), query, st)
if err != nil {
return nil, err
}
return db.DB.Exec(query, args...)
}
type EmptyScanner struct {
}
func (EmptyScanner) Scan(src interface{}) error {
return nil
}
type Tx struct {
*sql.Tx
db *DB
}
func (db *DB) Begin() (*Tx, error) {
tx, err := db.DB.Begin()
if err != nil {
return nil, err
}
return &Tx{tx, db}, nil
}
func (tx *Tx) Prepare(query string) (*Stmt, error) {
names := make(map[string]int)
var i int
query = re.ReplaceAllStringFunc(query, func(src string) string {
names[src[1:]] = i
i += 1
return "?"
})
stmt, err := tx.Tx.Prepare(query)
if err != nil {
return nil, err
}
return &Stmt{stmt, tx.db, names}, nil
}
func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
// TODO:
return stmt
}
func (tx *Tx) ExecMap(query string, mp interface{}) (sql.Result, error) {
query, args, err := MapToSlice(query, mp)
if err != nil {
return nil, err
}
return tx.Tx.Exec(query, args...)
}
func (tx *Tx) ExecStruct(query string, st interface{}) (sql.Result, error) {
query, args, err := StructToSlice(query, st)
if err != nil {
return nil, err
}
return tx.Tx.Exec(query, args...)
}
func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
rows, err := tx.Tx.Query(query, args...)
if err != nil {
return nil, err
}
return &Rows{rows, tx.db}, nil
}
func (tx *Tx) QueryMap(query string, mp interface{}) (*Rows, error) {
query, args, err := MapToSlice(query, mp)
if err != nil {
return nil, err
}
return tx.Query(query, args...)
}
func (tx *Tx) QueryStruct(query string, st interface{}) (*Rows, error) {
query, args, err := StructToSlice(query, st)
if err != nil {
return nil, err
}
return tx.Query(query, args...)
}
func (tx *Tx) QueryRow(query string, args ...interface{}) *Row {
rows, err := tx.Query(query, args...)
return &Row{rows, err}
}
func (tx *Tx) QueryRowMap(query string, mp interface{}) *Row {
query, args, err := MapToSlice(query, mp)
if err != nil {
return &Row{nil, err}
}
return tx.QueryRow(query, args...)
}
func (tx *Tx) QueryRowStruct(query string, st interface{}) *Row {
query, args, err := StructToSlice(query, st)
if err != nil {
return &Row{nil, err}
}
return tx.QueryRow(query, args...)
} }

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
import ( import (

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
type Driver interface { type Driver interface {

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
import "errors" import "errors"

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
import ( import (

View file

@ -1 +1,7 @@
module "github.com/go-xorm/core" module github.com/go-xorm/core
require (
github.com/go-sql-driver/mysql v1.4.1
github.com/mattn/go-sqlite3 v1.10.0
google.golang.org/appengine v1.4.0 // indirect
)

9
vendor/github.com/go-xorm/core/go.sum generated vendored Normal file
View file

@ -0,0 +1,9 @@
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
type LogLevel int type LogLevel int

View file

@ -1,8 +1,11 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
import ( import (
"fmt" "fmt"
"sort"
"strings" "strings"
) )
@ -46,11 +49,16 @@ func (index *Index) Equal(dst *Index) bool {
if len(index.Cols) != len(dst.Cols) { if len(index.Cols) != len(dst.Cols) {
return false return false
} }
sort.StringSlice(index.Cols).Sort()
sort.StringSlice(dst.Cols).Sort()
for i := 0; i < len(index.Cols); i++ { for i := 0; i < len(index.Cols); i++ {
if index.Cols[i] != dst.Cols[i] { var found bool
for j := 0; j < len(dst.Cols); j++ {
if index.Cols[i] == dst.Cols[j] {
found = true
break
}
}
if !found {
return false return false
} }
} }

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
import ( import (

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
import ( import (

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
import ( import (

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
import ( import (
@ -53,3 +57,10 @@ func convertTime(dest *NullTime, src interface{}) error {
} }
return nil return nil
} }
type EmptyScanner struct {
}
func (EmptyScanner) Scan(src interface{}) error {
return nil
}

165
vendor/github.com/go-xorm/core/stmt.go generated vendored Normal file
View file

@ -0,0 +1,165 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core
import (
"context"
"database/sql"
"errors"
"reflect"
)
type Stmt struct {
*sql.Stmt
db *DB
names map[string]int
}
func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
names := make(map[string]int)
var i int
query = re.ReplaceAllStringFunc(query, func(src string) string {
names[src[1:]] = i
i += 1
return "?"
})
stmt, err := db.DB.PrepareContext(ctx, query)
if err != nil {
return nil, err
}
return &Stmt{stmt, db, names}, nil
}
func (db *DB) Prepare(query string) (*Stmt, error) {
return db.PrepareContext(context.Background(), query)
}
func (s *Stmt) ExecMapContext(ctx context.Context, mp interface{}) (sql.Result, error) {
vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return nil, errors.New("mp should be a map's pointer")
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
}
return s.Stmt.ExecContext(ctx, args...)
}
func (s *Stmt) ExecMap(mp interface{}) (sql.Result, error) {
return s.ExecMapContext(context.Background(), mp)
}
func (s *Stmt) ExecStructContext(ctx context.Context, st interface{}) (sql.Result, error) {
vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return nil, errors.New("mp should be a map's pointer")
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface()
}
return s.Stmt.ExecContext(ctx, args...)
}
func (s *Stmt) ExecStruct(st interface{}) (sql.Result, error) {
return s.ExecStructContext(context.Background(), st)
}
func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error) {
rows, err := s.Stmt.QueryContext(ctx, args...)
if err != nil {
return nil, err
}
return &Rows{rows, s.db}, nil
}
func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
return s.QueryContext(context.Background(), args...)
}
func (s *Stmt) QueryMapContext(ctx context.Context, mp interface{}) (*Rows, error) {
vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return nil, errors.New("mp should be a map's pointer")
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
}
return s.QueryContext(ctx, args...)
}
func (s *Stmt) QueryMap(mp interface{}) (*Rows, error) {
return s.QueryMapContext(context.Background(), mp)
}
func (s *Stmt) QueryStructContext(ctx context.Context, st interface{}) (*Rows, error) {
vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return nil, errors.New("mp should be a map's pointer")
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface()
}
return s.Query(args...)
}
func (s *Stmt) QueryStruct(st interface{}) (*Rows, error) {
return s.QueryStructContext(context.Background(), st)
}
func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row {
rows, err := s.QueryContext(ctx, args...)
return &Row{rows, err}
}
func (s *Stmt) QueryRow(args ...interface{}) *Row {
return s.QueryRowContext(context.Background(), args...)
}
func (s *Stmt) QueryRowMapContext(ctx context.Context, mp interface{}) *Row {
vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return &Row{nil, errors.New("mp should be a map's pointer")}
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
}
return s.QueryRowContext(ctx, args...)
}
func (s *Stmt) QueryRowMap(mp interface{}) *Row {
return s.QueryRowMapContext(context.Background(), mp)
}
func (s *Stmt) QueryRowStructContext(ctx context.Context, st interface{}) *Row {
vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return &Row{nil, errors.New("st should be a struct's pointer")}
}
args := make([]interface{}, len(s.names))
for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface()
}
return s.QueryRowContext(ctx, args...)
}
func (s *Stmt) QueryRowStruct(st interface{}) *Row {
return s.QueryRowStructContext(context.Background(), st)
}

View file

@ -1,3 +1,7 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core package core
import ( import (

Some files were not shown because too many files have changed in this diff Show more