* update github.com/blevesearch/bleve v2.0.2 -> v2.0.3 * github.com/denisenkom/go-mssqldb v0.9.0 -> v0.10.0 * github.com/editorconfig/editorconfig-core-go v2.4.1 -> v2.4.2 * github.com/go-chi/cors v1.1.1 -> v1.2.0 * github.com/go-git/go-billy v5.0.0 -> v5.1.0 * github.com/go-git/go-git v5.2.0 -> v5.3.0 * github.com/go-ldap/ldap v3.2.4 -> v3.3.0 * github.com/go-redis/redis v8.6.0 -> v8.8.2 * github.com/go-sql-driver/mysql v1.5.0 -> v1.6.0 * github.com/go-swagger/go-swagger v0.26.1 -> v0.27.0 * github.com/lib/pq v1.9.0 -> v1.10.1 * github.com/mattn/go-sqlite3 v1.14.6 -> v1.14.7 * github.com/go-testfixtures/testfixtures v3.5.0 -> v3.6.0 * github.com/issue9/identicon v1.0.1 -> v1.2.0 * github.com/klauspost/compress v1.11.8 -> v1.12.1 * github.com/mgechev/revive v1.0.3 -> v1.0.6 * github.com/microcosm-cc/bluemonday v1.0.7 -> v1.0.8 * github.com/niklasfasching/go-org v1.4.0 -> v1.5.0 * github.com/olivere/elastic v7.0.22 -> v7.0.24 * github.com/pelletier/go-toml v1.8.1 -> v1.9.0 * github.com/prometheus/client_golang v1.9.0 -> v1.10.0 * github.com/xanzy/go-gitlab v0.44.0 -> v0.48.0 * github.com/yuin/goldmark v1.3.3 -> v1.3.5 * github.com/6543/go-version v1.2.4 -> v1.3.1 * do github.com/lib/pq v1.10.0 -> v1.10.1 again ...tags/v1.15.0-rc1
@@ -11,81 +11,74 @@ require ( | |||
gitea.com/go-chi/captcha v0.0.0-20210110083842-e7696c336a1e | |||
gitea.com/go-chi/session v0.0.0-20210108030337-0cb48c5ba8ee | |||
gitea.com/lunny/levelqueue v0.3.0 | |||
github.com/Microsoft/go-winio v0.4.16 // indirect | |||
github.com/Microsoft/go-winio v0.4.18 // indirect | |||
github.com/NYTimes/gziphandler v1.1.1 | |||
github.com/PuerkitoBio/goquery v1.5.1 | |||
github.com/RoaringBitmap/roaring v0.5.5 // indirect | |||
github.com/RoaringBitmap/roaring v0.6.0 // indirect | |||
github.com/alecthomas/chroma v0.8.2 | |||
github.com/andybalholm/brotli v1.0.1 // indirect | |||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect | |||
github.com/blevesearch/bleve/v2 v2.0.2 | |||
github.com/blevesearch/bleve/v2 v2.0.3 | |||
github.com/boombuler/barcode v1.0.1 // indirect | |||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect | |||
github.com/caddyserver/certmagic v0.13.0 | |||
github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af // indirect | |||
github.com/chi-middleware/proxy v1.1.1 | |||
github.com/couchbase/go-couchbase v0.0.0-20210224140812-5740cd35f448 // indirect | |||
github.com/couchbase/gomemcached v0.1.2 // indirect | |||
github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401 // indirect | |||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect | |||
github.com/denisenkom/go-mssqldb v0.9.0 | |||
github.com/denisenkom/go-mssqldb v0.10.0 | |||
github.com/dgrijalva/jwt-go v3.2.0+incompatible | |||
github.com/dlclark/regexp2 v1.4.0 // indirect | |||
github.com/dustin/go-humanize v1.0.0 | |||
github.com/editorconfig/editorconfig-core-go/v2 v2.4.1 | |||
github.com/editorconfig/editorconfig-core-go/v2 v2.4.2 | |||
github.com/emirpasic/gods v1.12.0 | |||
github.com/ethantkoenig/rupture v1.0.0 | |||
github.com/gliderlabs/ssh v0.3.2 | |||
github.com/glycerine/go-unsnap-stream v0.0.0-20210130063903-47dfef350d96 // indirect | |||
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect | |||
github.com/go-chi/chi v1.5.4 | |||
github.com/go-chi/cors v1.1.1 | |||
github.com/go-chi/cors v1.2.0 | |||
github.com/go-enry/go-enry/v2 v2.6.1 | |||
github.com/go-git/go-billy/v5 v5.0.0 | |||
github.com/go-git/go-git/v5 v5.2.0 | |||
github.com/go-ldap/ldap/v3 v3.2.4 | |||
github.com/go-openapi/errors v0.20.0 // indirect | |||
github.com/go-openapi/validate v0.20.2 // indirect | |||
github.com/go-redis/redis/v8 v8.6.0 | |||
github.com/go-sql-driver/mysql v1.5.0 | |||
github.com/go-swagger/go-swagger v0.26.1 | |||
github.com/go-testfixtures/testfixtures/v3 v3.5.0 | |||
github.com/go-git/go-billy/v5 v5.1.0 | |||
github.com/go-git/go-git/v5 v5.3.0 | |||
github.com/go-ldap/ldap/v3 v3.3.0 | |||
github.com/go-redis/redis/v8 v8.8.2 | |||
github.com/go-sql-driver/mysql v1.6.0 | |||
github.com/go-swagger/go-swagger v0.27.0 | |||
github.com/go-testfixtures/testfixtures/v3 v3.6.0 | |||
github.com/gobwas/glob v0.2.3 | |||
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28 | |||
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14 | |||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 | |||
github.com/golang/snappy v0.0.3 // indirect | |||
github.com/google/go-github/v32 v32.1.0 | |||
github.com/google/go-querystring v1.1.0 // indirect | |||
github.com/google/uuid v1.2.0 | |||
github.com/gorilla/context v1.1.1 | |||
github.com/gorilla/mux v1.8.0 // indirect | |||
github.com/gorilla/sessions v1.2.1 // indirect | |||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect | |||
github.com/hashicorp/go-retryablehttp v0.6.8 // indirect | |||
github.com/hashicorp/go-version v1.2.1 | |||
github.com/hashicorp/go-version v1.3.1 | |||
github.com/huandu/xstrings v1.3.2 | |||
github.com/imdario/mergo v0.3.11 // indirect | |||
github.com/issue9/assert v1.3.2 // indirect | |||
github.com/issue9/identicon v1.0.1 | |||
github.com/issue9/identicon v1.2.0 | |||
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7 | |||
github.com/json-iterator/go v1.1.10 | |||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 | |||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect | |||
github.com/kevinburke/ssh_config v1.1.0 // indirect | |||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4 | |||
github.com/klauspost/compress v1.11.8 | |||
github.com/klauspost/compress v1.12.1 | |||
github.com/klauspost/pgzip v1.2.5 // indirect | |||
github.com/lafriks/xormstore v1.4.0 | |||
github.com/lib/pq v1.9.0 | |||
github.com/lib/pq v1.10.1 | |||
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 | |||
github.com/mailru/easyjson v0.7.7 // indirect | |||
github.com/markbates/goth v1.67.1 | |||
github.com/mattn/go-isatty v0.0.12 | |||
github.com/mattn/go-runewidth v0.0.10 // indirect | |||
github.com/mattn/go-sqlite3 v1.14.6 | |||
github.com/mattn/go-runewidth v0.0.12 // indirect | |||
github.com/mattn/go-sqlite3 v1.14.7 | |||
github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 | |||
github.com/mgechev/revive v1.0.3 | |||
github.com/mgechev/revive v1.0.6 | |||
github.com/mholt/archiver/v3 v3.5.0 | |||
github.com/microcosm-cc/bluemonday v1.0.7 | |||
github.com/miekg/dns v1.1.41 // indirect | |||
github.com/microcosm-cc/bluemonday v1.0.8 | |||
github.com/miekg/dns v1.1.40 // indirect | |||
github.com/minio/md5-simd v1.1.2 // indirect | |||
github.com/minio/minio-go/v7 v7.0.10 | |||
github.com/minio/sha256-simd v1.0.0 // indirect | |||
@@ -93,28 +86,23 @@ require ( | |||
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect | |||
github.com/msteinert/pam v0.0.0-20201130170657-e61372126161 | |||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 | |||
github.com/niklasfasching/go-org v1.4.0 | |||
github.com/olekukonko/tablewriter v0.0.5 // indirect | |||
github.com/niklasfasching/go-org v1.5.0 | |||
github.com/oliamb/cutter v0.2.2 | |||
github.com/olivere/elastic/v7 v7.0.22 | |||
github.com/pelletier/go-toml v1.8.1 | |||
github.com/olivere/elastic/v7 v7.0.24 | |||
github.com/pelletier/go-toml v1.9.0 | |||
github.com/pierrec/lz4/v4 v4.1.3 // indirect | |||
github.com/pkg/errors v0.9.1 | |||
github.com/pquerna/otp v1.3.0 | |||
github.com/prometheus/client_golang v1.9.0 | |||
github.com/prometheus/common v0.18.0 // indirect | |||
github.com/prometheus/procfs v0.6.0 // indirect | |||
github.com/prometheus/client_golang v1.10.0 | |||
github.com/quasoft/websspi v1.0.0 | |||
github.com/rivo/uniseg v0.2.0 // indirect | |||
github.com/russross/blackfriday/v2 v2.1.0 // indirect | |||
github.com/sergi/go-diff v1.1.0 | |||
github.com/sergi/go-diff v1.2.0 | |||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect | |||
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 | |||
github.com/spf13/afero v1.5.1 // indirect | |||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect | |||
github.com/stretchr/testify v1.7.0 | |||
github.com/syndtr/goleveldb v1.0.0 | |||
github.com/tinylib/msgp v1.1.5 // indirect | |||
github.com/tstranex/u2f v1.0.0 | |||
github.com/ulikunitz/xz v0.5.10 // indirect | |||
github.com/unknwon/com v1.0.1 | |||
@@ -123,10 +111,9 @@ require ( | |||
github.com/unrolled/render v1.1.0 | |||
github.com/urfave/cli v1.22.5 | |||
github.com/willf/bitset v1.1.11 // indirect | |||
github.com/xanzy/go-gitlab v0.44.0 | |||
github.com/xanzy/ssh-agent v0.3.0 // indirect | |||
github.com/xanzy/go-gitlab v0.48.0 | |||
github.com/yohcop/openid-go v1.0.0 | |||
github.com/yuin/goldmark v1.3.3 | |||
github.com/yuin/goldmark v1.3.5 | |||
github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691 | |||
github.com/yuin/goldmark-meta v1.0.0 | |||
go.jolheiser.com/hcaptcha v0.0.4 | |||
@@ -135,7 +122,7 @@ require ( | |||
go.uber.org/zap v1.16.0 // indirect | |||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b | |||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758 | |||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93 | |||
golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78 | |||
golang.org/x/sys v0.0.0-20210421221651-33663a62ff08 | |||
golang.org/x/text v0.3.6 | |||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect | |||
@@ -150,4 +137,4 @@ require ( | |||
xorm.io/xorm v1.0.7 | |||
) | |||
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.2.4 | |||
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1 |
@@ -53,8 +53,8 @@ gitea.com/lunny/levelqueue v0.3.0 h1:MHn1GuSZkxvVEDMyAPqlc7A3cOW+q8RcGhRgH/xtm6I | |||
gitea.com/lunny/levelqueue v0.3.0/go.mod h1:HBqmLbz56JWpfEGG0prskAV97ATNRoj5LDmPicD22hU= | |||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= | |||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= | |||
github.com/6543/go-version v1.2.4 h1:MPsSnqNrM0HwA9tnmWNnsMdQMg4/u4fflARjwomoof4= | |||
github.com/6543/go-version v1.2.4/go.mod h1:oqFAHCwtLVUTLdhQmVZWYvaHXTdsbB4SY85at64SQEo= | |||
github.com/6543/go-version v1.3.1 h1:HvOp+Telns7HWJ2Xo/05YXQSB2bE0WmVgbHqwMPZT4U= | |||
github.com/6543/go-version v1.3.1/go.mod h1:oqFAHCwtLVUTLdhQmVZWYvaHXTdsbB4SY85at64SQEo= | |||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28= | |||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= | |||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= | |||
@@ -64,8 +64,9 @@ github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo | |||
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= | |||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= | |||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= | |||
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= | |||
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= | |||
github.com/Microsoft/go-winio v0.4.18 h1:yjwCO1nhWEShaA5qsmPOBzAOjRCa2PRLsDNZ5yBWXpg= | |||
github.com/Microsoft/go-winio v0.4.18/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= | |||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= | |||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= | |||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= | |||
@@ -77,8 +78,8 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt | |||
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/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= | |||
github.com/RoaringBitmap/roaring v0.5.5 h1:naNqvO1mNnghk2UvcsqnzHDBn9DRbCIRy94GmDTRVTQ= | |||
github.com/RoaringBitmap/roaring v0.5.5/go.mod h1:puNo5VdzwbaIQxSiDIwfXl4Hnc+fbovcX4IW/dSTtUk= | |||
github.com/RoaringBitmap/roaring v0.6.0 h1:tZcn2nJpUrZf+xQY8x+9QY7BxSETMjkdNG4Ts5zahyU= | |||
github.com/RoaringBitmap/roaring v0.6.0/go.mod h1:WZ83fjBF/7uBHi6QoFyfGL4+xuV4Qn+xFkm4+vSzrhE= | |||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= | |||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= | |||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= | |||
@@ -127,12 +128,13 @@ github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:l | |||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= | |||
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= | |||
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= | |||
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg= | |||
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= | |||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= | |||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= | |||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= | |||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= | |||
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= | |||
github.com/aws/aws-sdk-go v1.35.20/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= | |||
github.com/aws/aws-sdk-go v1.38.3/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= | |||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= | |||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= | |||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= | |||
@@ -144,8 +146,8 @@ github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQ | |||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= | |||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= | |||
github.com/blevesearch/bleve/v2 v2.0.1/go.mod h1:OBP2Pktqik8vEiUlGhuWjYx7KiO4zD542+DHqICwM5w= | |||
github.com/blevesearch/bleve/v2 v2.0.2 h1:D93VfhOiR6wALovgjsK5XNPeDRrZQlUEIq4YWFeaiTw= | |||
github.com/blevesearch/bleve/v2 v2.0.2/go.mod h1:ip+4iafiEq2gCY5rJXe87bT6LkF/OJMCjQEYIfTBfW8= | |||
github.com/blevesearch/bleve/v2 v2.0.3 h1:mDrwrsRIA4PDYkfUNjoh5zGECvquuJIA3MJU5ivaO8E= | |||
github.com/blevesearch/bleve/v2 v2.0.3/go.mod h1:ip+4iafiEq2gCY5rJXe87bT6LkF/OJMCjQEYIfTBfW8= | |||
github.com/blevesearch/bleve_index_api v1.0.0 h1:Ds3XeuTxjXCkG6pgIwWDRyooJKNIuOKemnN0N0IkhTU= | |||
github.com/blevesearch/bleve_index_api v1.0.0/go.mod h1:fiwKS0xLEm+gBRgv5mumf0dhgFr2mDgZah1pqv1c1M4= | |||
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo= | |||
@@ -194,6 +196,9 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= | |||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= | |||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= | |||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | |||
github.com/chavacava/garif v0.0.0-20210405163807-87a70f3d418b/go.mod h1:Qjyv4H3//PWVzTeCezG2b9IRn6myJxJSr4TD/xo6ojU= | |||
github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af h1:spmv8nSH9h5oCQf40jt/ufBCt9j0/58u4G+rkeMqXGI= | |||
github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af/go.mod h1:Qjyv4H3//PWVzTeCezG2b9IRn6myJxJSr4TD/xo6ojU= | |||
github.com/chi-middleware/proxy v1.1.1 h1:4HaXUp8o2+bhHr1OhVy+VjN0+L7/07JDcn6v7YrTjrQ= | |||
github.com/chi-middleware/proxy v1.1.1/go.mod h1:jQwMEJct2tz9VmtCELxvnXoMfa+SOdikvbVJVHv/M+0= | |||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= | |||
@@ -248,8 +253,8 @@ 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/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= | |||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= | |||
github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk= | |||
github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= | |||
github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8= | |||
github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= | |||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= | |||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= | |||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= | |||
@@ -270,8 +275,8 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn | |||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= | |||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= | |||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= | |||
github.com/editorconfig/editorconfig-core-go/v2 v2.4.1 h1:ELDiPZji50x20Wvf9FnP4pb7fE3PV/DNhNd6MRlhgfI= | |||
github.com/editorconfig/editorconfig-core-go/v2 v2.4.1/go.mod h1:UHV4+gECABtht7ALQkPdc5gzP77D+4WDUOZAfx8ifx8= | |||
github.com/editorconfig/editorconfig-core-go/v2 v2.4.2 h1:1lkDpSoAaFLrgYTVJ/eNCV+lkDSv/j9Wm0jcvDfVVEo= | |||
github.com/editorconfig/editorconfig-core-go/v2 v2.4.2/go.mod h1:IXeWRVO4LZRoNunhHh/oP6BQvTs94nB2pNvbw32l8tQ= | |||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= | |||
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o= | |||
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= | |||
@@ -308,9 +313,6 @@ github.com/gliderlabs/ssh v0.3.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aev | |||
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= | |||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= | |||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= | |||
github.com/glycerine/go-unsnap-stream v0.0.0-20210130063903-47dfef350d96 h1:rCXyLrgJ598XNj7KTqPzAvwTzlyvI+clqasoNfLQStE= | |||
github.com/glycerine/go-unsnap-stream v0.0.0-20210130063903-47dfef350d96/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= | |||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31 h1:gclg6gY70GLy3PbkQ1AERPfmLMMagS60DKF78eWwLn8= | |||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= | |||
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= | |||
github.com/go-asn1-ber/asn1-ber v1.5.3 h1:u7utq56RUFiynqUzgVMFDymapcOtQ/MZkh3H4QYkxag= | |||
@@ -320,28 +322,29 @@ github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= | |||
github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= | |||
github.com/go-chi/chi/v5 v5.0.1 h1:ALxjCrTf1aflOlkhMnCUP86MubbWFrzB3gkRPReLpTo= | |||
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= | |||
github.com/go-chi/cors v1.1.1 h1:eHuqxsIw89iXcWnWUN8R72JMibABJTN/4IOYI5WERvw= | |||
github.com/go-chi/cors v1.1.1/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VChg1I= | |||
github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE= | |||
github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= | |||
github.com/go-enry/go-enry/v2 v2.6.1 h1:ckFkMVj2NeHpaQDFDiSjanVjNy2IiuMNivhXDB4c5Q0= | |||
github.com/go-enry/go-enry/v2 v2.6.1/go.mod h1:GVzIiAytiS5uT/QiuakK7TF1u4xDab87Y8V5EJRpsIQ= | |||
github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo= | |||
github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4= | |||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= | |||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= | |||
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM= | |||
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= | |||
github.com/go-git/go-billy/v5 v5.1.0 h1:4pl5BV4o7ZG/lterP4S6WzJ6xr49Ba5ET9ygheTYahk= | |||
github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= | |||
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= | |||
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= | |||
github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2JgI= | |||
github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs= | |||
github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc= | |||
github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw= | |||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= | |||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= | |||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= | |||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= | |||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= | |||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= | |||
github.com/go-ldap/ldap/v3 v3.2.4 h1:PFavAq2xTgzo/loE8qNXcQaofAaqIpI4WgaLdv+1l3E= | |||
github.com/go-ldap/ldap/v3 v3.2.4/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg= | |||
github.com/go-ldap/ldap/v3 v3.3.0 h1:lwx+SJpgOHd8tG6SumBQZXCmNX51zM8B1cfxJ5gv4tQ= | |||
github.com/go-ldap/ldap/v3 v3.3.0/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg= | |||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= | |||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= | |||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= | |||
@@ -388,7 +391,6 @@ github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2e | |||
github.com/go-openapi/loads v0.19.6/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hsKvYBNEGVc= | |||
github.com/go-openapi/loads v0.19.7/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hsKvYBNEGVc= | |||
github.com/go-openapi/loads v0.20.0/go.mod h1:2LhKquiE513rN5xC6Aan6lYOSddlL8Mp20AW9kpviM4= | |||
github.com/go-openapi/loads v0.20.1/go.mod h1:/6LfFL8fDvTSX8ypmYXIq3U9Q7nfniSOStW22m864WM= | |||
github.com/go-openapi/loads v0.20.2 h1:z5p5Xf5wujMxS1y8aP+vxwW5qYT2zdJBbXKmQUG3lcc= | |||
github.com/go-openapi/loads v0.20.2/go.mod h1:hTVUotJ+UonAMMZsvakEgmWKgtulweO9vYP2bQYKA/o= | |||
github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= | |||
@@ -397,8 +399,8 @@ github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29g | |||
github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= | |||
github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98= | |||
github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk= | |||
github.com/go-openapi/runtime v0.19.26 h1:K/6PoVNj5WJXUnMk+VEbELeXjtBkCS1UxTDa04tdXE0= | |||
github.com/go-openapi/runtime v0.19.26/go.mod h1:BvrQtn6iVb2QmiVXRsFAm6ZCAZBpbVKFfN6QWCp582M= | |||
github.com/go-openapi/runtime v0.19.27 h1:4zrQCJoP7rqNCUaApDv1MdPkaa5TuPfO05Lq5WLhX9I= | |||
github.com/go-openapi/runtime v0.19.27/go.mod h1:BvrQtn6iVb2QmiVXRsFAm6ZCAZBpbVKFfN6QWCp582M= | |||
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= | |||
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= | |||
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= | |||
@@ -408,7 +410,6 @@ github.com/go-openapi/spec v0.19.8/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHK | |||
github.com/go-openapi/spec v0.19.15/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU= | |||
github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU= | |||
github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ= | |||
github.com/go-openapi/spec v0.20.2/go.mod h1:RW6Xcbs6LOyWLU/mXGdzn2Qc+3aj+ASfI7rvSZh1Vls= | |||
github.com/go-openapi/spec v0.20.3 h1:uH9RQ6vdyPSs2pSy9fL8QPspDF2AMIMPtmK5coSSjtQ= | |||
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg= | |||
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= | |||
@@ -419,8 +420,9 @@ github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6 | |||
github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= | |||
github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= | |||
github.com/go-openapi/strfmt v0.19.11/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= | |||
github.com/go-openapi/strfmt v0.20.0 h1:l2omNtmNbMc39IGptl9BuXBEKcZfS8zjrTsPKTiJiDM= | |||
github.com/go-openapi/strfmt v0.20.0/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= | |||
github.com/go-openapi/strfmt v0.20.1 h1:1VgxvehFne1mbChGeCmZ5pc0LxUf6yaACVSIYAR91Xc= | |||
github.com/go-openapi/strfmt v0.20.1/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk= | |||
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= | |||
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= | |||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= | |||
@@ -429,8 +431,9 @@ github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfT | |||
github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= | |||
github.com/go-openapi/swag v0.19.12/go.mod h1:eFdyEBkTdoAf/9RXBvj4cr1nH7GD8Kzo5HTt47gr72M= | |||
github.com/go-openapi/swag v0.19.13/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= | |||
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= | |||
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= | |||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= | |||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= | |||
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= | |||
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= | |||
github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo= | |||
@@ -443,20 +446,21 @@ github.com/go-openapi/validate v0.20.2/go.mod h1:e7OJoKNgd0twXZwIn0A43tHbvIcr/rZ | |||
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-redis/redis/v8 v8.4.0/go.mod h1:A1tbYoHSa1fXwN+//ljcCYYJeLmVrwL9hbQN45Jdy0M= | |||
github.com/go-redis/redis/v8 v8.6.0 h1:swqbqOrxaPztsj2Hf1p94M3YAgl7hYEpcw21z299hh8= | |||
github.com/go-redis/redis/v8 v8.6.0/go.mod h1:DQ9q4Rk2HtwkrwVrdgmphoOQDMfpvcd/nHEwRsicg8s= | |||
github.com/go-redis/redis/v8 v8.8.2 h1:O/NcHqobw7SEptA0yA6up6spZVFtwE06SXM8rgLtsP8= | |||
github.com/go-redis/redis/v8 v8.8.2/go.mod h1:F7resOH5Kdug49Otu24RjHWwgK7u9AmtqWMnCV1iP5Y= | |||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= | |||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= | |||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= | |||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= | |||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= | |||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= | |||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= | |||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= | |||
github.com/go-swagger/go-swagger v0.26.1 h1:1XUWLnH6hKxHzeKjJfA2gHkSqcT1Zgi4q/PZp2hDdN8= | |||
github.com/go-swagger/go-swagger v0.26.1/go.mod h1:zlf/LHplZpdtU2mYXg9Ajd3+9TgHYltv5f/pEM6LjnI= | |||
github.com/go-swagger/go-swagger v0.27.0 h1:K7+nkBuf4oS1jTBrdvWqYFpqD69V5CN8HamZzCDDhAI= | |||
github.com/go-swagger/go-swagger v0.27.0/go.mod h1:WodZVysInJilkW7e6IRw+dZGp5yW6rlMFZ4cb+THl9A= | |||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0= | |||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0= | |||
github.com/go-testfixtures/testfixtures/v3 v3.5.0 h1:fFJGHhFdcwy48oTLHvr0WRQ09rGiZE+as9ElvbRWS+c= | |||
github.com/go-testfixtures/testfixtures/v3 v3.5.0/go.mod h1:P4L3WxgOsCLbAeUC50qX5rdj1ULZfUMqgCbqah3OH5U= | |||
github.com/go-testfixtures/testfixtures/v3 v3.6.0 h1:fHrJWcZ0TOHA0UcExV0Nwx+5MR9QXVDWYdVfwe4DfmM= | |||
github.com/go-testfixtures/testfixtures/v3 v3.6.0/go.mod h1:YUBpgqvleDRhkx4MQbzdA7A3G5ca2wLtf9bHbDqNaRQ= | |||
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= | |||
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= | |||
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= | |||
@@ -523,8 +527,10 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W | |||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= | |||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= | |||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | |||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= | |||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | |||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= | |||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= | |||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= | |||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | |||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | |||
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | |||
@@ -541,12 +547,14 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ | |||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= | |||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= | |||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||
github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II= | |||
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI= | |||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= | |||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= | |||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= | |||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= | |||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | |||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= | |||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= | |||
@@ -614,7 +622,6 @@ github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrj | |||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= | |||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= | |||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= | |||
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= | |||
github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs= | |||
github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= | |||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= | |||
@@ -637,16 +644,14 @@ github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq | |||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= | |||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= | |||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= | |||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= | |||
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= | |||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= | |||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= | |||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= | |||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= | |||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= | |||
github.com/issue9/assert v1.3.1/go.mod h1:9Ger+iz8X7r1zMYYwEhh++2wMGWcNN2oVI+zIQXxcio= | |||
github.com/issue9/assert v1.3.2 h1:IaTa37u4m1fUuTH9K9ldO5IONKVDXjLiUO1T9vj0OF0= | |||
github.com/issue9/assert v1.3.2/go.mod h1:9Ger+iz8X7r1zMYYwEhh++2wMGWcNN2oVI+zIQXxcio= | |||
github.com/issue9/identicon v1.0.1 h1:pCDfjMDM6xWK0Chxo8Lif+ST/nOEtmXgMITgV1YA9Og= | |||
github.com/issue9/identicon v1.0.1/go.mod h1:UKNVkUFI68RPz/RlLhsAr1aX6bBSaYEWRHVfdjrMUmk= | |||
github.com/issue9/assert v1.4.1 h1:gUtOpMTeaE4JTe9kACma5foOHBvVt1p5XTFrULDwdXI= | |||
github.com/issue9/assert v1.4.1/go.mod h1:Yktk83hAVl1SPSYtd9kjhBizuiBIqUQyj+D5SE2yjVY= | |||
github.com/issue9/identicon v1.2.0 h1:ek+UcTTyMW/G0iNbLOAlrPC13eSzXTWhbJSs8PHhHGQ= | |||
github.com/issue9/identicon v1.2.0/go.mod h1:A9toNT0ky/1WP5iNFyDmrkNiYH6eX3HcN5V6uH0g0ec= | |||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= | |||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= | |||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= | |||
@@ -693,8 +698,9 @@ github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7 h1:g0fAGBisHaE | |||
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= | |||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= | |||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= | |||
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= | |||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= | |||
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= | |||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= | |||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= | |||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= | |||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= | |||
@@ -720,9 +726,9 @@ github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaR | |||
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= | |||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= | |||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= | |||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= | |||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= | |||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= | |||
github.com/kevinburke/ssh_config v1.1.0 h1:pH/t1WS9NzT8go394IqZeJTMHVm6Cr6ZJ6AQ+mdNo/o= | |||
github.com/kevinburke/ssh_config v1.1.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= | |||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4 h1:cTxwSmnaqLoo+4tLukHoB9iqHOu3LmLhRmgUxZo6Vp4= | |||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= | |||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= | |||
@@ -731,8 +737,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o | |||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= | |||
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= | |||
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= | |||
github.com/klauspost/compress v1.11.8 h1:difgzQsp5mdAz9v8lm3P/I+EpDKMU/6uTMw1y1FObuo= | |||
github.com/klauspost/compress v1.11.8/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= | |||
github.com/klauspost/compress v1.12.1 h1:/+xsCsk06wE38cyiqOR/o7U2fSftcH72xD+BQXmja/g= | |||
github.com/klauspost/compress v1.12.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= | |||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= | |||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= | |||
github.com/klauspost/cpuid v1.2.5/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= | |||
@@ -765,10 +771,10 @@ github.com/lestrrat-go/jwx v0.9.0/go.mod h1:iEoxlYfZjvoGpuWwxUz+eR5e6KTJGsaRcy/Y | |||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | |||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | |||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | |||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | |||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= | |||
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8= | |||
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= | |||
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= | |||
github.com/lib/pq v1.10.1 h1:6VXZrLU0jHBYyAqrSPa+MgPfnSvTPuMgK+k0o5kVFWo= | |||
github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= | |||
github.com/libdns/libdns v0.2.0 h1:ewg3ByWrdUrxrje8ChPVMBNcotg7H9LQYg+u5De2RzI= | |||
github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= | |||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= | |||
@@ -780,8 +786,8 @@ github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VOb | |||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= | |||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= | |||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= | |||
github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= | |||
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= | |||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= | |||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= | |||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= | |||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= | |||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= | |||
@@ -810,30 +816,29 @@ github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y | |||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= | |||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= | |||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= | |||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | |||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | |||
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= | |||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= | |||
github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow= | |||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= | |||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= | |||
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= | |||
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= | |||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= | |||
github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA= | |||
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= | |||
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/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 h1:QASJXOGm2RZ5Ardbc86qNFvby9AqkLDibfChMtAg5QM= | |||
github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= | |||
github.com/mgechev/revive v1.0.3 h1:z3FL6IFFN3JKzHYHD8O1ExH9g/4lAGJ5x1+9rPZgsFg= | |||
github.com/mgechev/revive v1.0.3/go.mod h1:POGGZagSo/0frdr7VeAifzS5Uka0d0GPiM35MsTO8nE= | |||
github.com/mgechev/revive v1.0.6 h1:MgRQ3ys2uQCyVjelaDhVs8oSvOPYInzGA/nNGMa+MNU= | |||
github.com/mgechev/revive v1.0.6/go.mod h1:Lj5gIVxjBlH8REa3icEOkdfchwYc291nShzZ4QYWyMo= | |||
github.com/mholt/acmez v0.1.3 h1:J7MmNIk4Qf9b8mAGqAh4XkNeowv3f1zW816yf4zt7Qk= | |||
github.com/mholt/acmez v0.1.3/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM= | |||
github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE= | |||
github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc= | |||
github.com/microcosm-cc/bluemonday v1.0.7 h1:6yAQfk4XT+PI/dk1ZeBp1gr3Q2Hd1DR0O3aEyPUJVTE= | |||
github.com/microcosm-cc/bluemonday v1.0.7/go.mod h1:HOT/6NaBlR0f9XlxD3zolN6Z3N8Lp4pvhp+jLS5ihnI= | |||
github.com/microcosm-cc/bluemonday v1.0.8 h1:JGc6zQRHqlp+UlLrsbUbbp0mOaJLV44vvQmBSU0Sfj0= | |||
github.com/microcosm-cc/bluemonday v1.0.8/go.mod h1:HOT/6NaBlR0f9XlxD3zolN6Z3N8Lp4pvhp+jLS5ihnI= | |||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= | |||
github.com/miekg/dns v1.1.30/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= | |||
github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= | |||
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= | |||
github.com/miekg/dns v1.1.40 h1:pyyPFfGMnciYUk/mXpKkVmeMQjfXqt3FAJ2hy7tPiLA= | |||
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= | |||
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= | |||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= | |||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= | |||
@@ -882,10 +887,9 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi | |||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= | |||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= | |||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= | |||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= | |||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= | |||
github.com/niklasfasching/go-org v1.4.0 h1:qPy4VEdX55f5QcLiaD3X7N/tY5XOgk4y2uEyQa02i7A= | |||
github.com/niklasfasching/go-org v1.4.0/go.mod h1:4FWT4U/Anir9ewjwNpbZIzMjG5RaXFafkyWZNEPRdk8= | |||
github.com/niklasfasching/go-org v1.5.0 h1:V8IwoSPm/d61bceyWFxxnQLtlvNT+CjiYIhtZLdnMF0= | |||
github.com/niklasfasching/go-org v1.5.0/go.mod h1:sSb8ylwnAG+h8MGFDB3R1D5bxf8wA08REfhjShg3kjA= | |||
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= | |||
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ= | |||
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= | |||
@@ -893,15 +897,15 @@ github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= | |||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | |||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= | |||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= | |||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= | |||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= | |||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= | |||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= | |||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= | |||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= | |||
github.com/oliamb/cutter v0.2.2 h1:Lfwkya0HHNU1YLnGv2hTkzHfasrSMkgv4Dn+5rmlk3k= | |||
github.com/oliamb/cutter v0.2.2/go.mod h1:4BenG2/4GuRBDbVm/OPahDVqbrOemzpPiG5mi1iryBU= | |||
github.com/olivere/elastic/v7 v7.0.22 h1:esBA6JJwvYgfms0EVlH7Z+9J4oQ/WUADF2y/nCNDw7s= | |||
github.com/olivere/elastic/v7 v7.0.22/go.mod h1:VDexNy9NjmtAkrjNoI7tImv7FR4tf5zUA3ickqu5Pc8= | |||
github.com/olivere/elastic/v7 v7.0.24 h1:9ZcCQP3Pvgese7TaypYiVAL49sCEphyIwkVxtRf8jb8= | |||
github.com/olivere/elastic/v7 v7.0.24/go.mod h1:OuWmD2DiuYhddWegBKPWQuelVKBLrW0fa/VUYgxuGTY= | |||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | |||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | |||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | |||
@@ -932,12 +936,11 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP | |||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= | |||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= | |||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= | |||
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= | |||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= | |||
github.com/pelletier/go-toml v1.9.0 h1:NOd0BRdOKpPf0SxkL3HxSQOG7rNh+4kl6PHcBPFs7Q0= | |||
github.com/pelletier/go-toml v1.9.0/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= | |||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= | |||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= | |||
github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= | |||
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= | |||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= | |||
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= | |||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= | |||
@@ -953,7 +956,7 @@ github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZ | |||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | |||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | |||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= | |||
github.com/pquerna/cachecontrol v0.0.0-20200921180117-858c6e7e6b7e/go.mod h1:hoLfEwdY11HjRfKFH6KqnPsfxlo3BP6bJehpDv8t6sQ= | |||
github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac/go.mod h1:hoLfEwdY11HjRfKFH6KqnPsfxlo3BP6bJehpDv8t6sQ= | |||
github.com/pquerna/otp v1.3.0 h1:oJV/SkzR33anKXwQU3Of42rL4wbrffP4uvUf1SvS5Xs= | |||
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= | |||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= | |||
@@ -962,8 +965,8 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf | |||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= | |||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= | |||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= | |||
github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU= | |||
github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= | |||
github.com/prometheus/client_golang v1.10.0 h1:/o0BDeWzLWXNZ+4q5gXltUvaMpJqckTa+jTNoB+z4cg= | |||
github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= | |||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | |||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | |||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | |||
@@ -977,7 +980,6 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 | |||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= | |||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= | |||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= | |||
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= | |||
github.com/prometheus/common v0.18.0 h1:WCVKW7aL6LEe1uryfI9dnEc2ZqNB1Fn0ok930v0iL1Y= | |||
github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= | |||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= | |||
@@ -986,7 +988,6 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z | |||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= | |||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= | |||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= | |||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= | |||
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= | |||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= | |||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= | |||
@@ -1016,8 +1017,9 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0 | |||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= | |||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= | |||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= | |||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= | |||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= | |||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= | |||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= | |||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE= | |||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= | |||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk= | |||
@@ -1034,6 +1036,7 @@ github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx | |||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= | |||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= | |||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= | |||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= | |||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= | |||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= | |||
github.com/smartystreets/assertions v1.1.1 h1:T/YLemO5Yp7KPzS+lVtu+WsHn8yoSwTfItdAd1r3cck= | |||
@@ -1048,14 +1051,14 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k | |||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= | |||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= | |||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= | |||
github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= | |||
github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg= | |||
github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= | |||
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= | |||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= | |||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= | |||
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= | |||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= | |||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= | |||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= | |||
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= | |||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= | |||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= | |||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= | |||
@@ -1064,6 +1067,7 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn | |||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= | |||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= | |||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= | |||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= | |||
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= | |||
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= | |||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo= | |||
@@ -1090,15 +1094,12 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP | |||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= | |||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= | |||
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= | |||
github.com/tinylib/msgp v1.1.5 h1:2gXmtWueD2HefZHQe1QOy9HVzmFrLOVvsXwXBQ0ayy0= | |||
github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= | |||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= | |||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= | |||
github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= | |||
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM= | |||
github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ= | |||
github.com/tstranex/u2f v1.0.0/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGBSayo= | |||
github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= | |||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= | |||
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= | |||
github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= | |||
@@ -1123,11 +1124,13 @@ github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv | |||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= | |||
github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE= | |||
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= | |||
github.com/xanzy/go-gitlab v0.44.0 h1:cEiGhqu7EpFGuei2a2etAwB+x6403E5CvpLn35y+GPs= | |||
github.com/xanzy/go-gitlab v0.44.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= | |||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= | |||
github.com/xanzy/go-gitlab v0.48.0 h1:RP9r4pMDIwE2fbtc+QYiC1euDsPGHcAjPkhje4X3QPU= | |||
github.com/xanzy/go-gitlab v0.48.0/go.mod h1:UW8JJbyBbqtOyBYNHRo261IRdHUFJr2m0y0z1xUiu+E= | |||
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= | |||
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= | |||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= | |||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= | |||
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= | |||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= | |||
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= | |||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= | |||
@@ -1136,13 +1139,14 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q | |||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= | |||
github.com/yohcop/openid-go v1.0.0 h1:EciJ7ZLETHR3wOtxBvKXx9RV6eyHZpCaSZ1inbBaUXE= | |||
github.com/yohcop/openid-go v1.0.0/go.mod h1:/408xiwkeItSPJZSTPF7+VtZxPkPrRRpRNK2vjGh6yI= | |||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= | |||
github.com/yuin/goldmark v1.1.22/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
github.com/yuin/goldmark v1.3.3 h1:37BdQwPx8VOSic8eDSWee6QL9mRpZRm9VJp/QugNrW0= | |||
github.com/yuin/goldmark v1.3.3/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= | |||
github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs= | |||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= | |||
github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691 h1:VWSxtAiQNh3zgHJpdpkpVYjTPqRE3P6UZCOPa1nRDio= | |||
github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691/go.mod h1:YLF3kDffRfUH/bTxOxHhV6lxwIB3Vfj91rEwNMS9MXo= | |||
github.com/yuin/goldmark-meta v1.0.0 h1:ScsatUIT2gFS6azqzLGUjgOnELsBOxMXerM3ogdJhAM= | |||
@@ -1164,9 +1168,9 @@ go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS | |||
go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= | |||
go.mongodb.org/mongo-driver v1.4.3/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= | |||
go.mongodb.org/mongo-driver v1.4.4/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= | |||
go.mongodb.org/mongo-driver v1.4.5/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= | |||
go.mongodb.org/mongo-driver v1.4.6 h1:rh7GdYmDrb8AQSkF8yteAus8qYOgOASWDOv1BWqBXkU= | |||
go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= | |||
go.mongodb.org/mongo-driver v1.5.1 h1:9nOVLGDfOaZ9R0tBumx/BcuqkbFpyTCU2r/Po7A2azI= | |||
go.mongodb.org/mongo-driver v1.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw= | |||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= | |||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= | |||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | |||
@@ -1175,15 +1179,16 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | |||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | |||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | |||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= | |||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= | |||
go.opentelemetry.io/otel v0.14.0/go.mod h1:vH5xEuwy7Rts0GNtsCW3HYQoZDY+OmBJ6t1bFGGlxgw= | |||
go.opentelemetry.io/otel v0.17.0 h1:6MKOu8WY4hmfpQ4oQn34u6rYhnf2sWf1LXYO/UFm71U= | |||
go.opentelemetry.io/otel v0.17.0/go.mod h1:Oqtdxmf7UtEvL037ohlgnaYa1h7GtMh0NcSd9eqkC9s= | |||
go.opentelemetry.io/otel/metric v0.17.0 h1:t+5EioN8YFXQ2EH+1j6FHCKMUj+57zIDSnSGr/mWuug= | |||
go.opentelemetry.io/otel/metric v0.17.0/go.mod h1:hUz9lH1rNXyEwWAhIWCMFWKhYtpASgSnObJFnU26dJ0= | |||
go.opentelemetry.io/otel/oteltest v0.17.0 h1:TyAihUowTDLqb4+m5ePAsR71xPJaTBJl4KDArIdi9k4= | |||
go.opentelemetry.io/otel/oteltest v0.17.0/go.mod h1:JT/LGFxPwpN+nlsTiinSYjdIx3hZIGqHCpChcIZmdoE= | |||
go.opentelemetry.io/otel/trace v0.17.0 h1:SBOj64/GAOyWzs5F680yW1ITIfJkm6cJWL2YAvuL9xY= | |||
go.opentelemetry.io/otel/trace v0.17.0/go.mod h1:bIujpqg6ZL6xUTubIUgziI1jSaUPthmabA/ygf/6Cfg= | |||
go.opentelemetry.io/otel v0.19.0 h1:Lenfy7QHRXPZVsw/12CWpxX6d/JkrX8wrx2vO8G80Ng= | |||
go.opentelemetry.io/otel v0.19.0/go.mod h1:j9bF567N9EfomkSidSfmMwIwIBuP37AMAIzVW85OxSg= | |||
go.opentelemetry.io/otel/metric v0.19.0 h1:dtZ1Ju44gkJkYvo+3qGqVXmf88tc+a42edOywypengg= | |||
go.opentelemetry.io/otel/metric v0.19.0/go.mod h1:8f9fglJPRnXuskQmKpnad31lcLJ2VmNNqIsx/uIwBSc= | |||
go.opentelemetry.io/otel/oteltest v0.19.0 h1:YVfA0ByROYqTwOxqHVZYZExzEpfZor+MU1rU+ip2v9Q= | |||
go.opentelemetry.io/otel/oteltest v0.19.0/go.mod h1:tI4yxwh8U21v7JD6R3BcA/2+RBoTKFexE/PJ/nSO7IA= | |||
go.opentelemetry.io/otel/trace v0.19.0 h1:1ucYlenXIDA1OlHVLDZKX0ObXV5RLaq06DtUKz5e5zc= | |||
go.opentelemetry.io/otel/trace v0.19.0/go.mod h1:4IXiNextNOpPnRlI4ryK69mn5iC84bjBWZQA5DXz/qg= | |||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | |||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | |||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= | |||
@@ -1226,7 +1231,7 @@ golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPh | |||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | |||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | |||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | |||
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= | |||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= | |||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg= | |||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= | |||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | |||
@@ -1262,8 +1267,9 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB | |||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||
golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY= | |||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= | |||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
@@ -1318,6 +1324,8 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v | |||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | |||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | |||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | |||
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= | |||
golang.org/x/net v0.0.0-20210331060903-cb1fcc7394e5/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= | |||
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= | |||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758 h1:aEpZnXcAmXkd6AvLb2OPt+EN1Zu/8Ne3pCqPjja5PXY= | |||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= | |||
@@ -1331,8 +1339,9 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ | |||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | |||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | |||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | |||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93 h1:alLDrZkL34Y2bnGHfvC1CYBRBXCXgx8AC2vY4MRtYX4= | |||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | |||
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | |||
golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78 h1:rPRtHfUb0UKZeZ6GH4K4Nt4YRbE9V1u+QZX5upZXqJQ= | |||
golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | |||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
@@ -1343,9 +1352,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ | |||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= | |||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= | |||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
@@ -1358,7 +1366,6 @@ golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5h | |||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/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-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
@@ -1409,20 +1416,19 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w | |||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210421221651-33663a62ff08 h1:qyN5bV+96OX8pL78eXDuz6YlDPzCYgdW74H5yE9BoSU= | |||
golang.org/x/sys v0.0.0-20210421221651-33663a62ff08/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= | |||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= | |||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | |||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||
@@ -1502,9 +1508,7 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc | |||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= | |||
golang.org/x/tools v0.0.0-20200928182047-19e03678916f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= | |||
golang.org/x/tools v0.0.0-20200929161345-d7fc70abf50f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= | |||
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |||
golang.org/x/tools v0.0.0-20201125231158-b5590deeca9b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |||
@@ -1617,16 +1621,19 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 | |||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | |||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | |||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= | |||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= | |||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= | |||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | |||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= | |||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= | |||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= | |||
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/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= | |||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= | |||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= | |||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= | |||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= | |||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | |||
@@ -1651,7 +1658,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= |
@@ -0,0 +1 @@ | |||
* @microsoft/containerplat |
@@ -5,21 +5,14 @@ package winio | |||
import ( | |||
"os" | |||
"runtime" | |||
"syscall" | |||
"unsafe" | |||
) | |||
//sys getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = GetFileInformationByHandleEx | |||
//sys setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = SetFileInformationByHandle | |||
const ( | |||
fileBasicInfo = 0 | |||
fileIDInfo = 0x12 | |||
"golang.org/x/sys/windows" | |||
) | |||
// FileBasicInfo contains file access time and file attributes information. | |||
type FileBasicInfo struct { | |||
CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime | |||
CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime | |||
FileAttributes uint32 | |||
pad uint32 // padding | |||
} | |||
@@ -27,7 +20,7 @@ type FileBasicInfo struct { | |||
// GetFileBasicInfo retrieves times and attributes for a file. | |||
func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { | |||
bi := &FileBasicInfo{} | |||
if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { | |||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { | |||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} | |||
} | |||
runtime.KeepAlive(f) | |||
@@ -36,13 +29,32 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { | |||
// SetFileBasicInfo sets times and attributes for a file. | |||
func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error { | |||
if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { | |||
if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { | |||
return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err} | |||
} | |||
runtime.KeepAlive(f) | |||
return nil | |||
} | |||
// FileStandardInfo contains extended information for the file. | |||
// FILE_STANDARD_INFO in WinBase.h | |||
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_standard_info | |||
type FileStandardInfo struct { | |||
AllocationSize, EndOfFile int64 | |||
NumberOfLinks uint32 | |||
DeletePending, Directory bool | |||
} | |||
// GetFileStandardInfo retrieves ended information for the file. | |||
func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) { | |||
si := &FileStandardInfo{} | |||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil { | |||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} | |||
} | |||
runtime.KeepAlive(f) | |||
return si, nil | |||
} | |||
// FileIDInfo contains the volume serial number and file ID for a file. This pair should be | |||
// unique on a system. | |||
type FileIDInfo struct { | |||
@@ -53,7 +65,7 @@ type FileIDInfo struct { | |||
// GetFileID retrieves the unique (volume, file ID) pair for a file. | |||
func GetFileID(f *os.File) (*FileIDInfo, error) { | |||
fileID := &FileIDInfo{} | |||
if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { | |||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { | |||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} | |||
} | |||
runtime.KeepAlive(f) |
@@ -4,6 +4,6 @@ go 1.12 | |||
require ( | |||
github.com/pkg/errors v0.9.1 | |||
github.com/sirupsen/logrus v1.4.1 | |||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 | |||
github.com/sirupsen/logrus v1.7.0 | |||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c | |||
) |
@@ -1,16 +1,14 @@ | |||
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/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= | |||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | |||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | |||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | |||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | |||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | |||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= | |||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= | |||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | |||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= | |||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= | |||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= | |||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | |||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo= | |||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= | |||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= | |||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
@@ -1,3 +1,5 @@ | |||
// +build windows | |||
package winio | |||
import ( |
@@ -1,3 +1,5 @@ | |||
// +build windows | |||
// Package guid provides a GUID type. The backing structure for a GUID is | |||
// identical to that used by the golang.org/x/sys/windows GUID type. | |||
// There are two main binary encodings used for a GUID, the big-endian encoding, |
@@ -28,8 +28,9 @@ const ( | |||
ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300 | |||
SeBackupPrivilege = "SeBackupPrivilege" | |||
SeRestorePrivilege = "SeRestorePrivilege" | |||
SeBackupPrivilege = "SeBackupPrivilege" | |||
SeRestorePrivilege = "SeRestorePrivilege" | |||
SeSecurityPrivilege = "SeSecurityPrivilege" | |||
) | |||
const ( |
@@ -1,3 +1,3 @@ | |||
package winio | |||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go | |||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go |
@@ -19,6 +19,7 @@ const ( | |||
var ( | |||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) | |||
errERROR_EINVAL error = syscall.EINVAL | |||
) | |||
// errnoErr returns common boxed Errno values, to prevent | |||
@@ -26,7 +27,7 @@ var ( | |||
func errnoErr(e syscall.Errno) error { | |||
switch e { | |||
case 0: | |||
return nil | |||
return errERROR_EINVAL | |||
case errnoERROR_IO_PENDING: | |||
return errERROR_IO_PENDING | |||
} | |||
@@ -37,514 +38,382 @@ func errnoErr(e syscall.Errno) error { | |||
} | |||
var ( | |||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") | |||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll") | |||
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll") | |||
modntdll = windows.NewLazySystemDLL("ntdll.dll") | |||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") | |||
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll") | |||
procCancelIoEx = modkernel32.NewProc("CancelIoEx") | |||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") | |||
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") | |||
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") | |||
procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult") | |||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") | |||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") | |||
procCreateFileW = modkernel32.NewProc("CreateFileW") | |||
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") | |||
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") | |||
procLocalAlloc = modkernel32.NewProc("LocalAlloc") | |||
procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") | |||
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") | |||
procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") | |||
procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") | |||
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") | |||
procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") | |||
procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") | |||
procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") | |||
procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") | |||
procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") | |||
procLocalFree = modkernel32.NewProc("LocalFree") | |||
procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") | |||
procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") | |||
procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle") | |||
procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") | |||
procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") | |||
procRevertToSelf = modadvapi32.NewProc("RevertToSelf") | |||
procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") | |||
procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") | |||
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") | |||
procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") | |||
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") | |||
procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW") | |||
procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") | |||
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") | |||
procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") | |||
procRevertToSelf = modadvapi32.NewProc("RevertToSelf") | |||
procBackupRead = modkernel32.NewProc("BackupRead") | |||
procBackupWrite = modkernel32.NewProc("BackupWrite") | |||
procCancelIoEx = modkernel32.NewProc("CancelIoEx") | |||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") | |||
procCreateFileW = modkernel32.NewProc("CreateFileW") | |||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") | |||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") | |||
procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") | |||
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") | |||
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") | |||
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") | |||
procLocalAlloc = modkernel32.NewProc("LocalAlloc") | |||
procLocalFree = modkernel32.NewProc("LocalFree") | |||
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") | |||
procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") | |||
procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") | |||
procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") | |||
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") | |||
procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult") | |||
procbind = modws2_32.NewProc("bind") | |||
) | |||
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) { | |||
r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) { | |||
var _p0 uint32 | |||
if releaseAll { | |||
_p0 = 1 | |||
} | |||
return | |||
} | |||
func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) { | |||
r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0) | |||
newport = syscall.Handle(r0) | |||
if newport == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize))) | |||
success = r0 != 0 | |||
if true { | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0) | |||
func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) { | |||
r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0) | |||
func convertSidToStringSid(sid *byte, str **uint16) (err error) { | |||
r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { | |||
var _p0 uint32 | |||
if wait { | |||
_p0 = 1 | |||
} else { | |||
_p0 = 0 | |||
func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) { | |||
var _p0 *uint16 | |||
_p0, err = syscall.UTF16PtrFromString(str) | |||
if err != nil { | |||
return | |||
} | |||
r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0) | |||
return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size) | |||
} | |||
func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { | |||
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0) | |||
func getSecurityDescriptorLength(sd uintptr) (len uint32) { | |||
r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0) | |||
len = uint32(r0) | |||
return | |||
} | |||
func impersonateSelf(level uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { | |||
func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { | |||
var _p0 *uint16 | |||
_p0, err = syscall.UTF16PtrFromString(name) | |||
_p0, err = syscall.UTF16PtrFromString(accountName) | |||
if err != nil { | |||
return | |||
} | |||
return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa) | |||
return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse) | |||
} | |||
func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { | |||
r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0) | |||
handle = syscall.Handle(r0) | |||
if handle == syscall.InvalidHandle { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0) | |||
if r1 == 0 { | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { | |||
func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { | |||
var _p0 *uint16 | |||
_p0, err = syscall.UTF16PtrFromString(name) | |||
_p0, err = syscall.UTF16PtrFromString(systemName) | |||
if err != nil { | |||
return | |||
} | |||
return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile) | |||
return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId) | |||
} | |||
func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { | |||
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) | |||
handle = syscall.Handle(r0) | |||
if handle == syscall.InvalidHandle { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0) | |||
if r1 == 0 { | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) { | |||
var _p0 *uint16 | |||
_p0, err = syscall.UTF16PtrFromString(systemName) | |||
if err != nil { | |||
return | |||
} | |||
return | |||
return _lookupPrivilegeName(_p0, luid, buffer, size) | |||
} | |||
func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) | |||
func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func localAlloc(uFlags uint32, length uint32) (ptr uintptr) { | |||
r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0) | |||
ptr = uintptr(r0) | |||
return | |||
func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) { | |||
var _p0 *uint16 | |||
_p0, err = syscall.UTF16PtrFromString(systemName) | |||
if err != nil { | |||
return | |||
} | |||
var _p1 *uint16 | |||
_p1, err = syscall.UTF16PtrFromString(name) | |||
if err != nil { | |||
return | |||
} | |||
return _lookupPrivilegeValue(_p0, _p1, luid) | |||
} | |||
func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { | |||
r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) | |||
status = ntstatus(r0) | |||
func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) { | |||
r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) | |||
if r1 == 0 { | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func rtlNtStatusToDosError(status ntstatus) (winerr error) { | |||
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) | |||
if r0 != 0 { | |||
winerr = syscall.Errno(r0) | |||
func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) { | |||
var _p0 uint32 | |||
if openAsSelf { | |||
_p0 = 1 | |||
} | |||
r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) | |||
if r1 == 0 { | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) { | |||
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0) | |||
status = ntstatus(r0) | |||
func revertToSelf() (err error) { | |||
r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) | |||
if r1 == 0 { | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) { | |||
r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0) | |||
status = ntstatus(r0) | |||
func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { | |||
var _p0 *byte | |||
if len(b) > 0 { | |||
_p0 = &b[0] | |||
} | |||
var _p1 uint32 | |||
if abort { | |||
_p1 = 1 | |||
} | |||
var _p2 uint32 | |||
if processSecurity { | |||
_p2 = 1 | |||
} | |||
r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) | |||
if r1 == 0 { | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { | |||
var _p0 *uint16 | |||
_p0, err = syscall.UTF16PtrFromString(accountName) | |||
if err != nil { | |||
return | |||
func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { | |||
var _p0 *byte | |||
if len(b) > 0 { | |||
_p0 = &b[0] | |||
} | |||
return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse) | |||
var _p1 uint32 | |||
if abort { | |||
_p1 = 1 | |||
} | |||
var _p2 uint32 | |||
if processSecurity { | |||
_p2 = 1 | |||
} | |||
r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) | |||
if r1 == 0 { | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0) | |||
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) { | |||
r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func convertSidToStringSid(sid *byte, str **uint16) (err error) { | |||
r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0) | |||
func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { | |||
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) { | |||
func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { | |||
var _p0 *uint16 | |||
_p0, err = syscall.UTF16PtrFromString(str) | |||
_p0, err = syscall.UTF16PtrFromString(name) | |||
if err != nil { | |||
return | |||
} | |||
return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size) | |||
return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile) | |||
} | |||
func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { | |||
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) | |||
handle = syscall.Handle(r0) | |||
if handle == syscall.InvalidHandle { | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) { | |||
r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0) | |||
newport = syscall.Handle(r0) | |||
if newport == 0 { | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func localFree(mem uintptr) { | |||
syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0) | |||
return | |||
} | |||
func getSecurityDescriptorLength(sd uintptr) (len uint32) { | |||
r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0) | |||
len = uint32(r0) | |||
return | |||
} | |||
func getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { | |||
var _p0 *uint16 | |||
_p0, err = syscall.UTF16PtrFromString(name) | |||
if err != nil { | |||
return | |||
} | |||
return | |||
return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa) | |||
} | |||
func setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { | |||
r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0) | |||
handle = syscall.Handle(r0) | |||
if handle == syscall.InvalidHandle { | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) { | |||
var _p0 uint32 | |||
if releaseAll { | |||
_p0 = 1 | |||
} else { | |||
_p0 = 0 | |||
} | |||
r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize))) | |||
success = r0 != 0 | |||
if true { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
} | |||
func getCurrentThread() (h syscall.Handle) { | |||
r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0) | |||
h = syscall.Handle(r0) | |||
return | |||
} | |||
func impersonateSelf(level uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0) | |||
func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func revertToSelf() (err error) { | |||
r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) | |||
func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) { | |||
var _p0 uint32 | |||
if openAsSelf { | |||
_p0 = 1 | |||
} else { | |||
_p0 = 0 | |||
} | |||
r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) | |||
func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func getCurrentThread() (h syscall.Handle) { | |||
r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0) | |||
h = syscall.Handle(r0) | |||
func localAlloc(uFlags uint32, length uint32) (ptr uintptr) { | |||
r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0) | |||
ptr = uintptr(r0) | |||
return | |||
} | |||
func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) { | |||
var _p0 *uint16 | |||
_p0, err = syscall.UTF16PtrFromString(systemName) | |||
if err != nil { | |||
return | |||
} | |||
var _p1 *uint16 | |||
_p1, err = syscall.UTF16PtrFromString(name) | |||
if err != nil { | |||
return | |||
} | |||
return _lookupPrivilegeValue(_p0, _p1, luid) | |||
func localFree(mem uintptr) { | |||
syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0) | |||
return | |||
} | |||
func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) { | |||
r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) | |||
func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) { | |||
r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) { | |||
var _p0 *uint16 | |||
_p0, err = syscall.UTF16PtrFromString(systemName) | |||
if err != nil { | |||
return | |||
} | |||
return _lookupPrivilegeName(_p0, luid, buffer, size) | |||
} | |||
func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
} | |||
func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { | |||
r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) | |||
status = ntstatus(r0) | |||
return | |||
} | |||
func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { | |||
var _p0 *uint16 | |||
_p0, err = syscall.UTF16PtrFromString(systemName) | |||
if err != nil { | |||
return | |||
} | |||
return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId) | |||
func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) { | |||
r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0) | |||
status = ntstatus(r0) | |||
return | |||
} | |||
func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { | |||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
} | |||
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) { | |||
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0) | |||
status = ntstatus(r0) | |||
return | |||
} | |||
func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { | |||
var _p0 *byte | |||
if len(b) > 0 { | |||
_p0 = &b[0] | |||
} | |||
var _p1 uint32 | |||
if abort { | |||
_p1 = 1 | |||
} else { | |||
_p1 = 0 | |||
} | |||
var _p2 uint32 | |||
if processSecurity { | |||
_p2 = 1 | |||
} else { | |||
_p2 = 0 | |||
} | |||
r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
func rtlNtStatusToDosError(status ntstatus) (winerr error) { | |||
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) | |||
if r0 != 0 { | |||
winerr = syscall.Errno(r0) | |||
} | |||
return | |||
} | |||
func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { | |||
var _p0 *byte | |||
if len(b) > 0 { | |||
_p0 = &b[0] | |||
} | |||
var _p1 uint32 | |||
if abort { | |||
_p1 = 1 | |||
} else { | |||
_p1 = 0 | |||
} | |||
var _p2 uint32 | |||
if processSecurity { | |||
_p2 = 1 | |||
} else { | |||
_p2 = 0 | |||
func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { | |||
var _p0 uint32 | |||
if wait { | |||
_p0 = 1 | |||
} | |||
r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) | |||
r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0) | |||
if r1 == 0 { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} | |||
@@ -552,11 +421,7 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p | |||
func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) { | |||
r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) | |||
if r1 == socketError { | |||
if e1 != 0 { | |||
err = errnoErr(e1) | |||
} else { | |||
err = syscall.EINVAL | |||
} | |||
err = errnoErr(e1) | |||
} | |||
return | |||
} |
@@ -3,4 +3,3 @@ roaring-fuzz.zip | |||
workdir | |||
coverage.out | |||
testdata/all3.classic | |||
testdata/all3.msgp.snappy |
@@ -17,7 +17,7 @@ branches: | |||
only: | |||
- master | |||
script: | |||
- goveralls -v -service travis-ci -ignore arraycontainer_gen.go,bitmapcontainer_gen.go,rle16_gen.go,rle_gen.go,roaringarray_gen.go,rle.go || go test | |||
- goveralls -v -service travis-ci -ignore rle16_gen.go,rle_gen.go,rle.go || go test | |||
- go test -race -run TestConcurrent* | |||
- go build -tags appengine | |||
- go test -tags appengine |
@@ -97,10 +97,6 @@ nuke: | |||
rm -rf ./target | |||
GOPATH=$(GOPATH) go clean -i ./... | |||
ser: | |||
go generate | |||
cover: | |||
go test -coverprofile=coverage.out | |||
go tool cover -html=coverage.out |
@@ -4,8 +4,6 @@ import ( | |||
"fmt" | |||
) | |||
//go:generate msgp -unexported | |||
type arrayContainer struct { | |||
content []uint16 | |||
} | |||
@@ -485,7 +483,7 @@ func (ac *arrayContainer) orArrayCardinality(value2 *arrayContainer) int { | |||
func (ac *arrayContainer) lazyorArray(value2 *arrayContainer) container { | |||
value1 := ac | |||
maxPossibleCardinality := value1.getCardinality() + value2.getCardinality() | |||
if maxPossibleCardinality > arrayLazyLowerBound { // it could be a bitmap!^M | |||
if maxPossibleCardinality > arrayLazyLowerBound { // it could be a bitmap! | |||
bc := newBitmapContainer() | |||
for k := 0; k < len(value2.content); k++ { | |||
v := value2.content[k] |
@@ -1,134 +0,0 @@ | |||
package roaring | |||
// NOTE: THIS FILE WAS PRODUCED BY THE | |||
// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp) | |||
// DO NOT EDIT | |||
import "github.com/tinylib/msgp/msgp" | |||
// Deprecated: DecodeMsg implements msgp.Decodable | |||
func (z *arrayContainer) DecodeMsg(dc *msgp.Reader) (err error) { | |||
var field []byte | |||
_ = field | |||
var zbzg uint32 | |||
zbzg, err = dc.ReadMapHeader() | |||
if err != nil { | |||
return | |||
} | |||
for zbzg > 0 { | |||
zbzg-- | |||
field, err = dc.ReadMapKeyPtr() | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "content": | |||
var zbai uint32 | |||
zbai, err = dc.ReadArrayHeader() | |||
if err != nil { | |||
return | |||
} | |||
if cap(z.content) >= int(zbai) { | |||
z.content = (z.content)[:zbai] | |||
} else { | |||
z.content = make([]uint16, zbai) | |||
} | |||
for zxvk := range z.content { | |||
z.content[zxvk], err = dc.ReadUint16() | |||
if err != nil { | |||
return | |||
} | |||
} | |||
default: | |||
err = dc.Skip() | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
return | |||
} | |||
// Deprecated: EncodeMsg implements msgp.Encodable | |||
func (z *arrayContainer) EncodeMsg(en *msgp.Writer) (err error) { | |||
// map header, size 1 | |||
// write "content" | |||
err = en.Append(0x81, 0xa7, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74) | |||
if err != nil { | |||
return err | |||
} | |||
err = en.WriteArrayHeader(uint32(len(z.content))) | |||
if err != nil { | |||
return | |||
} | |||
for zxvk := range z.content { | |||
err = en.WriteUint16(z.content[zxvk]) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
return | |||
} | |||
// Deprecated: MarshalMsg implements msgp.Marshaler | |||
func (z *arrayContainer) MarshalMsg(b []byte) (o []byte, err error) { | |||
o = msgp.Require(b, z.Msgsize()) | |||
// map header, size 1 | |||
// string "content" | |||
o = append(o, 0x81, 0xa7, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74) | |||
o = msgp.AppendArrayHeader(o, uint32(len(z.content))) | |||
for zxvk := range z.content { | |||
o = msgp.AppendUint16(o, z.content[zxvk]) | |||
} | |||
return | |||
} | |||
// Deprecated: UnmarshalMsg implements msgp.Unmarshaler | |||
func (z *arrayContainer) UnmarshalMsg(bts []byte) (o []byte, err error) { | |||
var field []byte | |||
_ = field | |||
var zcmr uint32 | |||
zcmr, bts, err = msgp.ReadMapHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
for zcmr > 0 { | |||
zcmr-- | |||
field, bts, err = msgp.ReadMapKeyZC(bts) | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "content": | |||
var zajw uint32 | |||
zajw, bts, err = msgp.ReadArrayHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
if cap(z.content) >= int(zajw) { | |||
z.content = (z.content)[:zajw] | |||
} else { | |||
z.content = make([]uint16, zajw) | |||
} | |||
for zxvk := range z.content { | |||
z.content[zxvk], bts, err = msgp.ReadUint16Bytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
default: | |||
bts, err = msgp.Skip(bts) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
o = bts | |||
return | |||
} | |||
// Deprecated: Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message | |||
func (z *arrayContainer) Msgsize() (s int) { | |||
s = 1 + 8 + msgp.ArrayHeaderSize + (len(z.content) * (msgp.Uint16Size)) | |||
return | |||
} |
@@ -5,8 +5,6 @@ import ( | |||
"unsafe" | |||
) | |||
//go:generate msgp -unexported | |||
type bitmapContainer struct { | |||
cardinality int | |||
bitmap []uint64 | |||
@@ -115,7 +113,7 @@ type bitmapContainerShortIterator struct { | |||
func (bcsi *bitmapContainerShortIterator) next() uint16 { | |||
j := bcsi.i | |||
bcsi.i = bcsi.ptr.NextSetBit(bcsi.i + 1) | |||
bcsi.i = bcsi.ptr.NextSetBit(uint(bcsi.i) + 1) | |||
return uint16(j) | |||
} | |||
func (bcsi *bitmapContainerShortIterator) hasNext() bool { | |||
@@ -128,7 +126,7 @@ func (bcsi *bitmapContainerShortIterator) peekNext() uint16 { | |||
func (bcsi *bitmapContainerShortIterator) advanceIfNeeded(minval uint16) { | |||
if bcsi.hasNext() && bcsi.peekNext() < minval { | |||
bcsi.i = bcsi.ptr.NextSetBit(int(minval)) | |||
bcsi.i = bcsi.ptr.NextSetBit(uint(minval)) | |||
} | |||
} | |||
@@ -1009,20 +1007,23 @@ func (bc *bitmapContainer) fillArray(container []uint16) { | |||
} | |||
} | |||
func (bc *bitmapContainer) NextSetBit(i int) int { | |||
x := i / 64 | |||
if x >= len(bc.bitmap) { | |||
func (bc *bitmapContainer) NextSetBit(i uint) int { | |||
var ( | |||
x = i / 64 | |||
length = uint(len(bc.bitmap)) | |||
) | |||
if x >= length { | |||
return -1 | |||
} | |||
w := bc.bitmap[x] | |||
w = w >> uint(i%64) | |||
if w != 0 { | |||
return i + countTrailingZeros(w) | |||
return int(i) + countTrailingZeros(w) | |||
} | |||
x++ | |||
for ; x < len(bc.bitmap); x++ { | |||
for ; x < length; x++ { | |||
if bc.bitmap[x] != 0 { | |||
return (x * 64) + countTrailingZeros(bc.bitmap[x]) | |||
return int(x*64) + countTrailingZeros(bc.bitmap[x]) | |||
} | |||
} | |||
return -1 |
@@ -1,415 +0,0 @@ | |||
package roaring | |||
// NOTE: THIS FILE WAS PRODUCED BY THE | |||
// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp) | |||
// DO NOT EDIT | |||
import "github.com/tinylib/msgp/msgp" | |||
// Deprecated: DecodeMsg implements msgp.Decodable | |||
func (z *bitmapContainer) DecodeMsg(dc *msgp.Reader) (err error) { | |||
var field []byte | |||
_ = field | |||
var zbzg uint32 | |||
zbzg, err = dc.ReadMapHeader() | |||
if err != nil { | |||
return | |||
} | |||
for zbzg > 0 { | |||
zbzg-- | |||
field, err = dc.ReadMapKeyPtr() | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "cardinality": | |||
z.cardinality, err = dc.ReadInt() | |||
if err != nil { | |||
return | |||
} | |||
case "bitmap": | |||
var zbai uint32 | |||
zbai, err = dc.ReadArrayHeader() | |||
if err != nil { | |||
return | |||
} | |||
if cap(z.bitmap) >= int(zbai) { | |||
z.bitmap = (z.bitmap)[:zbai] | |||
} else { | |||
z.bitmap = make([]uint64, zbai) | |||
} | |||
for zxvk := range z.bitmap { | |||
z.bitmap[zxvk], err = dc.ReadUint64() | |||
if err != nil { | |||
return | |||
} | |||
} | |||
default: | |||
err = dc.Skip() | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
return | |||
} | |||
// Deprecated: EncodeMsg implements msgp.Encodable | |||
func (z *bitmapContainer) EncodeMsg(en *msgp.Writer) (err error) { | |||
// map header, size 2 | |||
// write "cardinality" | |||
err = en.Append(0x82, 0xab, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79) | |||
if err != nil { | |||
return err | |||
} | |||
err = en.WriteInt(z.cardinality) | |||
if err != nil { | |||
return | |||
} | |||
// write "bitmap" | |||
err = en.Append(0xa6, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70) | |||
if err != nil { | |||
return err | |||
} | |||
err = en.WriteArrayHeader(uint32(len(z.bitmap))) | |||
if err != nil { | |||
return | |||
} | |||
for zxvk := range z.bitmap { | |||
err = en.WriteUint64(z.bitmap[zxvk]) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
return | |||
} | |||
// Deprecated: MarshalMsg implements msgp.Marshaler | |||
func (z *bitmapContainer) MarshalMsg(b []byte) (o []byte, err error) { | |||
o = msgp.Require(b, z.Msgsize()) | |||
// map header, size 2 | |||
// string "cardinality" | |||
o = append(o, 0x82, 0xab, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79) | |||
o = msgp.AppendInt(o, z.cardinality) | |||
// string "bitmap" | |||
o = append(o, 0xa6, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70) | |||
o = msgp.AppendArrayHeader(o, uint32(len(z.bitmap))) | |||
for zxvk := range z.bitmap { | |||
o = msgp.AppendUint64(o, z.bitmap[zxvk]) | |||
} | |||
return | |||
} | |||
// Deprecated: UnmarshalMsg implements msgp.Unmarshaler | |||
func (z *bitmapContainer) UnmarshalMsg(bts []byte) (o []byte, err error) { | |||
var field []byte | |||
_ = field | |||
var zcmr uint32 | |||
zcmr, bts, err = msgp.ReadMapHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
for zcmr > 0 { | |||
zcmr-- | |||
field, bts, err = msgp.ReadMapKeyZC(bts) | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "cardinality": | |||
z.cardinality, bts, err = msgp.ReadIntBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
case "bitmap": | |||
var zajw uint32 | |||
zajw, bts, err = msgp.ReadArrayHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
if cap(z.bitmap) >= int(zajw) { | |||
z.bitmap = (z.bitmap)[:zajw] | |||
} else { | |||
z.bitmap = make([]uint64, zajw) | |||
} | |||
for zxvk := range z.bitmap { | |||
z.bitmap[zxvk], bts, err = msgp.ReadUint64Bytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
default: | |||
bts, err = msgp.Skip(bts) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
o = bts | |||
return | |||
} | |||
// Deprecated: Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message | |||
func (z *bitmapContainer) Msgsize() (s int) { | |||
s = 1 + 12 + msgp.IntSize + 7 + msgp.ArrayHeaderSize + (len(z.bitmap) * (msgp.Uint64Size)) | |||
return | |||
} | |||
// Deprecated: DecodeMsg implements msgp.Decodable | |||
func (z *bitmapContainerShortIterator) DecodeMsg(dc *msgp.Reader) (err error) { | |||
var field []byte | |||
_ = field | |||
var zhct uint32 | |||
zhct, err = dc.ReadMapHeader() | |||
if err != nil { | |||
return | |||
} | |||
for zhct > 0 { | |||
zhct-- | |||
field, err = dc.ReadMapKeyPtr() | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "ptr": | |||
if dc.IsNil() { | |||
err = dc.ReadNil() | |||
if err != nil { | |||
return | |||
} | |||
z.ptr = nil | |||
} else { | |||
if z.ptr == nil { | |||
z.ptr = new(bitmapContainer) | |||
} | |||
var zcua uint32 | |||
zcua, err = dc.ReadMapHeader() | |||
if err != nil { | |||
return | |||
} | |||
for zcua > 0 { | |||
zcua-- | |||
field, err = dc.ReadMapKeyPtr() | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "cardinality": | |||
z.ptr.cardinality, err = dc.ReadInt() | |||
if err != nil { | |||
return | |||
} | |||
case "bitmap": | |||
var zxhx uint32 | |||
zxhx, err = dc.ReadArrayHeader() | |||
if err != nil { | |||
return | |||
} | |||
if cap(z.ptr.bitmap) >= int(zxhx) { | |||
z.ptr.bitmap = (z.ptr.bitmap)[:zxhx] | |||
} else { | |||
z.ptr.bitmap = make([]uint64, zxhx) | |||
} | |||
for zwht := range z.ptr.bitmap { | |||
z.ptr.bitmap[zwht], err = dc.ReadUint64() | |||
if err != nil { | |||
return | |||
} | |||
} | |||
default: | |||
err = dc.Skip() | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
} | |||
case "i": | |||
z.i, err = dc.ReadInt() | |||
if err != nil { | |||
return | |||
} | |||
default: | |||
err = dc.Skip() | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
return | |||
} | |||
// Deprecated: EncodeMsg implements msgp.Encodable | |||
func (z *bitmapContainerShortIterator) EncodeMsg(en *msgp.Writer) (err error) { | |||
// map header, size 2 | |||
// write "ptr" | |||
err = en.Append(0x82, 0xa3, 0x70, 0x74, 0x72) | |||
if err != nil { | |||
return err | |||
} | |||
if z.ptr == nil { | |||
err = en.WriteNil() | |||
if err != nil { | |||
return | |||
} | |||
} else { | |||
// map header, size 2 | |||
// write "cardinality" | |||
err = en.Append(0x82, 0xab, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79) | |||
if err != nil { | |||
return err | |||
} | |||
err = en.WriteInt(z.ptr.cardinality) | |||
if err != nil { | |||
return | |||
} | |||
// write "bitmap" | |||
err = en.Append(0xa6, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70) | |||
if err != nil { | |||
return err | |||
} | |||
err = en.WriteArrayHeader(uint32(len(z.ptr.bitmap))) | |||
if err != nil { | |||
return | |||
} | |||
for zwht := range z.ptr.bitmap { | |||
err = en.WriteUint64(z.ptr.bitmap[zwht]) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
// write "i" | |||
err = en.Append(0xa1, 0x69) | |||
if err != nil { | |||
return err | |||
} | |||
err = en.WriteInt(z.i) | |||
if err != nil { | |||
return | |||
} | |||
return | |||
} | |||
// Deprecated: MarshalMsg implements msgp.Marshaler | |||
func (z *bitmapContainerShortIterator) MarshalMsg(b []byte) (o []byte, err error) { | |||
o = msgp.Require(b, z.Msgsize()) | |||
// map header, size 2 | |||
// string "ptr" | |||
o = append(o, 0x82, 0xa3, 0x70, 0x74, 0x72) | |||
if z.ptr == nil { | |||
o = msgp.AppendNil(o) | |||
} else { | |||
// map header, size 2 | |||
// string "cardinality" | |||
o = append(o, 0x82, 0xab, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79) | |||
o = msgp.AppendInt(o, z.ptr.cardinality) | |||
// string "bitmap" | |||
o = append(o, 0xa6, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70) | |||
o = msgp.AppendArrayHeader(o, uint32(len(z.ptr.bitmap))) | |||
for zwht := range z.ptr.bitmap { | |||
o = msgp.AppendUint64(o, z.ptr.bitmap[zwht]) | |||
} | |||
} | |||
// string "i" | |||
o = append(o, 0xa1, 0x69) | |||
o = msgp.AppendInt(o, z.i) | |||
return | |||
} | |||
// Deprecated: UnmarshalMsg implements msgp.Unmarshaler | |||
func (z *bitmapContainerShortIterator) UnmarshalMsg(bts []byte) (o []byte, err error) { | |||
var field []byte | |||
_ = field | |||
var zlqf uint32 | |||
zlqf, bts, err = msgp.ReadMapHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
for zlqf > 0 { | |||
zlqf-- | |||
field, bts, err = msgp.ReadMapKeyZC(bts) | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "ptr": | |||
if msgp.IsNil(bts) { | |||
bts, err = msgp.ReadNilBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
z.ptr = nil | |||
} else { | |||
if z.ptr == nil { | |||
z.ptr = new(bitmapContainer) | |||
} | |||
var zdaf uint32 | |||
zdaf, bts, err = msgp.ReadMapHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
for zdaf > 0 { | |||
zdaf-- | |||
field, bts, err = msgp.ReadMapKeyZC(bts) | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "cardinality": | |||
z.ptr.cardinality, bts, err = msgp.ReadIntBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
case "bitmap": | |||
var zpks uint32 | |||
zpks, bts, err = msgp.ReadArrayHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
if cap(z.ptr.bitmap) >= int(zpks) { | |||
z.ptr.bitmap = (z.ptr.bitmap)[:zpks] | |||
} else { | |||
z.ptr.bitmap = make([]uint64, zpks) | |||
} | |||
for zwht := range z.ptr.bitmap { | |||
z.ptr.bitmap[zwht], bts, err = msgp.ReadUint64Bytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
default: | |||
bts, err = msgp.Skip(bts) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
} | |||
case "i": | |||
z.i, bts, err = msgp.ReadIntBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
default: | |||
bts, err = msgp.Skip(bts) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
o = bts | |||
return | |||
} | |||
// Deprecated: Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message | |||
func (z *bitmapContainerShortIterator) Msgsize() (s int) { | |||
s = 1 + 4 | |||
if z.ptr == nil { | |||
s += msgp.NilSize | |||
} else { | |||
s += 1 + 12 + msgp.IntSize + 7 + msgp.ArrayHeaderSize + (len(z.ptr.bitmap) * (msgp.Uint64Size)) | |||
} | |||
s += 2 + msgp.IntSize | |||
return | |||
} |
@@ -1,161 +0,0 @@ | |||
package roaring | |||
import ( | |||
"encoding/binary" | |||
"io" | |||
) | |||
type byteInput interface { | |||
// next returns a slice containing the next n bytes from the buffer, | |||
// advancing the buffer as if the bytes had been returned by Read. | |||
next(n int) ([]byte, error) | |||
// readUInt32 reads uint32 with LittleEndian order | |||
readUInt32() (uint32, error) | |||
// readUInt16 reads uint16 with LittleEndian order | |||
readUInt16() (uint16, error) | |||
// getReadBytes returns read bytes | |||
getReadBytes() int64 | |||
// skipBytes skips exactly n bytes | |||
skipBytes(n int) error | |||
} | |||
func newByteInputFromReader(reader io.Reader) byteInput { | |||
return &byteInputAdapter{ | |||
r: reader, | |||
readBytes: 0, | |||
} | |||
} | |||
func newByteInput(buf []byte) byteInput { | |||
return &byteBuffer{ | |||
buf: buf, | |||
off: 0, | |||
} | |||
} | |||
type byteBuffer struct { | |||
buf []byte | |||
off int | |||
} | |||
// next returns a slice containing the next n bytes from the reader | |||
// If there are fewer bytes than the given n, io.ErrUnexpectedEOF will be returned | |||
func (b *byteBuffer) next(n int) ([]byte, error) { | |||
m := len(b.buf) - b.off | |||
if n > m { | |||
return nil, io.ErrUnexpectedEOF | |||
} | |||
data := b.buf[b.off : b.off+n] | |||
b.off += n | |||
return data, nil | |||
} | |||
// readUInt32 reads uint32 with LittleEndian order | |||
func (b *byteBuffer) readUInt32() (uint32, error) { | |||
if len(b.buf)-b.off < 4 { | |||
return 0, io.ErrUnexpectedEOF | |||
} | |||
v := binary.LittleEndian.Uint32(b.buf[b.off:]) | |||
b.off += 4 | |||
return v, nil | |||
} | |||
// readUInt16 reads uint16 with LittleEndian order | |||
func (b *byteBuffer) readUInt16() (uint16, error) { | |||
if len(b.buf)-b.off < 2 { | |||
return 0, io.ErrUnexpectedEOF | |||
} | |||
v := binary.LittleEndian.Uint16(b.buf[b.off:]) | |||
b.off += 2 | |||
return v, nil | |||
} | |||
// getReadBytes returns read bytes | |||
func (b *byteBuffer) getReadBytes() int64 { | |||
return int64(b.off) | |||
} | |||
// skipBytes skips exactly n bytes | |||
func (b *byteBuffer) skipBytes(n int) error { | |||
m := len(b.buf) - b.off | |||
if n > m { | |||
return io.ErrUnexpectedEOF | |||
} | |||
b.off += n | |||
return nil | |||
} | |||
// reset resets the given buffer with a new byte slice | |||
func (b *byteBuffer) reset(buf []byte) { | |||
b.buf = buf | |||
b.off = 0 | |||
} | |||
type byteInputAdapter struct { | |||
r io.Reader | |||
readBytes int | |||
} | |||
// next returns a slice containing the next n bytes from the buffer, | |||
// advancing the buffer as if the bytes had been returned by Read. | |||
func (b *byteInputAdapter) next(n int) ([]byte, error) { | |||
buf := make([]byte, n) | |||
m, err := io.ReadAtLeast(b.r, buf, n) | |||
b.readBytes += m | |||
if err != nil { | |||
return nil, err | |||
} | |||
return buf, nil | |||
} | |||
// readUInt32 reads uint32 with LittleEndian order | |||
func (b *byteInputAdapter) readUInt32() (uint32, error) { | |||
buf, err := b.next(4) | |||
if err != nil { | |||
return 0, err | |||
} | |||
return binary.LittleEndian.Uint32(buf), nil | |||
} | |||
// readUInt16 reads uint16 with LittleEndian order | |||
func (b *byteInputAdapter) readUInt16() (uint16, error) { | |||
buf, err := b.next(2) | |||
if err != nil { | |||
return 0, err | |||
} | |||
return binary.LittleEndian.Uint16(buf), nil | |||
} | |||
// getReadBytes returns read bytes | |||
func (b *byteInputAdapter) getReadBytes() int64 { | |||
return int64(b.readBytes) | |||
} | |||
// skipBytes skips exactly n bytes | |||
func (b *byteInputAdapter) skipBytes(n int) error { | |||
_, err := b.next(n) | |||
return err | |||
} | |||
// reset resets the given buffer with a new stream | |||
func (b *byteInputAdapter) reset(stream io.Reader) { | |||
b.r = stream | |||
b.readBytes = 0 | |||
} |
@@ -11,7 +11,6 @@ require ( | |||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae | |||
github.com/philhofer/fwd v1.0.0 // indirect | |||
github.com/stretchr/testify v1.4.0 | |||
github.com/tinylib/msgp v1.1.0 | |||
github.com/willf/bitset v1.1.10 | |||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect | |||
golang.org/x/tools v0.0.0-20200928182047-19e03678916f // indirect |
@@ -20,8 +20,6 @@ github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= | |||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | |||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= | |||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | |||
github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU= | |||
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= | |||
github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc= | |||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= | |||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= |
@@ -0,0 +1,166 @@ | |||
package internal | |||
import ( | |||
"encoding/binary" | |||
"io" | |||
) | |||
// ByteInput typed interface around io.Reader or raw bytes | |||
type ByteInput interface { | |||
// Next returns a slice containing the next n bytes from the buffer, | |||
// advancing the buffer as if the bytes had been returned by Read. | |||
Next(n int) ([]byte, error) | |||
// ReadUInt32 reads uint32 with LittleEndian order | |||
ReadUInt32() (uint32, error) | |||
// ReadUInt16 reads uint16 with LittleEndian order | |||
ReadUInt16() (uint16, error) | |||
// GetReadBytes returns read bytes | |||
GetReadBytes() int64 | |||
// SkipBytes skips exactly n bytes | |||
SkipBytes(n int) error | |||
} | |||
// NewByteInputFromReader creates reader wrapper | |||
func NewByteInputFromReader(reader io.Reader) ByteInput { | |||
return &ByteInputAdapter{ | |||
r: reader, | |||
readBytes: 0, | |||
} | |||
} | |||
// NewByteInput creates raw bytes wrapper | |||
func NewByteInput(buf []byte) ByteInput { | |||
return &ByteBuffer{ | |||
buf: buf, | |||
off: 0, | |||
} | |||
} | |||
// ByteBuffer raw bytes wrapper | |||
type ByteBuffer struct { | |||
buf []byte | |||
off int | |||
} | |||
// Next returns a slice containing the next n bytes from the reader | |||
// If there are fewer bytes than the given n, io.ErrUnexpectedEOF will be returned | |||
func (b *ByteBuffer) Next(n int) ([]byte, error) { | |||
m := len(b.buf) - b.off | |||
if n > m { | |||
return nil, io.ErrUnexpectedEOF | |||
} | |||
data := b.buf[b.off : b.off+n] | |||
b.off += n | |||
return data, nil | |||
} | |||
// ReadUInt32 reads uint32 with LittleEndian order | |||
func (b *ByteBuffer) ReadUInt32() (uint32, error) { | |||
if len(b.buf)-b.off < 4 { | |||
return 0, io.ErrUnexpectedEOF | |||
} | |||
v := binary.LittleEndian.Uint32(b.buf[b.off:]) | |||
b.off += 4 | |||
return v, nil | |||
} | |||
// ReadUInt16 reads uint16 with LittleEndian order | |||
func (b *ByteBuffer) ReadUInt16() (uint16, error) { | |||
if len(b.buf)-b.off < 2 { | |||
return 0, io.ErrUnexpectedEOF | |||
} | |||
v := binary.LittleEndian.Uint16(b.buf[b.off:]) | |||
b.off += 2 | |||
return v, nil | |||
} | |||
// GetReadBytes returns read bytes | |||
func (b *ByteBuffer) GetReadBytes() int64 { | |||
return int64(b.off) | |||
} | |||
// SkipBytes skips exactly n bytes | |||
func (b *ByteBuffer) SkipBytes(n int) error { | |||
m := len(b.buf) - b.off | |||
if n > m { | |||
return io.ErrUnexpectedEOF | |||
} | |||
b.off += n | |||
return nil | |||
} | |||
// Reset resets the given buffer with a new byte slice | |||
func (b *ByteBuffer) Reset(buf []byte) { | |||
b.buf = buf | |||
b.off = 0 | |||
} | |||
// ByteInputAdapter reader wrapper | |||
type ByteInputAdapter struct { | |||
r io.Reader | |||
readBytes int | |||
} | |||
// Next returns a slice containing the next n bytes from the buffer, | |||
// advancing the buffer as if the bytes had been returned by Read. | |||
func (b *ByteInputAdapter) Next(n int) ([]byte, error) { | |||
buf := make([]byte, n) | |||
m, err := io.ReadAtLeast(b.r, buf, n) | |||
b.readBytes += m | |||
if err != nil { | |||
return nil, err | |||
} | |||
return buf, nil | |||
} | |||
// ReadUInt32 reads uint32 with LittleEndian order | |||
func (b *ByteInputAdapter) ReadUInt32() (uint32, error) { | |||
buf, err := b.Next(4) | |||
if err != nil { | |||
return 0, err | |||
} | |||
return binary.LittleEndian.Uint32(buf), nil | |||
} | |||
// ReadUInt16 reads uint16 with LittleEndian order | |||
func (b *ByteInputAdapter) ReadUInt16() (uint16, error) { | |||
buf, err := b.Next(2) | |||
if err != nil { | |||
return 0, err | |||
} | |||
return binary.LittleEndian.Uint16(buf), nil | |||
} | |||
// GetReadBytes returns read bytes | |||
func (b *ByteInputAdapter) GetReadBytes() int64 { | |||
return int64(b.readBytes) | |||
} | |||
// SkipBytes skips exactly n bytes | |||
func (b *ByteInputAdapter) SkipBytes(n int) error { | |||
_, err := b.Next(n) | |||
return err | |||
} | |||
// Reset resets the given buffer with a new stream | |||
func (b *ByteInputAdapter) Reset(stream io.Reader) { | |||
b.r = stream | |||
b.readBytes = 0 | |||
} |
@@ -0,0 +1,21 @@ | |||
package internal | |||
import ( | |||
"sync" | |||
) | |||
var ( | |||
// ByteInputAdapterPool shared pool | |||
ByteInputAdapterPool = sync.Pool{ | |||
New: func() interface{} { | |||
return &ByteInputAdapter{} | |||
}, | |||
} | |||
// ByteBufferPool shared pool | |||
ByteBufferPool = sync.Pool{ | |||
New: func() interface{} { | |||
return &ByteBuffer{} | |||
}, | |||
} | |||
) |
@@ -166,7 +166,6 @@ func appenderRoutine(bitmapChan chan<- *Bitmap, resultChan <-chan keyedContainer | |||
make([]container, 0, expectedKeys), | |||
make([]bool, 0, expectedKeys), | |||
false, | |||
nil, | |||
}, | |||
} | |||
for i := range keys { |
@@ -11,7 +11,8 @@ import ( | |||
"fmt" | |||
"io" | |||
"strconv" | |||
"sync" | |||
"github.com/RoaringBitmap/roaring/internal" | |||
) | |||
// Bitmap represents a compressed bitmap where you can add integers. | |||
@@ -52,27 +53,19 @@ func (rb *Bitmap) ToBytes() ([]byte, error) { | |||
return rb.highlowcontainer.toBytes() | |||
} | |||
// Deprecated: WriteToMsgpack writes a msgpack2/snappy-streaming compressed serialized | |||
// version of this bitmap to stream. The format is not | |||
// compatible with the WriteTo() format, and is | |||
// experimental: it may produce smaller on disk | |||
// footprint and/or be faster to read, depending | |||
// on your content. Currently only the Go roaring | |||
// implementation supports this format. | |||
func (rb *Bitmap) WriteToMsgpack(stream io.Writer) (int64, error) { | |||
return 0, rb.highlowcontainer.writeToMsgpack(stream) | |||
} | |||
// ReadFrom reads a serialized version of this bitmap from stream. | |||
// The format is compatible with other RoaringBitmap | |||
// implementations (Java, C) and is documented here: | |||
// https://github.com/RoaringBitmap/RoaringFormatSpec | |||
func (rb *Bitmap) ReadFrom(reader io.Reader) (p int64, err error) { | |||
stream := byteInputAdapterPool.Get().(*byteInputAdapter) | |||
stream.reset(reader) | |||
// Since io.Reader is regarded as a stream and cannot be read twice. | |||
// So add cookieHeader to accept the 4-byte data that has been read in roaring64.ReadFrom. | |||
// It is not necessary to pass cookieHeader when call roaring.ReadFrom to read the roaring32 data directly. | |||
func (rb *Bitmap) ReadFrom(reader io.Reader, cookieHeader ...byte) (p int64, err error) { | |||
stream := internal.ByteInputAdapterPool.Get().(*internal.ByteInputAdapter) | |||
stream.Reset(reader) | |||
p, err = rb.highlowcontainer.readFrom(stream) | |||
byteInputAdapterPool.Put(stream) | |||
p, err = rb.highlowcontainer.readFrom(stream, cookieHeader...) | |||
internal.ByteInputAdapterPool.Put(stream) | |||
return | |||
} | |||
@@ -100,29 +93,15 @@ func (rb *Bitmap) ReadFrom(reader io.Reader) (p int64, err error) { | |||
// call CloneCopyOnWriteContainers on all such bitmaps. | |||
// | |||
func (rb *Bitmap) FromBuffer(buf []byte) (p int64, err error) { | |||
stream := byteBufferPool.Get().(*byteBuffer) | |||
stream.reset(buf) | |||
stream := internal.ByteBufferPool.Get().(*internal.ByteBuffer) | |||
stream.Reset(buf) | |||
p, err = rb.highlowcontainer.readFrom(stream) | |||
byteBufferPool.Put(stream) | |||
internal.ByteBufferPool.Put(stream) | |||
return | |||
} | |||
var ( | |||
byteBufferPool = sync.Pool{ | |||
New: func() interface{} { | |||
return &byteBuffer{} | |||
}, | |||
} | |||
byteInputAdapterPool = sync.Pool{ | |||
New: func() interface{} { | |||
return &byteInputAdapter{} | |||
}, | |||
} | |||
) | |||
// RunOptimize attempts to further compress the runs of consecutive values found in the bitmap | |||
func (rb *Bitmap) RunOptimize() { | |||
rb.highlowcontainer.runOptimize() | |||
@@ -133,14 +112,6 @@ func (rb *Bitmap) HasRunCompression() bool { | |||
return rb.highlowcontainer.hasRunCompression() | |||
} | |||
// Deprecated: ReadFromMsgpack reads a msgpack2/snappy-streaming serialized | |||
// version of this bitmap from stream. The format is | |||
// expected is that written by the WriteToMsgpack() | |||
// call; see additional notes there. | |||
func (rb *Bitmap) ReadFromMsgpack(stream io.Reader) (int64, error) { | |||
return 0, rb.highlowcontainer.readFromMsgpack(stream) | |||
} | |||
// MarshalBinary implements the encoding.BinaryMarshaler interface for the bitmap | |||
// (same as ToBytes) | |||
func (rb *Bitmap) MarshalBinary() ([]byte, error) { |
@@ -5,13 +5,9 @@ import ( | |||
"encoding/binary" | |||
"fmt" | |||
"io" | |||
snappy "github.com/glycerine/go-unsnap-stream" | |||
"github.com/tinylib/msgp/msgp" | |||
"github.com/RoaringBitmap/roaring/internal" | |||
) | |||
//go:generate msgp -unexported | |||
type container interface { | |||
addOffset(uint16) []container | |||
@@ -103,18 +99,6 @@ type roaringArray struct { | |||
containers []container `msg:"-"` // don't try to serialize directly. | |||
needCopyOnWrite []bool | |||
copyOnWrite bool | |||
// conserz is used at serialization time | |||
// to serialize containers. Otherwise empty. | |||
conserz []containerSerz | |||
} | |||
// containerSerz facilitates serializing container (tricky to | |||
// serialize because it is an interface) by providing a | |||
// light wrapper with a type identifier. | |||
type containerSerz struct { | |||
t contype `msg:"t"` // type | |||
r msgp.Raw `msg:"r"` // Raw msgpack of the actual container type | |||
} | |||
func newRoaringArray() *roaringArray { | |||
@@ -246,7 +230,6 @@ func (ra *roaringArray) resize(newsize int) { | |||
func (ra *roaringArray) clear() { | |||
ra.resize(0) | |||
ra.copyOnWrite = false | |||
ra.conserz = nil | |||
} | |||
func (ra *roaringArray) clone() *roaringArray { | |||
@@ -566,11 +549,19 @@ func (ra *roaringArray) toBytes() ([]byte, error) { | |||
return buf.Bytes(), err | |||
} | |||
func (ra *roaringArray) readFrom(stream byteInput) (int64, error) { | |||
cookie, err := stream.readUInt32() | |||
if err != nil { | |||
return stream.getReadBytes(), fmt.Errorf("error in roaringArray.readFrom: could not read initial cookie: %s", err) | |||
func (ra *roaringArray) readFrom(stream internal.ByteInput, cookieHeader ...byte) (int64, error) { | |||
var cookie uint32 | |||
var err error | |||
if len(cookieHeader) > 0 && len(cookieHeader) != 4 { | |||
return int64(len(cookieHeader)), fmt.Errorf("error in roaringArray.readFrom: could not read initial cookie: incorrect size of cookie header") | |||
} | |||
if len(cookieHeader) == 4 { | |||
cookie = binary.LittleEndian.Uint32(cookieHeader) | |||
} else { | |||
cookie, err = stream.ReadUInt32() | |||
if err != nil { | |||
return stream.GetReadBytes(), fmt.Errorf("error in roaringArray.readFrom: could not read initial cookie: %s", err) | |||
} | |||
} | |||
var size uint32 | |||
@@ -580,37 +571,36 @@ func (ra *roaringArray) readFrom(stream byteInput) (int64, error) { | |||
size = uint32(uint16(cookie>>16) + 1) | |||
// create is-run-container bitmap | |||
isRunBitmapSize := (int(size) + 7) / 8 | |||
isRunBitmap, err = stream.next(isRunBitmapSize) | |||
isRunBitmap, err = stream.Next(isRunBitmapSize) | |||
if err != nil { | |||
return stream.getReadBytes(), fmt.Errorf("malformed bitmap, failed to read is-run bitmap, got: %s", err) | |||
return stream.GetReadBytes(), fmt.Errorf("malformed bitmap, failed to read is-run bitmap, got: %s", err) | |||
} | |||
} else if cookie == serialCookieNoRunContainer { | |||
size, err = stream.readUInt32() | |||
size, err = stream.ReadUInt32() | |||
if err != nil { | |||
return stream.getReadBytes(), fmt.Errorf("malformed bitmap, failed to read a bitmap size: %s", err) | |||
return stream.GetReadBytes(), fmt.Errorf("malformed bitmap, failed to read a bitmap size: %s", err) | |||
} | |||
} else { | |||
return stream.getReadBytes(), fmt.Errorf("error in roaringArray.readFrom: did not find expected serialCookie in header") | |||
return stream.GetReadBytes(), fmt.Errorf("error in roaringArray.readFrom: did not find expected serialCookie in header") | |||
} | |||
if size > (1 << 16) { | |||
return stream.getReadBytes(), fmt.Errorf("it is logically impossible to have more than (1<<16) containers") | |||
return stream.GetReadBytes(), fmt.Errorf("it is logically impossible to have more than (1<<16) containers") | |||
} | |||
// descriptive header | |||
buf, err := stream.next(2 * 2 * int(size)) | |||
buf, err := stream.Next(2 * 2 * int(size)) | |||
if err != nil { | |||
return stream.getReadBytes(), fmt.Errorf("failed to read descriptive header: %s", err) | |||
return stream.GetReadBytes(), fmt.Errorf("failed to read descriptive header: %s", err) | |||
} | |||
keycard := byteSliceAsUint16Slice(buf) | |||
if isRunBitmap == nil || size >= noOffsetThreshold { | |||
if err := stream.skipBytes(int(size) * 4); err != nil { | |||
return stream.getReadBytes(), fmt.Errorf("failed to skip bytes: %s", err) | |||
if err := stream.SkipBytes(int(size) * 4); err != nil { | |||
return stream.GetReadBytes(), fmt.Errorf("failed to skip bytes: %s", err) | |||
} | |||
} | |||
@@ -641,16 +631,16 @@ func (ra *roaringArray) readFrom(stream byteInput) (int64, error) { | |||
if isRunBitmap != nil && isRunBitmap[i/8]&(1<<(i%8)) != 0 { | |||
// run container | |||
nr, err := stream.readUInt16() | |||
nr, err := stream.ReadUInt16() | |||
if err != nil { | |||
return 0, fmt.Errorf("failed to read runtime container size: %s", err) | |||
} | |||
buf, err := stream.next(int(nr) * 4) | |||
buf, err := stream.Next(int(nr) * 4) | |||
if err != nil { | |||
return stream.getReadBytes(), fmt.Errorf("failed to read runtime container content: %s", err) | |||
return stream.GetReadBytes(), fmt.Errorf("failed to read runtime container content: %s", err) | |||
} | |||
nb := runContainer16{ | |||
@@ -661,10 +651,10 @@ func (ra *roaringArray) readFrom(stream byteInput) (int64, error) { | |||
ra.containers[i] = &nb | |||
} else if card > arrayDefaultMaxSize { | |||
// bitmap container | |||
buf, err := stream.next(arrayDefaultMaxSize * 2) | |||
buf, err := stream.Next(arrayDefaultMaxSize * 2) | |||
if err != nil { | |||
return stream.getReadBytes(), fmt.Errorf("failed to read bitmap container: %s", err) | |||
return stream.GetReadBytes(), fmt.Errorf("failed to read bitmap container: %s", err) | |||
} | |||
nb := bitmapContainer{ | |||
@@ -675,10 +665,10 @@ func (ra *roaringArray) readFrom(stream byteInput) (int64, error) { | |||
ra.containers[i] = &nb | |||
} else { | |||
// array container | |||
buf, err := stream.next(card * 2) | |||
buf, err := stream.Next(card * 2) | |||
if err != nil { | |||
return stream.getReadBytes(), fmt.Errorf("failed to read array container: %s", err) | |||
return stream.GetReadBytes(), fmt.Errorf("failed to read array container: %s", err) | |||
} | |||
nb := arrayContainer{ | |||
@@ -689,7 +679,7 @@ func (ra *roaringArray) readFrom(stream byteInput) (int64, error) { | |||
} | |||
} | |||
return stream.getReadBytes(), nil | |||
return stream.GetReadBytes(), nil | |||
} | |||
func (ra *roaringArray) hasRunCompression() bool { | |||
@@ -702,84 +692,6 @@ func (ra *roaringArray) hasRunCompression() bool { | |||
return false | |||
} | |||
func (ra *roaringArray) writeToMsgpack(stream io.Writer) error { | |||
ra.conserz = make([]containerSerz, len(ra.containers)) | |||
for i, v := range ra.containers { | |||
switch cn := v.(type) { | |||
case *bitmapContainer: | |||
bts, err := cn.MarshalMsg(nil) | |||
if err != nil { | |||
return err | |||
} | |||
ra.conserz[i].t = bitmapContype | |||
ra.conserz[i].r = bts | |||
case *arrayContainer: | |||
bts, err := cn.MarshalMsg(nil) | |||
if err != nil { | |||
return err | |||
} | |||
ra.conserz[i].t = arrayContype | |||
ra.conserz[i].r = bts | |||
case *runContainer16: | |||
bts, err := cn.MarshalMsg(nil) | |||
if err != nil { | |||
return err | |||
} | |||
ra.conserz[i].t = run16Contype | |||
ra.conserz[i].r = bts | |||
default: | |||
panic(fmt.Errorf("Unrecognized container implementation: %T", cn)) | |||
} | |||
} | |||
w := snappy.NewWriter(stream) | |||
err := msgp.Encode(w, ra) | |||
ra.conserz = nil | |||
return err | |||
} | |||
func (ra *roaringArray) readFromMsgpack(stream io.Reader) error { | |||
r := snappy.NewReader(stream) | |||
err := msgp.Decode(r, ra) | |||
if err != nil { | |||
return err | |||
} | |||
if len(ra.containers) != len(ra.keys) { | |||
ra.containers = make([]container, len(ra.keys)) | |||
} | |||
for i, v := range ra.conserz { | |||
switch v.t { | |||
case bitmapContype: | |||
c := &bitmapContainer{} | |||
_, err = c.UnmarshalMsg(v.r) | |||
if err != nil { | |||
return err | |||
} | |||
ra.containers[i] = c | |||
case arrayContype: | |||
c := &arrayContainer{} | |||
_, err = c.UnmarshalMsg(v.r) | |||
if err != nil { | |||
return err | |||
} | |||
ra.containers[i] = c | |||
case run16Contype: | |||
c := &runContainer16{} | |||
_, err = c.UnmarshalMsg(v.r) | |||
if err != nil { | |||
return err | |||
} | |||
ra.containers[i] = c | |||
default: | |||
return fmt.Errorf("unrecognized contype serialization code: '%v'", v.t) | |||
} | |||
} | |||
ra.conserz = nil | |||
return nil | |||
} | |||
func (ra *roaringArray) advanceUntil(min uint16, pos int) int { | |||
lower := pos + 1 | |||
@@ -1,529 +0,0 @@ | |||
package roaring | |||
// NOTE: THIS FILE WAS PRODUCED BY THE | |||
// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp) | |||
// DO NOT EDIT | |||
import ( | |||
"github.com/tinylib/msgp/msgp" | |||
) | |||
// Deprecated: DecodeMsg implements msgp.Decodable | |||
func (z *containerSerz) DecodeMsg(dc *msgp.Reader) (err error) { | |||
var field []byte | |||
_ = field | |||
var zxvk uint32 | |||
zxvk, err = dc.ReadMapHeader() | |||
if err != nil { | |||
return | |||
} | |||
for zxvk > 0 { | |||
zxvk-- | |||
field, err = dc.ReadMapKeyPtr() | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "t": | |||
{ | |||
var zbzg uint8 | |||
zbzg, err = dc.ReadUint8() | |||
z.t = contype(zbzg) | |||
} | |||
if err != nil { | |||
return | |||
} | |||
case "r": | |||
err = z.r.DecodeMsg(dc) | |||
if err != nil { | |||
return | |||
} | |||
default: | |||
err = dc.Skip() | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
return | |||
} | |||
// Deprecated: EncodeMsg implements msgp.Encodable | |||
func (z *containerSerz) EncodeMsg(en *msgp.Writer) (err error) { | |||
// map header, size 2 | |||
// write "t" | |||
err = en.Append(0x82, 0xa1, 0x74) | |||
if err != nil { | |||
return err | |||
} | |||
err = en.WriteUint8(uint8(z.t)) | |||
if err != nil { | |||
return | |||
} | |||
// write "r" | |||
err = en.Append(0xa1, 0x72) | |||
if err != nil { | |||
return err | |||
} | |||
err = z.r.EncodeMsg(en) | |||
if err != nil { | |||
return | |||
} | |||
return | |||
} | |||
// Deprecated: MarshalMsg implements msgp.Marshaler | |||
func (z *containerSerz) MarshalMsg(b []byte) (o []byte, err error) { | |||
o = msgp.Require(b, z.Msgsize()) | |||
// map header, size 2 | |||
// string "t" | |||
o = append(o, 0x82, 0xa1, 0x74) | |||
o = msgp.AppendUint8(o, uint8(z.t)) | |||
// string "r" | |||
o = append(o, 0xa1, 0x72) | |||
o, err = z.r.MarshalMsg(o) | |||
if err != nil { | |||
return | |||
} | |||
return | |||
} | |||
// Deprecated: UnmarshalMsg implements msgp.Unmarshaler | |||
func (z *containerSerz) UnmarshalMsg(bts []byte) (o []byte, err error) { | |||
var field []byte | |||
_ = field | |||
var zbai uint32 | |||
zbai, bts, err = msgp.ReadMapHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
for zbai > 0 { | |||
zbai-- | |||
field, bts, err = msgp.ReadMapKeyZC(bts) | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "t": | |||
{ | |||
var zcmr uint8 | |||
zcmr, bts, err = msgp.ReadUint8Bytes(bts) | |||
z.t = contype(zcmr) | |||
} | |||
if err != nil { | |||
return | |||
} | |||
case "r": | |||
bts, err = z.r.UnmarshalMsg(bts) | |||
if err != nil { | |||
return | |||
} | |||
default: | |||
bts, err = msgp.Skip(bts) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
o = bts | |||
return | |||
} | |||
// Deprecated: Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message | |||
func (z *containerSerz) Msgsize() (s int) { | |||
s = 1 + 2 + msgp.Uint8Size + 2 + z.r.Msgsize() | |||
return | |||
} | |||
// Deprecated: DecodeMsg implements msgp.Decodable | |||
func (z *contype) DecodeMsg(dc *msgp.Reader) (err error) { | |||
{ | |||
var zajw uint8 | |||
zajw, err = dc.ReadUint8() | |||
(*z) = contype(zajw) | |||
} | |||
if err != nil { | |||
return | |||
} | |||
return | |||
} | |||
// Deprecated: EncodeMsg implements msgp.Encodable | |||
func (z contype) EncodeMsg(en *msgp.Writer) (err error) { | |||
err = en.WriteUint8(uint8(z)) | |||
if err != nil { | |||
return | |||
} | |||
return | |||
} | |||
// Deprecated: MarshalMsg implements msgp.Marshaler | |||
func (z contype) MarshalMsg(b []byte) (o []byte, err error) { | |||
o = msgp.Require(b, z.Msgsize()) | |||
o = msgp.AppendUint8(o, uint8(z)) | |||
return | |||
} | |||
// Deprecated: UnmarshalMsg implements msgp.Unmarshaler | |||
func (z *contype) UnmarshalMsg(bts []byte) (o []byte, err error) { | |||
{ | |||
var zwht uint8 | |||
zwht, bts, err = msgp.ReadUint8Bytes(bts) | |||
(*z) = contype(zwht) | |||
} | |||
if err != nil { | |||
return | |||
} | |||
o = bts | |||
return | |||
} | |||
// Deprecated: Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message | |||
func (z contype) Msgsize() (s int) { | |||
s = msgp.Uint8Size | |||
return | |||
} | |||
// Deprecated: DecodeMsg implements msgp.Decodable | |||
func (z *roaringArray) DecodeMsg(dc *msgp.Reader) (err error) { | |||
var field []byte | |||
_ = field | |||
var zlqf uint32 | |||
zlqf, err = dc.ReadMapHeader() | |||
if err != nil { | |||
return | |||
} | |||
for zlqf > 0 { | |||
zlqf-- | |||
field, err = dc.ReadMapKeyPtr() | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "keys": | |||
var zdaf uint32 | |||
zdaf, err = dc.ReadArrayHeader() | |||
if err != nil { | |||
return | |||
} | |||
if cap(z.keys) >= int(zdaf) { | |||
z.keys = (z.keys)[:zdaf] | |||
} else { | |||
z.keys = make([]uint16, zdaf) | |||
} | |||
for zhct := range z.keys { | |||
z.keys[zhct], err = dc.ReadUint16() | |||
if err != nil { | |||
return | |||
} | |||
} | |||
case "needCopyOnWrite": | |||
var zpks uint32 | |||
zpks, err = dc.ReadArrayHeader() | |||
if err != nil { | |||
return | |||
} | |||
if cap(z.needCopyOnWrite) >= int(zpks) { | |||
z.needCopyOnWrite = (z.needCopyOnWrite)[:zpks] | |||
} else { | |||
z.needCopyOnWrite = make([]bool, zpks) | |||
} | |||
for zcua := range z.needCopyOnWrite { | |||
z.needCopyOnWrite[zcua], err = dc.ReadBool() | |||
if err != nil { | |||
return | |||
} | |||
} | |||
case "copyOnWrite": | |||
z.copyOnWrite, err = dc.ReadBool() | |||
if err != nil { | |||
return | |||
} | |||
case "conserz": | |||
var zjfb uint32 | |||
zjfb, err = dc.ReadArrayHeader() | |||
if err != nil { | |||
return | |||
} | |||
if cap(z.conserz) >= int(zjfb) { | |||
z.conserz = (z.conserz)[:zjfb] | |||
} else { | |||
z.conserz = make([]containerSerz, zjfb) | |||
} | |||
for zxhx := range z.conserz { | |||
var zcxo uint32 | |||
zcxo, err = dc.ReadMapHeader() | |||
if err != nil { | |||
return | |||
} | |||
for zcxo > 0 { | |||
zcxo-- | |||
field, err = dc.ReadMapKeyPtr() | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "t": | |||
{ | |||
var zeff uint8 | |||
zeff, err = dc.ReadUint8() | |||
z.conserz[zxhx].t = contype(zeff) | |||
} | |||
if err != nil { | |||
return | |||
} | |||
case "r": | |||
err = z.conserz[zxhx].r.DecodeMsg(dc) | |||
if err != nil { | |||
return | |||
} | |||
default: | |||
err = dc.Skip() | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
} | |||
default: | |||
err = dc.Skip() | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
return | |||
} | |||
// Deprecated: EncodeMsg implements msgp.Encodable | |||
func (z *roaringArray) EncodeMsg(en *msgp.Writer) (err error) { | |||
// map header, size 4 | |||
// write "keys" | |||
err = en.Append(0x84, 0xa4, 0x6b, 0x65, 0x79, 0x73) | |||
if err != nil { | |||
return err | |||
} | |||
err = en.WriteArrayHeader(uint32(len(z.keys))) | |||
if err != nil { | |||
return | |||
} | |||
for zhct := range z.keys { | |||
err = en.WriteUint16(z.keys[zhct]) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
// write "needCopyOnWrite" | |||
err = en.Append(0xaf, 0x6e, 0x65, 0x65, 0x64, 0x43, 0x6f, 0x70, 0x79, 0x4f, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65) | |||
if err != nil { | |||
return err | |||
} | |||
err = en.WriteArrayHeader(uint32(len(z.needCopyOnWrite))) | |||
if err != nil { | |||
return | |||
} | |||
for zcua := range z.needCopyOnWrite { | |||
err = en.WriteBool(z.needCopyOnWrite[zcua]) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
// write "copyOnWrite" | |||
err = en.Append(0xab, 0x63, 0x6f, 0x70, 0x79, 0x4f, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65) | |||
if err != nil { | |||
return err | |||
} | |||
err = en.WriteBool(z.copyOnWrite) | |||
if err != nil { | |||
return | |||
} | |||
// write "conserz" | |||
err = en.Append(0xa7, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x72, 0x7a) | |||
if err != nil { | |||
return err | |||
} | |||
err = en.WriteArrayHeader(uint32(len(z.conserz))) | |||
if err != nil { | |||
return | |||
} | |||
for zxhx := range z.conserz { | |||
// map header, size 2 | |||
// write "t" | |||
err = en.Append(0x82, 0xa1, 0x74) | |||
if err != nil { | |||
return err | |||
} | |||
err = en.WriteUint8(uint8(z.conserz[zxhx].t)) | |||
if err != nil { | |||
return | |||
} | |||
// write "r" | |||
err = en.Append(0xa1, 0x72) | |||
if err != nil { | |||
return err | |||
} | |||
err = z.conserz[zxhx].r.EncodeMsg(en) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
return | |||
} | |||
// Deprecated: MarshalMsg implements msgp.Marshaler | |||
func (z *roaringArray) MarshalMsg(b []byte) (o []byte, err error) { | |||
o = msgp.Require(b, z.Msgsize()) | |||
// map header, size 4 | |||
// string "keys" | |||
o = append(o, 0x84, 0xa4, 0x6b, 0x65, 0x79, 0x73) | |||
o = msgp.AppendArrayHeader(o, uint32(len(z.keys))) | |||
for zhct := range z.keys { | |||
o = msgp.AppendUint16(o, z.keys[zhct]) | |||
} | |||
// string "needCopyOnWrite" | |||
o = append(o, 0xaf, 0x6e, 0x65, 0x65, 0x64, 0x43, 0x6f, 0x70, 0x79, 0x4f, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65) | |||
o = msgp.AppendArrayHeader(o, uint32(len(z.needCopyOnWrite))) | |||
for zcua := range z.needCopyOnWrite { | |||
o = msgp.AppendBool(o, z.needCopyOnWrite[zcua]) | |||
} | |||
// string "copyOnWrite" | |||
o = append(o, 0xab, 0x63, 0x6f, 0x70, 0x79, 0x4f, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65) | |||
o = msgp.AppendBool(o, z.copyOnWrite) | |||
// string "conserz" | |||
o = append(o, 0xa7, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x72, 0x7a) | |||
o = msgp.AppendArrayHeader(o, uint32(len(z.conserz))) | |||
for zxhx := range z.conserz { | |||
// map header, size 2 | |||
// string "t" | |||
o = append(o, 0x82, 0xa1, 0x74) | |||
o = msgp.AppendUint8(o, uint8(z.conserz[zxhx].t)) | |||
// string "r" | |||
o = append(o, 0xa1, 0x72) | |||
o, err = z.conserz[zxhx].r.MarshalMsg(o) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
return | |||
} | |||
// Deprecated: UnmarshalMsg implements msgp.Unmarshaler | |||
func (z *roaringArray) UnmarshalMsg(bts []byte) (o []byte, err error) { | |||
var field []byte | |||
_ = field | |||
var zrsw uint32 | |||
zrsw, bts, err = msgp.ReadMapHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
for zrsw > 0 { | |||
zrsw-- | |||
field, bts, err = msgp.ReadMapKeyZC(bts) | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "keys": | |||
var zxpk uint32 | |||
zxpk, bts, err = msgp.ReadArrayHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
if cap(z.keys) >= int(zxpk) { | |||
z.keys = (z.keys)[:zxpk] | |||
} else { | |||
z.keys = make([]uint16, zxpk) | |||
} | |||
for zhct := range z.keys { | |||
z.keys[zhct], bts, err = msgp.ReadUint16Bytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
case "needCopyOnWrite": | |||
var zdnj uint32 | |||
zdnj, bts, err = msgp.ReadArrayHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
if cap(z.needCopyOnWrite) >= int(zdnj) { | |||
z.needCopyOnWrite = (z.needCopyOnWrite)[:zdnj] | |||
} else { | |||
z.needCopyOnWrite = make([]bool, zdnj) | |||
} | |||
for zcua := range z.needCopyOnWrite { | |||
z.needCopyOnWrite[zcua], bts, err = msgp.ReadBoolBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
case "copyOnWrite": | |||
z.copyOnWrite, bts, err = msgp.ReadBoolBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
case "conserz": | |||
var zobc uint32 | |||
zobc, bts, err = msgp.ReadArrayHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
if cap(z.conserz) >= int(zobc) { | |||
z.conserz = (z.conserz)[:zobc] | |||
} else { | |||
z.conserz = make([]containerSerz, zobc) | |||
} | |||
for zxhx := range z.conserz { | |||
var zsnv uint32 | |||
zsnv, bts, err = msgp.ReadMapHeaderBytes(bts) | |||
if err != nil { | |||
return | |||
} | |||
for zsnv > 0 { | |||
zsnv-- | |||
field, bts, err = msgp.ReadMapKeyZC(bts) | |||
if err != nil { | |||
return | |||
} | |||
switch msgp.UnsafeString(field) { | |||
case "t": | |||
{ | |||
var zkgt uint8 | |||
zkgt, bts, err = msgp.ReadUint8Bytes(bts) | |||
z.conserz[zxhx].t = contype(zkgt) | |||
} | |||
if err != nil { | |||
return | |||
} | |||
case "r": | |||
bts, err = z.conserz[zxhx].r.UnmarshalMsg(bts) | |||
if err != nil { | |||
return | |||
} | |||
default: | |||
bts, err = msgp.Skip(bts) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
} | |||
default: | |||
bts, err = msgp.Skip(bts) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
} | |||
o = bts | |||
return | |||
} | |||
// Deprecated: Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message | |||
func (z *roaringArray) Msgsize() (s int) { | |||
s = 1 + 5 + msgp.ArrayHeaderSize + (len(z.keys) * (msgp.Uint16Size)) + 16 + msgp.ArrayHeaderSize + (len(z.needCopyOnWrite) * (msgp.BoolSize)) + 12 + msgp.BoolSize + 8 + msgp.ArrayHeaderSize | |||
for zxhx := range z.conserz { | |||
s += 1 + 2 + msgp.Uint8Size + 2 + z.conserz[zxhx].r.Msgsize() | |||
} | |||
return | |||
} |
@@ -44,16 +44,11 @@ import ( | |||
"unsafe" | |||
) | |||
//go:generate msgp -unexported | |||
// runContainer16 does run-length encoding of sets of | |||
// uint16 integers. | |||
type runContainer16 struct { | |||
iv []interval16 | |||
card int64 | |||
// avoid allocation during search | |||
myOpts searchOptions `msg:"-"` | |||
} | |||
// interval16 is the internal to runContainer16 | |||
@@ -120,8 +115,6 @@ func (p uint16Slice) Less(i, j int) bool { return p[i] < p[j] } | |||
// Swap swaps elements i and j. | |||
func (p uint16Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } | |||
//msgp:ignore addHelper | |||
// addHelper helps build a runContainer16. | |||
type addHelper16 struct { | |||
runstart uint16 | |||
@@ -617,10 +610,7 @@ func (rc *runContainer16) unionCardinality(b *runContainer16) uint64 { | |||
// indexOfIntervalAtOrAfter is a helper for union. | |||
func (rc *runContainer16) indexOfIntervalAtOrAfter(key int64, startIndex int64) int64 { | |||
rc.myOpts.startIndex = startIndex | |||
rc.myOpts.endxIndex = 0 | |||
w, already, _ := rc.search(key, &rc.myOpts) | |||
w, already, _ := rc.searchRange(key, startIndex, 0) | |||
if already { | |||
return w | |||
} | |||
@@ -844,7 +834,7 @@ toploop: | |||
// get returns true iff key is in the container. | |||
func (rc *runContainer16) contains(key uint16) bool { | |||
_, in, _ := rc.search(int64(key), nil) | |||
_, in, _ := rc.search(int64(key)) | |||
return in | |||
} | |||
@@ -853,22 +843,7 @@ func (rc *runContainer16) numIntervals() int { | |||
return len(rc.iv) | |||
} | |||
// searchOptions allows us to accelerate search with | |||
// prior knowledge of (mostly lower) bounds. This is used by Union | |||
// and Intersect. | |||
type searchOptions struct { | |||
// start here instead of at 0 | |||
startIndex int64 | |||
// upper bound instead of len(rc.iv); | |||
// endxIndex == 0 means ignore the bound and use | |||
// endxIndex == n ==len(rc.iv) which is also | |||
// naturally the default for search() | |||
// when opt = nil. | |||
endxIndex int64 | |||
} | |||
// search returns alreadyPresent to indicate if the | |||
// searchRange returns alreadyPresent to indicate if the | |||
// key is already in one of our interval16s. | |||
// | |||
// If key is alreadyPresent, then whichInterval16 tells | |||
@@ -892,24 +867,16 @@ type searchOptions struct { | |||
// | |||
// runContainer16.search always returns whichInterval16 < len(rc.iv). | |||
// | |||
// If not nil, opts can be used to further restrict | |||
// the search space. | |||
// The search space is from startIndex to endxIndex. If endxIndex is set to zero, then there | |||
// no upper bound. | |||
// | |||
func (rc *runContainer16) search(key int64, opts *searchOptions) (whichInterval16 int64, alreadyPresent bool, numCompares int) { | |||
func (rc *runContainer16) searchRange(key int64, startIndex int64, endxIndex int64) (whichInterval16 int64, alreadyPresent bool, numCompares int) { | |||
n := int64(len(rc.iv)) | |||
if n == 0 { | |||
return -1, false, 0 | |||
} | |||
startIndex := int64(0) | |||
endxIndex := n | |||
if opts != nil { | |||
startIndex = opts.startIndex | |||
// let endxIndex == 0 mean no effect | |||
if opts.endxIndex > 0 { | |||
endxIndex = opts.endxIndex | |||
} | |||
if endxIndex == 0 { | |||
endxIndex = n | |||
} | |||
// sort.Search returns the smallest index i | |||
@@ -979,6 +946,34 @@ func (rc *runContainer16) search(key int64, opts *searchOptions) (whichInterval1 | |||
return | |||
} | |||
// search returns alreadyPresent to indicate if the | |||
// key is already in one of our interval16s. | |||
// | |||
// If key is alreadyPresent, then whichInterval16 tells | |||
// you where. | |||
// | |||
// If key is not already present, then whichInterval16 is | |||
// set as follows: | |||
// | |||
// a) whichInterval16 == len(rc.iv)-1 if key is beyond our | |||
// last interval16 in rc.iv; | |||
// | |||
// b) whichInterval16 == -1 if key is before our first | |||
// interval16 in rc.iv; | |||
// | |||
// c) whichInterval16 is set to the minimum index of rc.iv | |||
// which comes strictly before the key; | |||
// so rc.iv[whichInterval16].last < key, | |||
// and if whichInterval16+1 exists, then key < rc.iv[whichInterval16+1].start | |||
// (Note that whichInterval16+1 won't exist when | |||
// whichInterval16 is the last interval.) | |||
// | |||
// runContainer16.search always returns whichInterval16 < len(rc.iv). | |||
// | |||
func (rc *runContainer16) search(key int64) (whichInterval16 int64, alreadyPresent bool, numCompares int) { | |||
return rc.searchRange(key, 0, 0) | |||
} | |||
// cardinality returns the count of the integers stored in the | |||
// runContainer16. | |||
func (rc *runContainer16) cardinality() int64 { | |||
@@ -1072,7 +1067,7 @@ func (rc *runContainer16) Add(k uint16) (wasNew bool) { | |||
k64 := int64(k) | |||
index, present, _ := rc.search(k64, nil) | |||
index, present, _ := rc.search(k64) | |||
if present { | |||
return // already there | |||
} | |||
@@ -1147,8 +1142,6 @@ func (rc *runContainer16) Add(k uint16) (wasNew bool) { | |||
return | |||
} | |||
//msgp:ignore runIterator | |||
// runIterator16 advice: you must call hasNext() | |||
// before calling next()/peekNext() to insure there are contents. | |||
type runIterator16 struct { | |||
@@ -1207,13 +1200,8 @@ func (ri *runIterator16) advanceIfNeeded(minval uint16) { | |||
return | |||
} | |||
opt := &searchOptions{ | |||
startIndex: ri.curIndex, | |||
endxIndex: int64(len(ri.rc.iv)), | |||
} | |||
// interval cannot be -1 because of minval > peekNext | |||
interval, isPresent, _ := ri.rc.search(int64(minval), opt) | |||
interval, isPresent, _ := ri.rc.searchRange(int64(minval), ri.curIndex, int64(len(ri.rc.iv))) | |||
// if the minval is present, set the curPosIndex at the right position | |||
if isPresent { | |||
@@ -1366,7 +1354,7 @@ func (ri *runIterator16) nextMany64(hs uint64, buf []uint64) int { | |||
func (rc *runContainer16) removeKey(key uint16) (wasPresent bool) { | |||
var index int64 | |||
index, wasPresent, _ = rc.search(int64(key), nil) | |||
index, wasPresent, _ = rc.search(int64(key)) | |||
if !wasPresent { | |||
return // already removed, nothing to do. | |||
} | |||
@@ -1457,12 +1445,8 @@ func intersectWithLeftover16(astart, alast, bstart, blast int64) (isOverlap, isL | |||
return | |||
} | |||
func (rc *runContainer16) findNextIntervalThatIntersectsStartingFrom(startIndex int64, key int64) (index int64, done bool) { | |||
rc.myOpts.startIndex = startIndex | |||
rc.myOpts.endxIndex = 0 | |||
w, _, _ := rc.search(key, &rc.myOpts) | |||
func (rc *runContainer16) findNextIntervalThatIntersectsStartingFrom(startIndex int64, key int64) (index int64, done bool) { | |||
w, _, _ := rc.searchRange(key, startIndex, 0) | |||
// rc.search always returns w < len(rc.iv) | |||
if w < startIndex { | |||
// not found and comes before lower bound startIndex, | |||
@@ -1603,8 +1587,8 @@ func (rc *runContainer16) isubtract(del interval16) { | |||
} | |||
// INVAR there is some intersection between rc and del | |||
istart, startAlready, _ := rc.search(int64(del.start), nil) | |||
ilast, lastAlready, _ := rc.search(int64(del.last()), nil) | |||
istart, startAlready, _ := rc.search(int64(del.start)) | |||
ilast, lastAlready, _ := rc.search(int64(del.last())) | |||
rc.card = -1 | |||
if istart == -1 { | |||
if ilast == n-1 && !lastAlready { | |||
@@ -2356,7 +2340,7 @@ func (rc *runContainer16) getCardinality() int { | |||
func (rc *runContainer16) rank(x uint16) int { | |||
n := int64(len(rc.iv)) | |||
xx := int64(x) | |||
w, already, _ := rc.search(xx, nil) | |||
w, already, _ := rc.search(xx) | |||
if w < 0 { | |||
return 0 | |||
} |
@@ -3,8 +3,6 @@ package roaring | |||
import ( | |||
"encoding/binary" | |||
"io" | |||
"github.com/tinylib/msgp/msgp" | |||
) | |||
// writeTo for runContainer16 follows this | |||
@@ -19,16 +17,3 @@ func (b *runContainer16) writeTo(stream io.Writer) (int, error) { | |||
} | |||
return stream.Write(buf) | |||
} | |||
func (b *runContainer16) writeToMsgpack(stream io.Writer) (int, error) { | |||
bts, err := b.MarshalMsg(nil) | |||
if err != nil { | |||
return 0, err | |||
} | |||
return stream.Write(bts) | |||
} | |||
func (b *runContainer16) readFromMsgpack(stream io.Reader) (int, error) { | |||
err := msgp.Decode(stream, b) | |||
return 0, err | |||
} |
@@ -177,6 +177,7 @@ func IsPrintableASCII(str string) bool | |||
func IsRFC3339(str string) bool | |||
func IsRFC3339WithoutZone(str string) bool | |||
func IsRGBcolor(str string) bool | |||
func IsRegex(str string) bool | |||
func IsRequestURI(rawurl string) bool | |||
func IsRequestURL(rawurl string) bool | |||
func IsRipeMD128(str string) bool | |||
@@ -203,6 +204,7 @@ func IsUUID(str string) bool | |||
func IsUUIDv3(str string) bool | |||
func IsUUIDv4(str string) bool | |||
func IsUUIDv5(str string) bool | |||
func IsULID(str string) bool | |||
func IsUnixTime(str string) bool | |||
func IsUpperCase(str string) bool | |||
func IsVariableWidth(str string) bool | |||
@@ -382,6 +384,7 @@ Here is a list of available validators for struct fields (validator - used funct | |||
"rfc3339WithoutZone": IsRFC3339WithoutZone, | |||
"ISO3166Alpha2": IsISO3166Alpha2, | |||
"ISO3166Alpha3": IsISO3166Alpha3, | |||
"ulid": IsULID, | |||
``` | |||
Validators with parameters | |||
@@ -42,6 +42,8 @@ const ( | |||
SSN string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$` | |||
WinPath string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$` | |||
UnixPath string = `^(/[^/\x00]*)+/?$` | |||
WinARPath string = `^(?:(?:[a-zA-Z]:|\\\\[a-z0-9_.$●-]+\\[a-z0-9_.$●-]+)\\|\\?[^\\/:*?"<>|\r\n]+\\?)(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$` | |||
UnixARPath string = `^((\.{0,2}/)?([^/\x00]*))+/?$` | |||
Semver string = "^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$" | |||
tagName string = "valid" | |||
hasLowerCase string = ".*[[:lower:]]" | |||
@@ -50,6 +52,7 @@ const ( | |||
hasWhitespaceOnly string = "^[[:space:]]+$" | |||
IMEI string = "^[0-9a-f]{14}$|^\\d{15}$|^\\d{18}$" | |||
IMSI string = "^\\d{14,15}$" | |||
E164 string = `^\+?[1-9]\d{1,14}$` | |||
) | |||
// Used by IsFilePath func | |||
@@ -97,6 +100,8 @@ var ( | |||
rxSSN = regexp.MustCompile(SSN) | |||
rxWinPath = regexp.MustCompile(WinPath) | |||
rxUnixPath = regexp.MustCompile(UnixPath) | |||
rxARWinPath = regexp.MustCompile(WinARPath) | |||
rxARUnixPath = regexp.MustCompile(UnixARPath) | |||
rxSemver = regexp.MustCompile(Semver) | |||
rxHasLowerCase = regexp.MustCompile(hasLowerCase) | |||
rxHasUpperCase = regexp.MustCompile(hasUpperCase) | |||
@@ -104,4 +109,5 @@ var ( | |||
rxHasWhitespaceOnly = regexp.MustCompile(hasWhitespaceOnly) | |||
rxIMEI = regexp.MustCompile(IMEI) | |||
rxIMSI = regexp.MustCompile(IMSI) | |||
rxE164 = regexp.MustCompile(E164) | |||
) |
@@ -165,6 +165,7 @@ var TagMap = map[string]Validator{ | |||
"ISO3166Alpha3": IsISO3166Alpha3, | |||
"ISO4217": IsISO4217, | |||
"IMEI": IsIMEI, | |||
"ulid": IsULID, | |||
} | |||
// ISO3166Entry stores country codes |
@@ -361,9 +361,96 @@ func IsUUID(str string) bool { | |||
return rxUUID.MatchString(str) | |||
} | |||
// Byte to index table for O(1) lookups when unmarshaling. | |||
// We use 0xFF as sentinel value for invalid indexes. | |||
var ulidDec = [...]byte{ | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, | |||
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, | |||
0x0F, 0x10, 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14, 0x15, 0xFF, | |||
0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C, 0x1D, 0x1E, | |||
0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, | |||
0x0D, 0x0E, 0x0F, 0x10, 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14, | |||
0x15, 0xFF, 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C, | |||
0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
} | |||
// EncodedSize is the length of a text encoded ULID. | |||
const ulidEncodedSize = 26 | |||
// IsULID checks if the string is a ULID. | |||
// | |||
// Implementation got from: | |||
// https://github.com/oklog/ulid (Apache-2.0 License) | |||
// | |||
func IsULID(str string) bool { | |||
// Check if a base32 encoded ULID is the right length. | |||
if len(str) != ulidEncodedSize { | |||
return false | |||
} | |||
// Check if all the characters in a base32 encoded ULID are part of the | |||
// expected base32 character set. | |||
if ulidDec[str[0]] == 0xFF || | |||
ulidDec[str[1]] == 0xFF || | |||
ulidDec[str[2]] == 0xFF || | |||
ulidDec[str[3]] == 0xFF || | |||
ulidDec[str[4]] == 0xFF || | |||
ulidDec[str[5]] == 0xFF || | |||
ulidDec[str[6]] == 0xFF || | |||
ulidDec[str[7]] == 0xFF || | |||
ulidDec[str[8]] == 0xFF || | |||
ulidDec[str[9]] == 0xFF || | |||
ulidDec[str[10]] == 0xFF || | |||
ulidDec[str[11]] == 0xFF || | |||
ulidDec[str[12]] == 0xFF || | |||
ulidDec[str[13]] == 0xFF || | |||
ulidDec[str[14]] == 0xFF || | |||
ulidDec[str[15]] == 0xFF || | |||
ulidDec[str[16]] == 0xFF || | |||
ulidDec[str[17]] == 0xFF || | |||
ulidDec[str[18]] == 0xFF || | |||
ulidDec[str[19]] == 0xFF || | |||
ulidDec[str[20]] == 0xFF || | |||
ulidDec[str[21]] == 0xFF || | |||
ulidDec[str[22]] == 0xFF || | |||
ulidDec[str[23]] == 0xFF || | |||
ulidDec[str[24]] == 0xFF || | |||
ulidDec[str[25]] == 0xFF { | |||
return false | |||
} | |||
// Check if the first character in a base32 encoded ULID will overflow. This | |||
// happens because the base32 representation encodes 130 bits, while the | |||
// ULID is only 128 bits. | |||
// | |||
// See https://github.com/oklog/ulid/issues/9 for details. | |||
if str[0] > '7' { | |||
return false | |||
} | |||
return true | |||
} | |||
// IsCreditCard checks if the string is a credit card. | |||
func IsCreditCard(str string) bool { | |||
sanitized := notNumberRegexp.ReplaceAllString(str, "") | |||
sanitized := whiteSpacesAndMinus.ReplaceAllString(str, "") | |||
if !rxCreditCard.MatchString(sanitized) { | |||
return false | |||
} | |||
@@ -509,6 +596,27 @@ func IsFilePath(str string) (bool, int) { | |||
return false, Unknown | |||
} | |||
//IsWinFilePath checks both relative & absolute paths in Windows | |||
func IsWinFilePath(str string) bool { | |||
if rxARWinPath.MatchString(str) { | |||
//check windows path limit see: | |||
// http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath | |||
if len(str[3:]) > 32767 { | |||
return false | |||
} | |||
return true | |||
} | |||
return false | |||
} | |||
//IsUnixFilePath checks both relative & absolute paths in Unix | |||
func IsUnixFilePath(str string) bool { | |||
if rxARUnixPath.MatchString(str) { | |||
return true | |||
} | |||
return false | |||
} | |||
// IsDataURI checks if a string is base64 encoded data URI such as an image | |||
func IsDataURI(str string) bool { | |||
dataURI := strings.Split(str, ",") | |||
@@ -586,11 +694,13 @@ func IsHash(str string, algorithm string) bool { | |||
len = "40" | |||
} else if algo == "tiger192" { | |||
len = "48" | |||
} else if algo == "sha256" { | |||
} else if algo == "sha3-224" { | |||
len = "56" | |||
} else if algo == "sha256" || algo == "sha3-256" { | |||
len = "64" | |||
} else if algo == "sha384" { | |||
} else if algo == "sha384" || algo == "sha3-384" { | |||
len = "96" | |||
} else if algo == "sha512" { | |||
} else if algo == "sha512" || algo == "sha3-512" { | |||
len = "128" | |||
} else { | |||
return false | |||
@@ -599,6 +709,26 @@ func IsHash(str string, algorithm string) bool { | |||
return Matches(str, "^[a-f0-9]{"+len+"}$") | |||
} | |||
// IsSHA3224 checks is a string is a SHA3-224 hash. Alias for `IsHash(str, "sha3-224")` | |||
func IsSHA3224(str string) bool { | |||
return IsHash(str, "sha3-224") | |||
} | |||
// IsSHA3256 checks is a string is a SHA3-256 hash. Alias for `IsHash(str, "sha3-256")` | |||
func IsSHA3256(str string) bool { | |||
return IsHash(str, "sha3-256") | |||
} | |||
// IsSHA3384 checks is a string is a SHA3-384 hash. Alias for `IsHash(str, "sha3-384")` | |||
func IsSHA3384(str string) bool { | |||
return IsHash(str, "sha3-384") | |||
} | |||
// IsSHA3512 checks is a string is a SHA3-512 hash. Alias for `IsHash(str, "sha3-512")` | |||
func IsSHA3512(str string) bool { | |||
return IsHash(str, "sha3-512") | |||
} | |||
// IsSHA512 checks is a string is a SHA512 hash. Alias for `IsHash(str, "sha512")` | |||
func IsSHA512(str string) bool { | |||
return IsHash(str, "sha512") | |||
@@ -819,6 +949,14 @@ func IsRsaPublicKey(str string, keylen int) bool { | |||
return bitlen == int(keylen) | |||
} | |||
// IsRegex checks if a give string is a valid regex with RE2 syntax or not | |||
func IsRegex(str string) bool { | |||
if _, err := regexp.Compile(str); err == nil { | |||
return true | |||
} | |||
return false | |||
} | |||
func toJSONName(tag string) string { | |||
if tag == "" { | |||
return "" | |||
@@ -1625,3 +1763,7 @@ func (sv stringValues) Len() int { return len(sv) } | |||
func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } | |||
func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) } | |||
func (sv stringValues) get(i int) string { return sv[i].String() } | |||
func IsE164(str string) bool { | |||
return rxE164.MatchString(str) | |||
} |
@@ -0,0 +1,3 @@ | |||
*.test | |||
*.out | |||
.devcontainer/ |
@@ -0,0 +1,21 @@ | |||
MIT License | |||
Copyright (c) 2021 Salvador Cavadini | |||
Permission is hereby granted, free of charge, to any person obtaining a copy | |||
of this software and associated documentation files (the "Software"), to deal | |||
in the Software without restriction, including without limitation the rights | |||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
copies of the Software, and to permit persons to whom the Software is | |||
furnished to do so, subject to the following conditions: | |||
The above copyright notice and this permission notice shall be included in all | |||
copies or substantial portions of the Software. | |||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
SOFTWARE. |
@@ -0,0 +1,52 @@ | |||
# garif | |||
A GO package to create and manipulate SARIF logs. | |||
SARIF, from _Static Analysis Results Interchange Format_, is a standard JSON-based format for the output of static analysis tools defined and promoted by [OASIS](https://www.oasis-open.org/). | |||
Current supported version of the standard is [SARIF-v2.1.0](https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html | |||
). | |||
## Usage | |||
The package provides access to every element of the SARIF model, therefore you are free to manipulate it at every detail. | |||
The package also provides constructors functions (`New...`) and decorators methods (`With...`) that simplify the creation of SARIF files for common use cases. | |||
Using these constructors and decorators we can easily create the example SARIF file of the [Microsoft SARIF pages](https://github.com/microsoft/sarif-tutorials/blob/master/docs/1-Introduction.md) | |||
```go | |||
import to `github.com/chavacava/garif` | |||
// ... | |||
rule := garif.NewRule("no-unused-vars"). | |||
WithHelpUri("https://eslint.org/docs/rules/no-unused-vars"). | |||
WithShortDescription("disallow unused variables"). | |||
WithProperties("category", "Variables") | |||
driver := garif.NewDriver("ESLint"). | |||
WithInformationUri("https://eslint.org"). | |||
WithRules(rule) | |||
run := garif.NewRun(NewTool(driver)). | |||
WithArtifactsURIs("file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js") | |||
run.WithResult(rule.Id, "'x' is assigned a value but never used.", "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js", 1, 5) | |||
logFile := garif.NewLogFile([]*Run{run}, Version210) | |||
logFile.Write(os.Stdout) | |||
``` | |||
## Why this package? | |||
This package was initiated during my works on adding to [`revive`](https://github.com/mgechev/revive) a SARIF output formatter. | |||
I've tried to use [go-sarif](https://github.com/owenrumney/go-sarif) by [Owen Rumney](https://github.com/owenrumney) but it is too focused in the use case of the static analyzer [tfsec](https://tfsec.dev) so I've decided to create a package flexible enough to generate SARIF files in broader cases. | |||
## More information about SARIF | |||
For more information about SARIF, you can visit the [Oasis Open](https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif) site. | |||
## Contributing | |||
Of course, contributions are welcome! |
@@ -0,0 +1,338 @@ | |||
package garif | |||
// NewAddress creates a valid Address | |||
func NewAddress() *Address { | |||
return &Address{} | |||
} | |||
// NewArtifact creates a valid Artifact | |||
func NewArtifact() *Artifact { | |||
return &Artifact{} | |||
} | |||
// NewArtifactChange creates a valid ArtifactChange | |||
func NewArtifactChange(location *ArtifactLocation, replacements ...*Replacement) *ArtifactChange { | |||
return &ArtifactChange{ | |||
ArtifactLocation: location, | |||
Replacements: replacements, | |||
} | |||
} | |||
// NewArtifactContent creates a valid ArtifactContent | |||
func NewArtifactContent() *ArtifactContent { | |||
return &ArtifactContent{} | |||
} | |||
// NewArtifactLocation creates a valid ArtifactLocation | |||
func NewArtifactLocation() *ArtifactLocation { | |||
return &ArtifactLocation{} | |||
} | |||
// NewAttachment creates a valid Attachment | |||
func NewAttachment(location *ArtifactLocation) *Attachment { | |||
return &Attachment{ArtifactLocation: location} | |||
} | |||
// NewCodeFlow creates a valid CodeFlow | |||
func NewCodeFlow(threadFlows ...*ThreadFlow) *CodeFlow { | |||
return &CodeFlow{ThreadFlows: threadFlows} | |||
} | |||
// NewConfigurationOverride creates a valid ConfigurationOverride | |||
func NewConfigurationOverride(configuration *ReportingConfiguration, descriptor *ReportingDescriptorReference) *ConfigurationOverride { | |||
return &ConfigurationOverride{ | |||
Configuration: configuration, | |||
Descriptor: descriptor, | |||
} | |||
} | |||
// NewConversion creates a valid Conversion | |||
func NewConversion(tool *Tool) *Conversion { | |||
return &Conversion{Tool: tool} | |||
} | |||
// NewEdge creates a valid Edge | |||
func NewEdge(id, sourceNodeId, targetNodeId string) *Edge { | |||
return &Edge{ | |||
Id: id, | |||
SourceNodeId: sourceNodeId, | |||
TargetNodeId: targetNodeId, | |||
} | |||
} | |||
// NewEdgeTraversal creates a valid EdgeTraversal | |||
func NewEdgeTraversal(edgeId string) *EdgeTraversal { | |||
return &EdgeTraversal{ | |||
EdgeId: edgeId, | |||
} | |||
} | |||
// NewException creates a valid Exception | |||
func NewException() *Exception { | |||
return &Exception{} | |||
} | |||
// NewExternalProperties creates a valid ExternalProperties | |||
func NewExternalProperties() *ExternalProperties { | |||
return &ExternalProperties{} | |||
} | |||
// NewExternalPropertyFileReference creates a valid ExternalPropertyFileReference | |||
func NewExternalPropertyFileReference() *ExternalPropertyFileReference { | |||
return &ExternalPropertyFileReference{} | |||
} | |||
// NewExternalPropertyFileReferences creates a valid ExternalPropertyFileReferences | |||
func NewExternalPropertyFileReferences() *ExternalPropertyFileReferences { | |||
return &ExternalPropertyFileReferences{} | |||
} | |||
// NewFix creates a valid Fix | |||
func NewFix(artifactChanges ...*ArtifactChange) *Fix { | |||
return &Fix{ | |||
ArtifactChanges: artifactChanges, | |||
} | |||
} | |||
// NewGraph creates a valid Graph | |||
func NewGraph() *Graph { | |||
return &Graph{} | |||
} | |||
// NewGraphTraversal creates a valid GraphTraversal | |||
func NewGraphTraversal() *GraphTraversal { | |||
return &GraphTraversal{} | |||
} | |||
// NewInvocation creates a valid Invocation | |||
func NewInvocation(executionSuccessful bool) *Invocation { | |||
return &Invocation{ | |||
ExecutionSuccessful: executionSuccessful, | |||
} | |||
} | |||
// NewLocation creates a valid Location | |||
func NewLocation() *Location { | |||
return &Location{} | |||
} | |||
// NewLocationRelationship creates a valid LocationRelationship | |||
func NewLocationRelationship(target int) *LocationRelationship { | |||
return &LocationRelationship{ | |||
Target: target, | |||
} | |||
} | |||
type LogFileVersion string | |||
const Version210 LogFileVersion = "2.1.0" | |||
// NewLogFile creates a valid LogFile | |||
func NewLogFile(runs []*Run, version LogFileVersion) *LogFile { | |||
return &LogFile{ | |||
Runs: runs, | |||
Version: version, | |||
} | |||
} | |||
// NewLogicalLocation creates a valid LogicalLocation | |||
func NewLogicalLocation() *LogicalLocation { | |||
return &LogicalLocation{} | |||
} | |||
// NewMessage creates a valid Message | |||
func NewMessage() *Message { | |||
return &Message{} | |||
} | |||
// NewMessageFromText creates a valid Message with the given text | |||
func NewMessageFromText(text string) *Message { | |||
return &Message{ | |||
Text: text, | |||
} | |||
} | |||
// NewMultiformatMessageString creates a valid MultiformatMessageString | |||
func NewMultiformatMessageString(text string) *MultiformatMessageString { | |||
return &MultiformatMessageString{ | |||
Text: text, | |||
} | |||
} | |||
// NewNode creates a valid Node | |||
func NewNode(id string) *Node { | |||
return &Node{ | |||
Id: id, | |||
} | |||
} | |||
// NewNotification creates a valid Notification | |||
func NewNotification(message *Message) *Notification { | |||
return &Notification{ | |||
Message: message, | |||
} | |||
} | |||
// NewPhysicalLocation creates a valid PhysicalLocation | |||
func NewPhysicalLocation() *PhysicalLocation { | |||
return &PhysicalLocation{} | |||
} | |||
// NewPropertyBag creates a valid PropertyBag | |||
func NewPropertyBag() *PropertyBag { | |||
return &PropertyBag{} | |||
} | |||
// NewRectangle creates a valid Rectangle | |||
func NewRectangle() *Rectangle { | |||
return &Rectangle{} | |||
} | |||
// NewRegion creates a valid Region | |||
func NewRegion() *Region { | |||
return &Region{} | |||
} | |||
// NewReplacement creates a valid Replacement | |||
func NewReplacement(deletedRegion *Region) *Replacement { | |||
return &Replacement{ | |||
DeletedRegion: deletedRegion, | |||
} | |||
} | |||
// NewReportingConfiguration creates a valid ReportingConfiguration | |||
func NewReportingConfiguration() *ReportingConfiguration { | |||
return &ReportingConfiguration{} | |||
} | |||
// NewReportingDescriptor creates a valid ReportingDescriptor | |||
func NewReportingDescriptor(id string) *ReportingDescriptor { | |||
return &ReportingDescriptor{ | |||
Id: id, | |||
} | |||
} | |||
// NewRule is an alias for NewReportingDescriptor | |||
func NewRule(id string) *ReportingDescriptor { | |||
return NewReportingDescriptor(id) | |||
} | |||
// NewReportingDescriptorReference creates a valid ReportingDescriptorReference | |||
func NewReportingDescriptorReference() *ReportingDescriptorReference { | |||
return &ReportingDescriptorReference{} | |||
} | |||
// NewReportingDescriptorRelationship creates a valid ReportingDescriptorRelationship | |||
func NewReportingDescriptorRelationship(target *ReportingDescriptorReference) *ReportingDescriptorRelationship { | |||
return &ReportingDescriptorRelationship{ | |||
Target: target, | |||
} | |||
} | |||
// NewResult creates a valid Result | |||
func NewResult(message *Message) *Result { | |||
return &Result{ | |||
Message: message, | |||
} | |||
} | |||
// NewResultProvenance creates a valid ResultProvenance | |||
func NewResultProvenance() *ResultProvenance { | |||
return &ResultProvenance{} | |||
} | |||
// NewRun creates a valid Run | |||
func NewRun(tool *Tool) *Run { | |||
return &Run{ | |||
Tool: tool, | |||
} | |||
} | |||
// NewRunAutomationDetails creates a valid RunAutomationDetails | |||
func NewRunAutomationDetails() *RunAutomationDetails { | |||
return &RunAutomationDetails{} | |||
} | |||
// New creates a valid | |||
func NewSpecialLocations() *SpecialLocations { | |||
return &SpecialLocations{} | |||
} | |||
// NewStack creates a valid Stack | |||
func NewStack(frames ...*StackFrame) *Stack { | |||
return &Stack{ | |||
Frames: frames, | |||
} | |||
} | |||
// NewStackFrame creates a valid StackFrame | |||
func NewStackFrame() *StackFrame { | |||
return &StackFrame{} | |||
} | |||
// NewSuppression creates a valid Suppression | |||
func NewSuppression(kind string) *Suppression { | |||
return &Suppression{ | |||
Kind: kind, | |||
} | |||
} | |||
// NewThreadFlow creates a valid ThreadFlow | |||
func NewThreadFlow(locations []*ThreadFlowLocation) *ThreadFlow { | |||
return &ThreadFlow{ | |||
Locations: locations, | |||
} | |||
} | |||
// NewThreadFlowLocation creates a valid ThreadFlowLocation | |||
func NewThreadFlowLocation() *ThreadFlowLocation { | |||
return &ThreadFlowLocation{} | |||
} | |||
// NewTool creates a valid Tool | |||
func NewTool(driver *ToolComponent) *Tool { | |||
return &Tool{ | |||
Driver: driver, | |||
} | |||
} | |||
// NewToolComponent creates a valid ToolComponent | |||
func NewToolComponent(name string) *ToolComponent { | |||
return &ToolComponent{ | |||
Name: name, | |||
} | |||
} | |||
// NewDriver is an alias for NewToolComponent | |||
func NewDriver(name string) *ToolComponent { | |||
return NewToolComponent(name) | |||
} | |||
// NewToolComponentReference creates a valid ToolComponentReference | |||
func NewToolComponentReference() *ToolComponentReference { | |||
return &ToolComponentReference{} | |||
} | |||
// NewTranslationMetadata creates a valid TranslationMetadata | |||
func NewTranslationMetadata(name string) *TranslationMetadata { | |||
return &TranslationMetadata{ | |||
Name: name, | |||
} | |||
} | |||
// NewVersionControlDetails creates a valid VersionControlDetails | |||
func NewVersionControlDetails(repositoryUri string) *VersionControlDetails { | |||
return &VersionControlDetails{ | |||
RepositoryUri: repositoryUri, | |||
} | |||
} | |||
// NewWebRequest creates a valid WebRequest | |||
func NewWebRequest() *WebRequest { | |||
return &WebRequest{} | |||
} | |||
// NewWebResponse creates a valid WebResponse | |||
func NewWebResponse() *WebResponse { | |||
return &WebResponse{} | |||
} |
@@ -0,0 +1,94 @@ | |||
package garif | |||
// WithLineColumn sets a physical location with the given line and column | |||
func (l *Location) WithLineColumn(line, column int) *Location { | |||
if l.PhysicalLocation == nil { | |||
l.PhysicalLocation = NewPhysicalLocation() | |||
} | |||
l.PhysicalLocation.Region = NewRegion() | |||
l.PhysicalLocation.Region.StartLine = line | |||
l.PhysicalLocation.Region.StartColumn = column | |||
return l | |||
} | |||
// WithURI sets a physical location with the given URI | |||
func (l *Location) WithURI(uri string) *Location { | |||
if l.PhysicalLocation == nil { | |||
l.PhysicalLocation = NewPhysicalLocation() | |||
} | |||
l.PhysicalLocation.ArtifactLocation = NewArtifactLocation() | |||
l.PhysicalLocation.ArtifactLocation.Uri = uri | |||
return l | |||
} | |||
// WithKeyValue sets (overwrites) the value of the given key | |||
func (b PropertyBag) WithKeyValue(key string, value interface{}) PropertyBag { | |||
b[key] = value | |||
return b | |||
} | |||
// WithHelpUri sets the help URI for this ReportingDescriptor | |||
func (r *ReportingDescriptor) WithHelpUri(uri string) *ReportingDescriptor { | |||
r.HelpUri = uri | |||
return r | |||
} | |||
// WithProperties adds the key & value to the properties of this ReportingDescriptor | |||
func (r *ReportingDescriptor) WithProperties(key string, value interface{}) *ReportingDescriptor { | |||
if r.Properties == nil { | |||
r.Properties = NewPropertyBag() | |||
} | |||
r.Properties.WithKeyValue(key, value) | |||
return r | |||
} | |||
// WithArtifactsURIs adds the given URI as artifacts of this Run | |||
func (r *Run) WithArtifactsURIs(uris ...string) *Run { | |||
if r.Artifacts == nil { | |||
r.Artifacts = []*Artifact{} | |||
} | |||
for _, uri := range uris { | |||
a := NewArtifact() | |||
a.Location = NewArtifactLocation() | |||
a.Location.Uri = uri | |||
r.Artifacts = append(r.Artifacts, a) | |||
} | |||
return r | |||
} | |||
// WithResult adds a result to this Run | |||
func (r *Run) WithResult(ruleId string, message string, uri string, line int, column int) *Run { | |||
if r.Results == nil { | |||
r.Results = []*Result{} | |||
} | |||
msg := NewMessage() | |||
msg.Text = message | |||
result := NewResult(msg) | |||
location := NewLocation().WithURI(uri).WithLineColumn(line, column) | |||
result.Locations = append(result.Locations, location) | |||
result.RuleId = ruleId | |||
r.Results = append(r.Results, result) | |||
return r | |||
} | |||
// WithInformationUri sets the information URI | |||
func (t *ToolComponent) WithInformationUri(uri string) *ToolComponent { | |||
t.InformationUri = uri | |||
return t | |||
} | |||
// WithRules sets (overwrites) the rules | |||
func (t *ToolComponent) WithRules(rules ...*ReportingDescriptor) *ToolComponent { | |||
t.Rules = rules | |||
return t | |||
} |
@@ -0,0 +1,11 @@ | |||
// Package garif defines all the GO structures required to model a SARIF log file. | |||
// These structures were created using the JSON-schema sarif-schema-2.1.0.json of SARIF logfiles | |||
// available at https://github.com/oasis-tcs/sarif-spec/tree/master/Schemata. | |||
// | |||
// The package provides constructors for all structures (see constructors.go) These constructors | |||
// ensure that the returned structure instantiation is valid with respect to the JSON schema and | |||
// should be used in place of plain structure instantiation. | |||
// The root structure is LogFile. | |||
// | |||
// The package provides utility decorators for the most commonly used structures (see decorators.go) | |||
package garif |
@@ -0,0 +1,5 @@ | |||
module github.com/chavacava/garif | |||
go 1.16 | |||
require github.com/stretchr/testify v1.7.0 |
@@ -0,0 +1,11 @@ | |||
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/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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | |||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | |||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | |||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
@@ -0,0 +1,26 @@ | |||
package garif | |||
import ( | |||
"encoding/json" | |||
"io" | |||
) | |||
// Write writes the JSON | |||
func (l *LogFile) Write(w io.Writer) error { | |||
marshal, err := json.Marshal(l) | |||
if err != nil { | |||
return err | |||
} | |||
_, err = w.Write(marshal) | |||
return err | |||
} | |||
// PrettyWrite writes indented JSON | |||
func (l *LogFile) PrettyWrite(w io.Writer) error { | |||
marshal, err := json.MarshalIndent(l, "", " ") | |||
if err != nil { | |||
return err | |||
} | |||
_, err = w.Write(marshal) | |||
return err | |||
} |
@@ -0,0 +1,8 @@ | |||
/.idea | |||
/.connstr | |||
.vscode | |||
.terraform | |||
*.tfstate* | |||
*.log | |||
*.swp | |||
*~ |
@@ -0,0 +1,10 @@ | |||
linters: | |||
enable: | |||
# basic go linters | |||
- gofmt | |||
- golint | |||
- govet | |||
# sql related linters | |||
- rowserrcheck | |||
- sqlclosecheck |
@@ -6,19 +6,8 @@ import ( | |||
"context" | |||
"database/sql/driver" | |||
"errors" | |||
"fmt" | |||
) | |||
var _ driver.Connector = &accessTokenConnector{} | |||
// accessTokenConnector wraps Connector and injects a | |||
// fresh access token when connecting to the database | |||
type accessTokenConnector struct { | |||
Connector | |||
accessTokenProvider func() (string, error) | |||
} | |||
// NewAccessTokenConnector creates a new connector from a DSN and a token provider. | |||
// The token provider func will be called when a new connection is requested and should return a valid access token. | |||
// The returned connector may be used with sql.OpenDB. | |||
@@ -32,20 +21,10 @@ func NewAccessTokenConnector(dsn string, tokenProvider func() (string, error)) ( | |||
return nil, err | |||
} | |||
c := &accessTokenConnector{ | |||
Connector: *conn, | |||
accessTokenProvider: tokenProvider, | |||
} | |||
return c, nil | |||
} | |||
// Connect returns a new database connection | |||
func (c *accessTokenConnector) Connect(ctx context.Context) (driver.Conn, error) { | |||
var err error | |||
c.Connector.params.fedAuthAccessToken, err = c.accessTokenProvider() | |||
if err != nil { | |||
return nil, fmt.Errorf("mssql: error retrieving access token: %+v", err) | |||
conn.params.fedAuthLibrary = fedAuthLibrarySecurityToken | |||
conn.securityTokenProvider = func(ctx context.Context) (string, error) { | |||
return tokenProvider() | |||
} | |||
return c.Connector.Connect(ctx) | |||
return conn, nil | |||
} |
@@ -39,6 +39,9 @@ environment: | |||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 | |||
GOVERSION: 115 | |||
SQLINSTANCE: SQL2017 | |||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 | |||
GOVERSION: 116 | |||
SQLINSTANCE: SQL2017 | |||
install: | |||
- set GOROOT=c:\go%GOVERSION% |
@@ -48,8 +48,8 @@ type tdsBuffer struct { | |||
func newTdsBuffer(bufsize uint16, transport io.ReadWriteCloser) *tdsBuffer { | |||
return &tdsBuffer{ | |||
packetSize: int(bufsize), | |||
wbuf: make([]byte, 1<<16), | |||
rbuf: make([]byte, 1<<16), | |||
wbuf: make([]byte, bufsize), | |||
rbuf: make([]byte, bufsize), | |||
rpos: 8, | |||
transport: transport, | |||
} | |||
@@ -137,19 +137,28 @@ func (w *tdsBuffer) FinishPacket() error { | |||
var headerSize = binary.Size(header{}) | |||
func (r *tdsBuffer) readNextPacket() error { | |||
h := header{} | |||
var err error | |||
err = binary.Read(r.transport, binary.BigEndian, &h) | |||
buf := r.rbuf[:headerSize] | |||
_, err := io.ReadFull(r.transport, buf) | |||
if err != nil { | |||
return err | |||
} | |||
h := header{ | |||
PacketType: packetType(buf[0]), | |||
Status: buf[1], | |||
Size: binary.BigEndian.Uint16(buf[2:4]), | |||
Spid: binary.BigEndian.Uint16(buf[4:6]), | |||
PacketNo: buf[6], | |||
Pad: buf[7], | |||
} | |||
if int(h.Size) > r.packetSize { | |||
return errors.New("Invalid packet size, it is longer than buffer size") | |||
return errors.New("invalid packet size, it is longer than buffer size") | |||
} | |||
if headerSize > int(h.Size) { | |||
return errors.New("Invalid packet size, it is shorter than header size") | |||
return errors.New("invalid packet size, it is shorter than header size") | |||
} | |||
_, err = io.ReadFull(r.transport, r.rbuf[headerSize:h.Size]) | |||
//s := base64.StdEncoding.EncodeToString(r.rbuf[headerSize:h.Size]) | |||
//fmt.Print(s) | |||
if err != nil { | |||
return err | |||
} |
@@ -44,8 +44,9 @@ type BulkOptions struct { | |||
type DataValue interface{} | |||
const ( | |||
sqlDateFormat = "2006-01-02" | |||
sqlTimeFormat = "2006-01-02 15:04:05.999999999Z07:00" | |||
sqlDateFormat = "2006-01-02" | |||
sqlDateTimeFormat = "2006-01-02 15:04:05.999999999Z07:00" | |||
sqlTimeFormat = "15:04:05.9999999" | |||
) | |||
func (cn *Conn) CreateBulk(table string, columns []string) (_ *Bulk) { | |||
@@ -86,7 +87,7 @@ func (b *Bulk) sendBulkCommand(ctx context.Context) (err error) { | |||
b.bulkColumns = append(b.bulkColumns, *bulkCol) | |||
b.dlogf("Adding column %s %s %#x", colname, bulkCol.ColName, bulkCol.ti.TypeId) | |||
} else { | |||
return fmt.Errorf("Column %s does not exist in destination table %s", colname, b.tablename) | |||
return fmt.Errorf("column %s does not exist in destination table %s", colname, b.tablename) | |||
} | |||
} | |||
@@ -166,7 +167,7 @@ func (b *Bulk) AddRow(row []interface{}) (err error) { | |||
} | |||
if len(row) != len(b.bulkColumns) { | |||
return fmt.Errorf("Row does not have the same number of columns than the destination table %d %d", | |||
return fmt.Errorf("row does not have the same number of columns than the destination table %d %d", | |||
len(row), len(b.bulkColumns)) | |||
} | |||
@@ -215,7 +216,7 @@ func (b *Bulk) makeRowData(row []interface{}) ([]byte, error) { | |||
} | |||
func (b *Bulk) Done() (rowcount int64, err error) { | |||
if b.headerSent == false { | |||
if !b.headerSent { | |||
//no rows had been sent | |||
return 0, nil | |||
} | |||
@@ -233,24 +234,13 @@ func (b *Bulk) Done() (rowcount int64, err error) { | |||
buf.FinishPacket() | |||
tokchan := make(chan tokenStruct, 5) | |||
go processResponse(b.ctx, b.cn.sess, tokchan, nil) | |||
var rowCount int64 | |||
for token := range tokchan { | |||
switch token := token.(type) { | |||
case doneStruct: | |||
if token.Status&doneCount != 0 { | |||
rowCount = int64(token.RowCount) | |||
} | |||
if token.isError() { | |||
return 0, token.getError() | |||
} | |||
case error: | |||
return 0, b.cn.checkBadConn(token) | |||
} | |||
reader := startReading(b.cn.sess, b.ctx, nil) | |||
err = reader.iterateResponse() | |||
if err != nil { | |||
return 0, b.cn.checkBadConn(err) | |||
} | |||
return rowCount, nil | |||
return reader.rowCount, nil | |||
} | |||
func (b *Bulk) createColMetadata() []byte { | |||
@@ -421,7 +411,7 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) | |||
res.ti.Size = len(res.buffer) | |||
case string: | |||
var t time.Time | |||
if t, err = time.Parse(sqlTimeFormat, val); err != nil { | |||
if t, err = time.Parse(sqlDateTimeFormat, val); err != nil { | |||
return res, fmt.Errorf("bulk: unable to convert string to date: %v", err) | |||
} | |||
res.buffer = encodeDateTime2(t, int(col.ti.Scale)) | |||
@@ -437,7 +427,7 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) | |||
res.ti.Size = len(res.buffer) | |||
case string: | |||
var t time.Time | |||
if t, err = time.Parse(sqlTimeFormat, val); err != nil { | |||
if t, err = time.Parse(sqlDateTimeFormat, val); err != nil { | |||
return res, fmt.Errorf("bulk: unable to convert string to date: %v", err) | |||
} | |||
res.buffer = encodeDateTimeOffset(t, int(col.ti.Scale)) | |||
@@ -468,7 +458,7 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) | |||
case time.Time: | |||
t = val | |||
case string: | |||
if t, err = time.Parse(sqlTimeFormat, val); err != nil { | |||
if t, err = time.Parse(sqlDateTimeFormat, val); err != nil { | |||
return res, fmt.Errorf("bulk: unable to convert string to date: %v", err) | |||
} | |||
default: | |||
@@ -485,7 +475,22 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) | |||
} else { | |||
err = fmt.Errorf("mssql: invalid size of column %d", col.ti.Size) | |||
} | |||
case typeTimeN: | |||
var t time.Time | |||
switch val := val.(type) { | |||
case time.Time: | |||
res.buffer = encodeTime(val.Hour(), val.Minute(), val.Second(), val.Nanosecond(), int(col.ti.Scale)) | |||
res.ti.Size = len(res.buffer) | |||
case string: | |||
if t, err = time.Parse(sqlTimeFormat, val); err != nil { | |||
return res, fmt.Errorf("bulk: unable to convert string to time: %v", err) | |||
} | |||
res.buffer = encodeTime(t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), int(col.ti.Scale)) | |||
res.ti.Size = len(res.buffer) | |||
default: | |||
err = fmt.Errorf("mssql: invalid type for time column: %T %s", val, val) | |||
return | |||
} | |||
// case typeMoney, typeMoney4, typeMoneyN: | |||
case typeDecimal, typeDecimalN, typeNumeric, typeNumericN: | |||
prec := col.ti.Prec |
@@ -37,11 +37,17 @@ type connectParams struct { | |||
failOverPartner string | |||
failOverPort uint64 | |||
packetSize uint16 | |||
fedAuthAccessToken string | |||
fedAuthLibrary int | |||
fedAuthADALWorkflow byte | |||
} | |||
// default packet size for TDS buffer | |||
const defaultPacketSize = 4096 | |||
func parseConnectParams(dsn string) (connectParams, error) { | |||
var p connectParams | |||
p := connectParams{ | |||
fedAuthLibrary: fedAuthLibraryReserved, | |||
} | |||
var params map[string]string | |||
if strings.HasPrefix(dsn, "odbc:") { | |||
@@ -65,7 +71,7 @@ func parseConnectParams(dsn string) (connectParams, error) { | |||
var err error | |||
p.logFlags, err = strconv.ParseUint(strlog, 10, 64) | |||
if err != nil { | |||
return p, fmt.Errorf("Invalid log parameter '%s': %s", strlog, err.Error()) | |||
return p, fmt.Errorf("invalid log parameter '%s': %s", strlog, err.Error()) | |||
} | |||
} | |||
server := params["server"] | |||
@@ -87,20 +93,19 @@ func parseConnectParams(dsn string) (connectParams, error) { | |||
var err error | |||
p.port, err = strconv.ParseUint(strport, 10, 16) | |||
if err != nil { | |||
f := "Invalid tcp port '%v': %v" | |||
f := "invalid tcp port '%v': %v" | |||
return p, fmt.Errorf(f, strport, err.Error()) | |||
} | |||
} | |||
// https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-network-packet-size-server-configuration-option | |||
// Default packet size remains at 4096 bytes | |||
p.packetSize = 4096 | |||
p.packetSize = defaultPacketSize | |||
strpsize, ok := params["packet size"] | |||
if ok { | |||
var err error | |||
psize, err := strconv.ParseUint(strpsize, 0, 16) | |||
if err != nil { | |||
f := "Invalid packet size '%v': %v" | |||
f := "invalid packet size '%v': %v" | |||
return p, fmt.Errorf(f, strpsize, err.Error()) | |||
} | |||
@@ -123,7 +128,7 @@ func parseConnectParams(dsn string) (connectParams, error) { | |||
if strconntimeout, ok := params["connection timeout"]; ok { | |||
timeout, err := strconv.ParseUint(strconntimeout, 10, 64) | |||
if err != nil { | |||
f := "Invalid connection timeout '%v': %v" | |||
f := "invalid connection timeout '%v': %v" | |||
return p, fmt.Errorf(f, strconntimeout, err.Error()) | |||
} | |||
p.conn_timeout = time.Duration(timeout) * time.Second | |||
@@ -132,7 +137,7 @@ func parseConnectParams(dsn string) (connectParams, error) { | |||
if strdialtimeout, ok := params["dial timeout"]; ok { | |||
timeout, err := strconv.ParseUint(strdialtimeout, 10, 64) | |||
if err != nil { | |||
f := "Invalid dial timeout '%v': %v" | |||
f := "invalid dial timeout '%v': %v" | |||
return p, fmt.Errorf(f, strdialtimeout, err.Error()) | |||
} | |||
p.dial_timeout = time.Duration(timeout) * time.Second | |||
@@ -144,7 +149,7 @@ func parseConnectParams(dsn string) (connectParams, error) { | |||
if keepAlive, ok := params["keepalive"]; ok { | |||
timeout, err := strconv.ParseUint(keepAlive, 10, 64) | |||
if err != nil { | |||
f := "Invalid keepAlive value '%s': %s" | |||
f := "invalid keepAlive value '%s': %s" | |||
return p, fmt.Errorf(f, keepAlive, err.Error()) | |||
} | |||
p.keepAlive = time.Duration(timeout) * time.Second | |||
@@ -157,7 +162,7 @@ func parseConnectParams(dsn string) (connectParams, error) { | |||
var err error | |||
p.encrypt, err = strconv.ParseBool(encrypt) | |||
if err != nil { | |||
f := "Invalid encrypt '%s': %s" | |||
f := "invalid encrypt '%s': %s" | |||
return p, fmt.Errorf(f, encrypt, err.Error()) | |||
} | |||
} | |||
@@ -169,7 +174,7 @@ func parseConnectParams(dsn string) (connectParams, error) { | |||
var err error | |||
p.trustServerCertificate, err = strconv.ParseBool(trust) | |||
if err != nil { | |||
f := "Invalid trust server certificate '%s': %s" | |||
f := "invalid trust server certificate '%s': %s" | |||
return p, fmt.Errorf(f, trust, err.Error()) | |||
} | |||
} | |||
@@ -209,7 +214,7 @@ func parseConnectParams(dsn string) (connectParams, error) { | |||
if ok { | |||
if appintent == "ReadOnly" { | |||
if p.database == "" { | |||
return p, fmt.Errorf("Database must be specified when ApplicationIntent is ReadOnly") | |||
return p, fmt.Errorf("database must be specified when ApplicationIntent is ReadOnly") | |||
} | |||
p.typeFlags |= fReadOnlyIntent | |||
} | |||
@@ -225,7 +230,7 @@ func parseConnectParams(dsn string) (connectParams, error) { | |||
var err error | |||
p.failOverPort, err = strconv.ParseUint(failOverPort, 0, 16) | |||
if err != nil { | |||
f := "Invalid tcp port '%v': %v" | |||
f := "invalid tcp port '%v': %v" | |||
return p, fmt.Errorf(f, failOverPort, err.Error()) | |||
} | |||
} | |||
@@ -233,6 +238,30 @@ func parseConnectParams(dsn string) (connectParams, error) { | |||
return p, nil | |||
} | |||
// convert connectionParams to url style connection string | |||
// used mostly for testing | |||
func (p connectParams) toUrl() *url.URL { | |||
q := url.Values{} | |||
if p.database != "" { | |||
q.Add("database", p.database) | |||
} | |||
if p.logFlags != 0 { | |||
q.Add("log", strconv.FormatUint(p.logFlags, 10)) | |||
} | |||
res := url.URL{ | |||
Scheme: "sqlserver", | |||
Host: p.host, | |||
User: url.UserPassword(p.user, p.password), | |||
} | |||
if p.instance != "" { | |||
res.Path = p.instance | |||
} | |||
if len(q) > 0 { | |||
res.RawQuery = q.Encode() | |||
} | |||
return &res | |||
} | |||
func splitConnectionString(dsn string) (res map[string]string) { | |||
res = map[string]string{} | |||
parts := strings.Split(dsn, ";") | |||
@@ -340,7 +369,7 @@ func splitConnectionStringOdbc(dsn string) (map[string]string, error) { | |||
case parserStateBeforeKey: | |||
switch { | |||
case c == '=': | |||
return res, fmt.Errorf("Unexpected character = at index %d. Expected start of key or semi-colon or whitespace.", i) | |||
return res, fmt.Errorf("unexpected character = at index %d. Expected start of key or semi-colon or whitespace", i) | |||
case !unicode.IsSpace(c) && c != ';': | |||
state = parserStateKey | |||
key += string(c) | |||
@@ -419,7 +448,7 @@ func splitConnectionStringOdbc(dsn string) (map[string]string, error) { | |||
case unicode.IsSpace(c): | |||
// Ignore whitespace | |||
default: | |||
return res, fmt.Errorf("Unexpected character %c at index %d. Expected semi-colon or whitespace.", c, i) | |||
return res, fmt.Errorf("unexpected character %c at index %d. Expected semi-colon or whitespace", c, i) | |||
} | |||
case parserStateEndValue: | |||
@@ -429,7 +458,7 @@ func splitConnectionStringOdbc(dsn string) (map[string]string, error) { | |||
case unicode.IsSpace(c): | |||
// Ignore whitespace | |||
default: | |||
return res, fmt.Errorf("Unexpected character %c at index %d. Expected semi-colon or whitespace.", c, i) | |||
return res, fmt.Errorf("unexpected character %c at index %d. Expected semi-colon or whitespace", c, i) | |||
} | |||
} | |||
} | |||
@@ -444,7 +473,7 @@ func splitConnectionStringOdbc(dsn string) (map[string]string, error) { | |||
case parserStateBareValue: | |||
res[key] = strings.TrimRightFunc(value, unicode.IsSpace) | |||
case parserStateBracedValue: | |||
return res, fmt.Errorf("Unexpected end of braced value at index %d.", len(dsn)) | |||
return res, fmt.Errorf("unexpected end of braced value at index %d", len(dsn)) | |||
case parserStateBracedValueClosingBrace: // End of braced value | |||
res[key] = value | |||
case parserStateEndValue: // Okay |
@@ -0,0 +1,82 @@ | |||
package mssql | |||
import ( | |||
"context" | |||
"errors" | |||
) | |||
// Federated authentication library affects the login data structure and message sequence. | |||
const ( | |||
// fedAuthLibraryLiveIDCompactToken specifies the Microsoft Live ID Compact Token authentication scheme | |||
fedAuthLibraryLiveIDCompactToken = 0x00 | |||
// fedAuthLibrarySecurityToken specifies a token-based authentication where the token is available | |||
// without additional information provided during the login sequence. | |||
fedAuthLibrarySecurityToken = 0x01 | |||
// fedAuthLibraryADAL specifies a token-based authentication where a token is obtained during the | |||
// login sequence using the server SPN and STS URL provided by the server during login. | |||
fedAuthLibraryADAL = 0x02 | |||
// fedAuthLibraryReserved is used to indicate that no federated authentication scheme applies. | |||
fedAuthLibraryReserved = 0x7F | |||
) | |||
// Federated authentication ADAL workflow affects the mechanism used to authenticate. | |||
const ( | |||
// fedAuthADALWorkflowPassword uses a username/password to obtain a token from Active Directory | |||
fedAuthADALWorkflowPassword = 0x01 | |||
// fedAuthADALWorkflowPassword uses the Windows identity to obtain a token from Active Directory | |||
fedAuthADALWorkflowIntegrated = 0x02 | |||
// fedAuthADALWorkflowMSI uses the managed identity service to obtain a token | |||
fedAuthADALWorkflowMSI = 0x03 | |||
) | |||
// newSecurityTokenConnector creates a new connector from a DSN and a token provider. | |||
// When invoked, token provider implementations should contact the security token | |||
// service specified and obtain the appropriate token, or return an error | |||
// to indicate why a token is not available. | |||
// The returned connector may be used with sql.OpenDB. | |||
func newSecurityTokenConnector(dsn string, tokenProvider func(ctx context.Context) (string, error)) (*Connector, error) { | |||
if tokenProvider == nil { | |||
return nil, errors.New("mssql: tokenProvider cannot be nil") | |||
} | |||
conn, err := NewConnector(dsn) | |||
if err != nil { | |||
return nil, err | |||
} | |||
conn.params.fedAuthLibrary = fedAuthLibrarySecurityToken | |||
conn.securityTokenProvider = tokenProvider | |||
return conn, nil | |||
} | |||
// newADALTokenConnector creates a new connector from a DSN and a Active Directory token provider. | |||
// Token provider implementations are called during federated | |||
// authentication login sequences where the server provides a service | |||
// principal name and security token service endpoint that should be used | |||
// to obtain the token. Implementations should contact the security token | |||
// service specified and obtain the appropriate token, or return an error | |||
// to indicate why a token is not available. | |||
// | |||
// The returned connector may be used with sql.OpenDB. | |||
func newActiveDirectoryTokenConnector(dsn string, adalWorkflow byte, tokenProvider func(ctx context.Context, serverSPN, stsURL string) (string, error)) (*Connector, error) { | |||
if tokenProvider == nil { | |||
return nil, errors.New("mssql: tokenProvider cannot be nil") | |||
} | |||
conn, err := NewConnector(dsn) | |||
if err != nil { | |||
return nil, err | |||
} | |||
conn.params.fedAuthLibrary = fedAuthLibraryADAL | |||
conn.params.fedAuthADALWorkflow = adalWorkflow | |||
conn.adalTokenProvider = tokenProvider | |||
return conn, nil | |||
} |
@@ -58,6 +58,7 @@ func (d *Driver) OpenConnector(dsn string) (*Connector, error) { | |||
if err != nil { | |||
return nil, err | |||
} | |||
return &Connector{ | |||
params: params, | |||
driver: d, | |||
@@ -100,6 +101,12 @@ type Connector struct { | |||
params connectParams | |||
driver *Driver | |||
// callback that can provide a security token during login | |||
securityTokenProvider func(ctx context.Context) (string, error) | |||
// callback that can provide a security token during ADAL login | |||
adalTokenProvider func(ctx context.Context, serverSPN, stsURL string) (string, error) | |||
// SessionInitSQL is executed after marking a given session to be reset. | |||
// When not present, the next query will still reset the session to the | |||
// database defaults. | |||
@@ -148,15 +155,7 @@ type Conn struct { | |||
processQueryText bool | |||
connectionGood bool | |||
outs map[string]interface{} | |||
returnStatus *ReturnStatus | |||
} | |||
func (c *Conn) setReturnStatus(s ReturnStatus) { | |||
if c.returnStatus == nil { | |||
return | |||
} | |||
*c.returnStatus = s | |||
outs map[string]interface{} | |||
} | |||
func (c *Conn) checkBadConn(err error) error { | |||
@@ -201,20 +200,15 @@ func (c *Conn) clearOuts() { | |||
} | |||
func (c *Conn) simpleProcessResp(ctx context.Context) error { | |||
tokchan := make(chan tokenStruct, 5) | |||
go processResponse(ctx, c.sess, tokchan, c.outs) | |||
reader := startReading(c.sess, ctx, c.outs) | |||
c.clearOuts() | |||
for tok := range tokchan { | |||
switch token := tok.(type) { | |||
case doneStruct: | |||
if token.isError() { | |||
return c.checkBadConn(token.getError()) | |||
} | |||
case error: | |||
return c.checkBadConn(token) | |||
} | |||
var resultError error | |||
err := reader.iterateResponse() | |||
if err != nil { | |||
return c.checkBadConn(err) | |||
} | |||
return nil | |||
return resultError | |||
} | |||
func (c *Conn) Commit() error { | |||
@@ -239,7 +233,7 @@ func (c *Conn) sendCommitRequest() error { | |||
c.sess.log.Printf("Failed to send CommitXact with %v", err) | |||
} | |||
c.connectionGood = false | |||
return fmt.Errorf("Faild to send CommitXact: %v", err) | |||
return fmt.Errorf("faild to send CommitXact: %v", err) | |||
} | |||
return nil | |||
} | |||
@@ -266,7 +260,7 @@ func (c *Conn) sendRollbackRequest() error { | |||
c.sess.log.Printf("Failed to send RollbackXact with %v", err) | |||
} | |||
c.connectionGood = false | |||
return fmt.Errorf("Failed to send RollbackXact: %v", err) | |||
return fmt.Errorf("failed to send RollbackXact: %v", err) | |||
} | |||
return nil | |||
} | |||
@@ -303,7 +297,7 @@ func (c *Conn) sendBeginRequest(ctx context.Context, tdsIsolation isoLevel) erro | |||
c.sess.log.Printf("Failed to send BeginXact with %v", err) | |||
} | |||
c.connectionGood = false | |||
return fmt.Errorf("Failed to send BeginXact: %v", err) | |||
return fmt.Errorf("failed to send BeginXact: %v", err) | |||
} | |||
return nil | |||
} | |||
@@ -478,7 +472,7 @@ func (s *Stmt) sendQuery(args []namedValue) (err error) { | |||
conn.sess.log.Printf("Failed to send Rpc with %v", err) | |||
} | |||
conn.connectionGood = false | |||
return fmt.Errorf("Failed to send RPC: %v", err) | |||
return fmt.Errorf("failed to send RPC: %v", err) | |||
} | |||
} | |||
return | |||
@@ -595,38 +589,46 @@ func (s *Stmt) queryContext(ctx context.Context, args []namedValue) (rows driver | |||
} | |||
func (s *Stmt) processQueryResponse(ctx context.Context) (res driver.Rows, err error) { | |||
tokchan := make(chan tokenStruct, 5) | |||
ctx, cancel := context.WithCancel(ctx) | |||
go processResponse(ctx, s.c.sess, tokchan, s.c.outs) | |||
reader := startReading(s.c.sess, ctx, s.c.outs) | |||
s.c.clearOuts() | |||
// process metadata | |||
var cols []columnStruct | |||
loop: | |||
for tok := range tokchan { | |||
switch token := tok.(type) { | |||
// By ignoring DONE token we effectively | |||
// skip empty result-sets. | |||
// This improves results in queries like that: | |||
// set nocount on; select 1 | |||
// see TestIgnoreEmptyResults test | |||
//case doneStruct: | |||
//break loop | |||
case []columnStruct: | |||
cols = token | |||
break loop | |||
case doneStruct: | |||
if token.isError() { | |||
cancel() | |||
return nil, s.c.checkBadConn(token.getError()) | |||
for { | |||
tok, err := reader.nextToken() | |||
if err == nil { | |||
if tok == nil { | |||
break | |||
} else { | |||
switch token := tok.(type) { | |||
// By ignoring DONE token we effectively | |||
// skip empty result-sets. | |||
// This improves results in queries like that: | |||
// set nocount on; select 1 | |||
// see TestIgnoreEmptyResults test | |||
//case doneStruct: | |||
//break loop | |||
case []columnStruct: | |||
cols = token | |||
break loop | |||
case doneStruct: | |||
if token.isError() { | |||
// need to cleanup cancellable context | |||
cancel() | |||
return nil, s.c.checkBadConn(token.getError()) | |||
} | |||
case ReturnStatus: | |||
s.c.sess.setReturnStatus(token) | |||
} | |||
} | |||
case ReturnStatus: | |||
s.c.setReturnStatus(token) | |||
case error: | |||
} else { | |||
// need to cleanup cancellable context | |||
cancel() | |||
return nil, s.c.checkBadConn(token) | |||
return nil, s.c.checkBadConn(err) | |||
} | |||
} | |||
res = &Rows{stmt: s, tokchan: tokchan, cols: cols, cancel: cancel} | |||
res = &Rows{stmt: s, reader: reader, cols: cols, cancel: cancel} | |||
return | |||
} | |||
@@ -648,48 +650,46 @@ func (s *Stmt) exec(ctx context.Context, args []namedValue) (res driver.Result, | |||
} | |||
func (s *Stmt) processExec(ctx context.Context) (res driver.Result, err error) { | |||
tokchan := make(chan tokenStruct, 5) | |||
go processResponse(ctx, s.c.sess, tokchan, s.c.outs) | |||
reader := startReading(s.c.sess, ctx, s.c.outs) | |||
s.c.clearOuts() | |||
var rowCount int64 | |||
for token := range tokchan { | |||
switch token := token.(type) { | |||
case doneInProcStruct: | |||
if token.Status&doneCount != 0 { | |||
rowCount += int64(token.RowCount) | |||
} | |||
case doneStruct: | |||
if token.Status&doneCount != 0 { | |||
rowCount += int64(token.RowCount) | |||
} | |||
if token.isError() { | |||
return nil, token.getError() | |||
} | |||
case ReturnStatus: | |||
s.c.setReturnStatus(token) | |||
case error: | |||
return nil, token | |||
} | |||
err = reader.iterateResponse() | |||
if err != nil { | |||
return nil, s.c.checkBadConn(err) | |||
} | |||
return &Result{s.c, rowCount}, nil | |||
return &Result{s.c, reader.rowCount}, nil | |||
} | |||
type Rows struct { | |||
stmt *Stmt | |||
cols []columnStruct | |||
tokchan chan tokenStruct | |||
stmt *Stmt | |||
cols []columnStruct | |||
reader *tokenProcessor | |||
nextCols []columnStruct | |||
cancel func() | |||
} | |||
func (rc *Rows) Close() error { | |||
// need to add a test which returns lots of rows | |||
// and check closing after reading only few rows | |||
rc.cancel() | |||
for _ = range rc.tokchan { | |||
for { | |||
tok, err := rc.reader.nextToken() | |||
if err == nil { | |||
if tok == nil { | |||
return nil | |||
} else { | |||
// continue consuming tokens | |||
continue | |||
} | |||
} else { | |||
if err == rc.reader.ctx.Err() { | |||
return nil | |||
} else { | |||
return err | |||
} | |||
} | |||
} | |||
rc.tokchan = nil | |||
return nil | |||
} | |||
func (rc *Rows) Columns() (res []string) { | |||
@@ -707,27 +707,34 @@ func (rc *Rows) Next(dest []driver.Value) error { | |||
if rc.nextCols != nil { | |||
return io.EOF | |||
} | |||
for tok := range rc.tokchan { | |||
switch tokdata := tok.(type) { | |||
case []columnStruct: | |||
rc.nextCols = tokdata | |||
return io.EOF | |||
case []interface{}: | |||
for i := range dest { | |||
dest[i] = tokdata[i] | |||
} | |||
return nil | |||
case doneStruct: | |||
if tokdata.isError() { | |||
return rc.stmt.c.checkBadConn(tokdata.getError()) | |||
for { | |||
tok, err := rc.reader.nextToken() | |||
if err == nil { | |||
if tok == nil { | |||
return io.EOF | |||
} else { | |||
switch tokdata := tok.(type) { | |||
case []columnStruct: | |||
rc.nextCols = tokdata | |||
return io.EOF | |||
case []interface{}: | |||
for i := range dest { | |||
dest[i] = tokdata[i] | |||
} | |||
return nil | |||
case doneStruct: | |||
if tokdata.isError() { | |||
return rc.stmt.c.checkBadConn(tokdata.getError()) | |||
} | |||
case ReturnStatus: | |||
rc.stmt.c.sess.setReturnStatus(tokdata) | |||
} | |||
} | |||
case ReturnStatus: | |||
rc.stmt.c.setReturnStatus(tokdata) | |||
case error: | |||
return rc.stmt.c.checkBadConn(tokdata) | |||
} else { | |||
return rc.stmt.c.checkBadConn(err) | |||
} | |||
} | |||
return io.EOF | |||
} | |||
func (rc *Rows) HasNextResultSet() bool { | |||
@@ -895,35 +902,41 @@ func (c *Conn) Ping(ctx context.Context) error { | |||
var _ driver.ConnBeginTx = &Conn{} | |||
// BeginTx satisfies ConnBeginTx. | |||
func (c *Conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { | |||
if !c.connectionGood { | |||
return nil, driver.ErrBadConn | |||
} | |||
if opts.ReadOnly { | |||
return nil, errors.New("Read-only transactions are not supported") | |||
} | |||
var tdsIsolation isoLevel | |||
switch sql.IsolationLevel(opts.Isolation) { | |||
func convertIsolationLevel(level sql.IsolationLevel) (isoLevel, error) { | |||
switch level { | |||
case sql.LevelDefault: | |||
tdsIsolation = isolationUseCurrent | |||
return isolationUseCurrent, nil | |||
case sql.LevelReadUncommitted: | |||
tdsIsolation = isolationReadUncommited | |||
return isolationReadUncommited, nil | |||
case sql.LevelReadCommitted: | |||
tdsIsolation = isolationReadCommited | |||
return isolationReadCommited, nil | |||
case sql.LevelWriteCommitted: | |||
return nil, errors.New("LevelWriteCommitted isolation level is not supported") | |||
return isolationUseCurrent, errors.New("LevelWriteCommitted isolation level is not supported") | |||
case sql.LevelRepeatableRead: | |||
tdsIsolation = isolationRepeatableRead | |||
return isolationRepeatableRead, nil | |||
case sql.LevelSnapshot: | |||
tdsIsolation = isolationSnapshot | |||
return isolationSnapshot, nil | |||
case sql.LevelSerializable: | |||
tdsIsolation = isolationSerializable | |||
return isolationSerializable, nil | |||
case sql.LevelLinearizable: | |||
return nil, errors.New("LevelLinearizable isolation level is not supported") | |||
return isolationUseCurrent, errors.New("LevelLinearizable isolation level is not supported") | |||
default: | |||
return nil, errors.New("Isolation level is not supported or unknown") | |||
return isolationUseCurrent, errors.New("isolation level is not supported or unknown") | |||
} | |||
} | |||
// BeginTx satisfies ConnBeginTx. | |||
func (c *Conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { | |||
if !c.connectionGood { | |||
return nil, driver.ErrBadConn | |||
} | |||
if opts.ReadOnly { | |||
return nil, errors.New("read-only transactions are not supported") | |||
} | |||
tdsIsolation, err := convertIsolationLevel(sql.IsolationLevel(opts.Isolation)) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return c.begin(ctx, tdsIsolation) | |||
} |
@@ -48,5 +48,5 @@ func (c *Connector) Driver() driver.Driver { | |||
} | |||
func (r *Result) LastInsertId() (int64, error) { | |||
return -1, errors.New("LastInsertId is not supported. Please use the OUTPUT clause or add `select ID = convert(bigint, SCOPE_IDENTITY())` to the end of your query.") | |||
return -1, errors.New("LastInsertId is not supported. Please use the OUTPUT clause or add `select ID = convert(bigint, SCOPE_IDENTITY())` to the end of your query") | |||
} |
@@ -110,7 +110,7 @@ func (c *Conn) CheckNamedValue(nv *driver.NamedValue) error { | |||
return nil | |||
case *ReturnStatus: | |||
*v = 0 // By default the return value should be zero. | |||
c.returnStatus = v | |||
c.sess.returnStatus = v | |||
return driver.ErrRemoveArgument | |||
case TVP: | |||
return nil |
@@ -7,8 +7,8 @@ import ( | |||
) | |||
type timeoutConn struct { | |||
c net.Conn | |||
timeout time.Duration | |||
c net.Conn | |||
timeout time.Duration | |||
} | |||
func newTimeoutConn(conn net.Conn, timeout time.Duration) *timeoutConn { | |||
@@ -51,21 +51,21 @@ func (c timeoutConn) RemoteAddr() net.Addr { | |||
} | |||
func (c timeoutConn) SetDeadline(t time.Time) error { | |||
panic("Not implemented") | |||
return c.c.SetDeadline(t) | |||
} | |||
func (c timeoutConn) SetReadDeadline(t time.Time) error { | |||
panic("Not implemented") | |||
return c.c.SetReadDeadline(t) | |||
} | |||
func (c timeoutConn) SetWriteDeadline(t time.Time) error { | |||
panic("Not implemented") | |||
return c.c.SetWriteDeadline(t) | |||
} | |||
// this connection is used during TLS Handshake | |||
// TDS protocol requires TLS handshake messages to be sent inside TDS packets | |||
type tlsHandshakeConn struct { | |||
buf *tdsBuffer | |||
buf *tdsBuffer | |||
packetPending bool | |||
continueRead bool | |||
} | |||
@@ -75,7 +75,7 @@ func (c *tlsHandshakeConn) Read(b []byte) (n int, err error) { | |||
c.packetPending = false | |||
err = c.buf.FinishPacket() | |||
if err != nil { | |||
err = fmt.Errorf("Cannot send handshake packet: %s", err.Error()) | |||
err = fmt.Errorf("cannot send handshake packet: %s", err.Error()) | |||
return | |||
} | |||
c.continueRead = false | |||
@@ -84,7 +84,7 @@ func (c *tlsHandshakeConn) Read(b []byte) (n int, err error) { | |||
var packet packetType | |||
packet, err = c.buf.BeginRead() | |||
if err != nil { | |||
err = fmt.Errorf("Cannot read handshake packet: %s", err.Error()) | |||
err = fmt.Errorf("cannot read handshake packet: %s", err.Error()) | |||
return | |||
} | |||
if packet != packPrelogin { | |||
@@ -105,27 +105,27 @@ func (c *tlsHandshakeConn) Write(b []byte) (n int, err error) { | |||
} | |||
func (c *tlsHandshakeConn) Close() error { | |||
panic("Not implemented") | |||
return c.buf.transport.Close() | |||
} | |||
func (c *tlsHandshakeConn) LocalAddr() net.Addr { | |||
panic("Not implemented") | |||
return nil | |||
} | |||
func (c *tlsHandshakeConn) RemoteAddr() net.Addr { | |||
panic("Not implemented") | |||
return nil | |||
} | |||
func (c *tlsHandshakeConn) SetDeadline(t time.Time) error { | |||
panic("Not implemented") | |||
func (c *tlsHandshakeConn) SetDeadline(_ time.Time) error { | |||
return nil | |||
} | |||
func (c *tlsHandshakeConn) SetReadDeadline(t time.Time) error { | |||
panic("Not implemented") | |||
func (c *tlsHandshakeConn) SetReadDeadline(_ time.Time) error { | |||
return nil | |||
} | |||
func (c *tlsHandshakeConn) SetWriteDeadline(t time.Time) error { | |||
panic("Not implemented") | |||
func (c *tlsHandshakeConn) SetWriteDeadline(_ time.Time) error { | |||
return nil | |||
} | |||
// this connection just delegates all methods to it's wrapped connection | |||
@@ -148,21 +148,21 @@ func (c passthroughConn) Close() error { | |||
} | |||
func (c passthroughConn) LocalAddr() net.Addr { | |||
panic("Not implemented") | |||
return c.c.LocalAddr() | |||
} | |||
func (c passthroughConn) RemoteAddr() net.Addr { | |||
panic("Not implemented") | |||
return c.c.RemoteAddr() | |||
} | |||
func (c passthroughConn) SetDeadline(t time.Time) error { | |||
panic("Not implemented") | |||
return c.c.SetDeadline(t) | |||
} | |||
func (c passthroughConn) SetReadDeadline(t time.Time) error { | |||
panic("Not implemented") | |||
return c.c.SetReadDeadline(t) | |||
} | |||
func (c passthroughConn) SetWriteDeadline(t time.Time) error { | |||
panic("Not implemented") | |||
return c.c.SetWriteDeadline(t) | |||
} |
@@ -14,6 +14,7 @@ import ( | |||
"time" | |||
"unicode/utf16" | |||
//lint:ignore SA1019 MD4 is used by legacy NTLM | |||
"golang.org/x/crypto/md4" | |||
) | |||
@@ -126,18 +127,6 @@ func createDesKey(bytes, material []byte) { | |||
material[7] = (byte)(bytes[6] << 1) | |||
} | |||
func oddParity(bytes []byte) { | |||
for i := 0; i < len(bytes); i++ { | |||
b := bytes[i] | |||
needsParity := (((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ (b >> 4) ^ (b >> 3) ^ (b >> 2) ^ (b >> 1)) & 0x01) == 0 | |||
if needsParity { | |||
bytes[i] = bytes[i] | byte(0x01) | |||
} else { | |||
bytes[i] = bytes[i] & byte(0xfe) | |||
} | |||
} | |||
} | |||
func encryptDes(key []byte, cleartext []byte, ciphertext []byte) { | |||
var desKey [8]byte | |||
createDesKey(key, desKey[:]) |
@@ -22,12 +22,6 @@ type param struct { | |||
buffer []byte | |||
} | |||
const ( | |||
fWithRecomp = 1 | |||
fNoMetaData = 2 | |||
fReuseMetaData = 4 | |||
) | |||
var ( | |||
sp_Cursor = procId{1, ""} | |||
sp_CursorOpen = procId{2, ""} |
@@ -82,19 +82,20 @@ const ( | |||
// https://msdn.microsoft.com/en-us/library/dd304214.aspx | |||
const ( | |||
packSQLBatch packetType = 1 | |||
packRPCRequest = 3 | |||
packReply = 4 | |||
packRPCRequest packetType = 3 | |||
packReply packetType = 4 | |||
// 2.2.1.7 Attention: https://msdn.microsoft.com/en-us/library/dd341449.aspx | |||
// 4.19.2 Out-of-Band Attention Signal: https://msdn.microsoft.com/en-us/library/dd305167.aspx | |||
packAttention = 6 | |||
packBulkLoadBCP = 7 | |||
packTransMgrReq = 14 | |||
packNormal = 15 | |||
packLogin7 = 16 | |||
packSSPIMessage = 17 | |||
packPrelogin = 18 | |||
packAttention packetType = 6 | |||
packBulkLoadBCP packetType = 7 | |||
packFedAuthToken packetType = 8 | |||
packTransMgrReq packetType = 14 | |||
packNormal packetType = 15 | |||
packLogin7 packetType = 16 | |||
packSSPIMessage packetType = 17 | |||
packPrelogin packetType = 18 | |||
) | |||
// prelogin fields | |||
@@ -118,6 +119,17 @@ const ( | |||
encryptReq = 3 // Encryption is required. | |||
) | |||
const ( | |||
featExtSESSIONRECOVERY byte = 0x01 | |||
featExtFEDAUTH byte = 0x02 | |||
featExtCOLUMNENCRYPTION byte = 0x04 | |||
featExtGLOBALTRANSACTIONS byte = 0x05 | |||
featExtAZURESQLSUPPORT byte = 0x08 | |||
featExtDATACLASSIFICATION byte = 0x09 | |||
featExtUTF8SUPPORT byte = 0x0A | |||
featExtTERMINATOR byte = 0xFF | |||
) | |||
type tdsSession struct { | |||
buf *tdsBuffer | |||
loginAck loginAckStruct | |||
@@ -129,6 +141,7 @@ type tdsSession struct { | |||
log optionalLogger | |||
routedServer string | |||
routedPort uint16 | |||
returnStatus *ReturnStatus | |||
} | |||
const ( | |||
@@ -155,13 +168,13 @@ func (p keySlice) Less(i, j int) bool { return p[i] < p[j] } | |||
func (p keySlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } | |||
// http://msdn.microsoft.com/en-us/library/dd357559.aspx | |||
func writePrelogin(w *tdsBuffer, fields map[uint8][]byte) error { | |||
func writePrelogin(packetType packetType, w *tdsBuffer, fields map[uint8][]byte) error { | |||
var err error | |||
w.BeginPacket(packPrelogin, false) | |||
w.BeginPacket(packetType, false) | |||
offset := uint16(5*len(fields) + 1) | |||
keys := make(keySlice, 0, len(fields)) | |||
for k, _ := range fields { | |||
for k := range fields { | |||
keys = append(keys, k) | |||
} | |||
sort.Sort(keys) | |||
@@ -210,12 +223,15 @@ func readPrelogin(r *tdsBuffer) (map[uint8][]byte, error) { | |||
if err != nil { | |||
return nil, err | |||
} | |||
if packet_type != 4 { | |||
return nil, errors.New("Invalid respones, expected packet type 4, PRELOGIN RESPONSE") | |||
if packet_type != packReply { | |||
return nil, errors.New("invalid respones, expected packet type 4, PRELOGIN RESPONSE") | |||
} | |||
if len(struct_buf) == 0 { | |||
return nil, errors.New("invalid empty PRELOGIN response, it must contain at least one byte") | |||
} | |||
offset := 0 | |||
results := map[uint8][]byte{} | |||
for true { | |||
for { | |||
rec_type := struct_buf[offset] | |||
if rec_type == preloginTERMINATOR { | |||
break | |||
@@ -240,6 +256,16 @@ const ( | |||
fIntSecurity = 0x80 | |||
) | |||
// OptionFlags3 | |||
// http://msdn.microsoft.com/en-us/library/dd304019.aspx | |||
const ( | |||
fChangePassword = 1 | |||
fSendYukonBinaryXML = 2 | |||
fUserInstance = 4 | |||
fUnknownCollationHandling = 8 | |||
fExtension = 0x10 | |||
) | |||
// TypeFlags | |||
const ( | |||
// 4 bits for fSQLType | |||
@@ -247,12 +273,6 @@ const ( | |||
fReadOnlyIntent = 32 | |||
) | |||
// OptionFlags3 | |||
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/773a62b6-ee89-4c02-9e5e-344882630aac | |||
const ( | |||
fExtension = 0x10 | |||
) | |||
type login struct { | |||
TDSVersion uint32 | |||
PacketSize uint32 | |||
@@ -295,7 +315,7 @@ func (e *featureExts) Add(f featureExt) error { | |||
} | |||
id := f.featureID() | |||
if _, exists := e.features[id]; exists { | |||
f := "Login error: Feature with ID '%v' is already present in FeatureExt block." | |||
f := "login error: Feature with ID '%v' is already present in FeatureExt block" | |||
return fmt.Errorf(f, id) | |||
} | |||
if e.features == nil { | |||
@@ -326,37 +346,63 @@ func (e featureExts) toBytes() []byte { | |||
return d | |||
} | |||
type featureExtFedAuthSTS struct { | |||
FedAuthEcho bool | |||
// featureExtFedAuth tracks federated authentication state before and during login | |||
type featureExtFedAuth struct { | |||
// FedAuthLibrary is populated by the federated authentication provider. | |||
FedAuthLibrary int | |||
// ADALWorkflow is populated by the federated authentication provider. | |||
ADALWorkflow byte | |||
// FedAuthEcho is populated from the prelogin response | |||
FedAuthEcho bool | |||
// FedAuthToken is populated during login with the value from the provider. | |||
FedAuthToken string | |||
Nonce []byte | |||
// Nonce is populated during login with the value from the provider. | |||
Nonce []byte | |||
// Signature is populated during login with the value from the server. | |||
Signature []byte | |||
} | |||
func (e *featureExtFedAuthSTS) featureID() byte { | |||
return 0x02 | |||
func (e *featureExtFedAuth) featureID() byte { | |||
return featExtFEDAUTH | |||
} | |||
func (e *featureExtFedAuthSTS) toBytes() []byte { | |||
func (e *featureExtFedAuth) toBytes() []byte { | |||
if e == nil { | |||
return nil | |||
} | |||
options := byte(0x01) << 1 // 0x01 => STS bFedAuthLibrary 7BIT | |||
options := byte(e.FedAuthLibrary) << 1 | |||
if e.FedAuthEcho { | |||
options |= 1 // fFedAuthEcho | |||
} | |||
d := make([]byte, 5) | |||
d[0] = options | |||
// Feature extension format depends on the federated auth library. | |||
// Options are described at | |||
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/773a62b6-ee89-4c02-9e5e-344882630aac | |||
var d []byte | |||
switch e.FedAuthLibrary { | |||
case fedAuthLibrarySecurityToken: | |||
d = make([]byte, 5) | |||
d[0] = options | |||
// looks like string in | |||
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/f88b63bb-b479-49e1-a87b-deda521da508 | |||
tokenBytes := str2ucs2(e.FedAuthToken) | |||
binary.LittleEndian.PutUint32(d[1:], uint32(len(tokenBytes))) // Should be a signed int32, but since the length is relatively small, this should work | |||
d = append(d, tokenBytes...) | |||
// looks like string in | |||
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/f88b63bb-b479-49e1-a87b-deda521da508 | |||
tokenBytes := str2ucs2(e.FedAuthToken) | |||
binary.LittleEndian.PutUint32(d[1:], uint32(len(tokenBytes))) // Should be a signed int32, but since the length is relatively small, this should work | |||
d = append(d, tokenBytes...) | |||
if len(e.Nonce) == 32 { | |||
d = append(d, e.Nonce...) | |||
if len(e.Nonce) == 32 { | |||
d = append(d, e.Nonce...) | |||
} | |||
case fedAuthLibraryADAL: | |||
d = []byte{options, e.ADALWorkflow} | |||
} | |||
return d | |||
@@ -418,7 +464,7 @@ func str2ucs2(s string) []byte { | |||
func ucs22str(s []byte) (string, error) { | |||
if len(s)%2 != 0 { | |||
return "", fmt.Errorf("Illegal UCS2 string length: %d", len(s)) | |||
return "", fmt.Errorf("illegal UCS2 string length: %d", len(s)) | |||
} | |||
buf := make([]uint16, len(s)/2) | |||
for i := 0; i < len(s); i += 2 { | |||
@@ -436,7 +482,7 @@ func manglePassword(password string) []byte { | |||
} | |||
// http://msdn.microsoft.com/en-us/library/dd304019.aspx | |||
func sendLogin(w *tdsBuffer, login login) error { | |||
func sendLogin(w *tdsBuffer, login *login) error { | |||
w.BeginPacket(packLogin7, false) | |||
hostname := str2ucs2(login.HostName) | |||
username := str2ucs2(login.UserName) | |||
@@ -572,6 +618,36 @@ func sendLogin(w *tdsBuffer, login login) error { | |||
return w.FinishPacket() | |||
} | |||
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/827d9632-2957-4d54-b9ea-384530ae79d0 | |||
func sendFedAuthInfo(w *tdsBuffer, fedAuth *featureExtFedAuth) (err error) { | |||
fedauthtoken := str2ucs2(fedAuth.FedAuthToken) | |||
tokenlen := len(fedauthtoken) | |||
datalen := 4 + tokenlen + len(fedAuth.Nonce) | |||
w.BeginPacket(packFedAuthToken, false) | |||
err = binary.Write(w, binary.LittleEndian, uint32(datalen)) | |||
if err != nil { | |||
return | |||
} | |||
err = binary.Write(w, binary.LittleEndian, uint32(tokenlen)) | |||
if err != nil { | |||
return | |||
} | |||
_, err = w.Write(fedauthtoken) | |||
if err != nil { | |||
return | |||
} | |||
_, err = w.Write(fedAuth.Nonce) | |||
if err != nil { | |||
return | |||
} | |||
return w.FinishPacket() | |||
} | |||
func readUcs2(r io.Reader, numchars int) (res string, err error) { | |||
buf := make([]byte, numchars*2) | |||
_, err = io.ReadFull(r, buf) | |||
@@ -770,12 +846,13 @@ type auth interface { | |||
// use the first one that allows a connection. | |||
func dialConnection(ctx context.Context, c *Connector, p connectParams) (conn net.Conn, err error) { | |||
var ips []net.IP | |||
ips, err = net.LookupIP(p.host) | |||
if err != nil { | |||
ip := net.ParseIP(p.host) | |||
if ip == nil { | |||
return nil, err | |||
ip := net.ParseIP(p.host) | |||
if ip == nil { | |||
ips, err = net.LookupIP(p.host) | |||
if err != nil { | |||
return | |||
} | |||
} else { | |||
ips = []net.IP{ip} | |||
} | |||
if len(ips) == 1 { | |||
@@ -802,7 +879,7 @@ func dialConnection(ctx context.Context, c *Connector, p connectParams) (conn ne | |||
} | |||
// Wait for either the *first* successful connection, or all the errors | |||
wait_loop: | |||
for i, _ := range ips { | |||
for i := range ips { | |||
select { | |||
case conn = <-connChan: | |||
// Got a connection to use, close any others | |||
@@ -824,12 +901,123 @@ func dialConnection(ctx context.Context, c *Connector, p connectParams) (conn ne | |||
} | |||
// Can't do the usual err != nil check, as it is possible to have gotten an error before a successful connection | |||
if conn == nil { | |||
f := "Unable to open tcp connection with host '%v:%v': %v" | |||
f := "unable to open tcp connection with host '%v:%v': %v" | |||
return nil, fmt.Errorf(f, p.host, resolveServerPort(p.port), err.Error()) | |||
} | |||
return conn, err | |||
} | |||
func preparePreloginFields(p connectParams, fe *featureExtFedAuth) map[uint8][]byte { | |||
instance_buf := []byte(p.instance) | |||
instance_buf = append(instance_buf, 0) // zero terminate instance name | |||
var encrypt byte | |||
if p.disableEncryption { | |||
encrypt = encryptNotSup | |||
} else if p.encrypt { | |||
encrypt = encryptOn | |||
} else { | |||
encrypt = encryptOff | |||
} | |||
fields := map[uint8][]byte{ | |||
preloginVERSION: {0, 0, 0, 0, 0, 0}, | |||
preloginENCRYPTION: {encrypt}, | |||
preloginINSTOPT: instance_buf, | |||
preloginTHREADID: {0, 0, 0, 0}, | |||
preloginMARS: {0}, // MARS disabled | |||
} | |||
if fe.FedAuthLibrary != fedAuthLibraryReserved { | |||
fields[preloginFEDAUTHREQUIRED] = []byte{1} | |||
} | |||
return fields | |||
} | |||
func interpretPreloginResponse(p connectParams, fe *featureExtFedAuth, fields map[uint8][]byte) (encrypt byte, err error) { | |||
// If the server returns the preloginFEDAUTHREQUIRED field, then federated authentication | |||
// is supported. The actual value may be 0 or 1, where 0 means either SSPI or federated | |||
// authentication is allowed, while 1 means only federated authentication is allowed. | |||
if fedAuthSupport, ok := fields[preloginFEDAUTHREQUIRED]; ok { | |||
if len(fedAuthSupport) != 1 { | |||
return 0, fmt.Errorf("Federated authentication flag length should be 1: is %d", len(fedAuthSupport)) | |||
} | |||
// We need to be able to echo the value back to the server | |||
fe.FedAuthEcho = fedAuthSupport[0] != 0 | |||
} else if fe.FedAuthLibrary != fedAuthLibraryReserved { | |||
return 0, fmt.Errorf("Federated authentication is not supported by the server") | |||
} | |||
encryptBytes, ok := fields[preloginENCRYPTION] | |||
if !ok { | |||
return 0, fmt.Errorf("encrypt negotiation failed") | |||
} | |||
encrypt = encryptBytes[0] | |||
if p.encrypt && (encrypt == encryptNotSup || encrypt == encryptOff) { | |||
return 0, fmt.Errorf("server does not support encryption") | |||
} | |||
return | |||
} | |||
func prepareLogin(ctx context.Context, c *Connector, p connectParams, log optionalLogger, auth auth, fe *featureExtFedAuth, packetSize uint32) (l *login, err error) { | |||
l = &login{ | |||
TDSVersion: verTDS74, | |||
PacketSize: packetSize, | |||
Database: p.database, | |||
OptionFlags2: fODBC, // to get unlimited TEXTSIZE | |||
HostName: p.workstation, | |||
ServerName: p.host, | |||
AppName: p.appname, | |||
TypeFlags: p.typeFlags, | |||
} | |||
switch { | |||
case fe.FedAuthLibrary == fedAuthLibrarySecurityToken: | |||
if p.logFlags&logDebug != 0 { | |||
log.Println("Starting federated authentication using security token") | |||
} | |||
fe.FedAuthToken, err = c.securityTokenProvider(ctx) | |||
if err != nil { | |||
if p.logFlags&logDebug != 0 { | |||
log.Printf("Failed to retrieve service principal token for federated authentication security token library: %v", err) | |||
} | |||
return nil, err | |||
} | |||
l.FeatureExt.Add(fe) | |||
case fe.FedAuthLibrary == fedAuthLibraryADAL: | |||
if p.logFlags&logDebug != 0 { | |||
log.Println("Starting federated authentication using ADAL") | |||
} | |||
l.FeatureExt.Add(fe) | |||
case auth != nil: | |||
if p.logFlags&logDebug != 0 { | |||
log.Println("Starting SSPI login") | |||
} | |||
l.SSPI, err = auth.InitialBytes() | |||
if err != nil { | |||
return nil, err | |||
} | |||
l.OptionFlags2 |= fIntSecurity | |||
return l, nil | |||
default: | |||
// Default to SQL server authentication with user and password | |||
l.UserName = p.user | |||
l.Password = p.password | |||
} | |||
return l, nil | |||
} | |||
func connect(ctx context.Context, c *Connector, log optionalLogger, p connectParams) (res *tdsSession, err error) { | |||
dialCtx := ctx | |||
if p.dial_timeout > 0 { | |||
@@ -842,24 +1030,24 @@ func connect(ctx context.Context, c *Connector, log optionalLogger, p connectPar | |||
// both instance name and port specified | |||
// when port is specified instance name is not used | |||
// you should not provide instance name when you provide port | |||
log.Println("WARN: You specified both instance name and port in the connection string, port will be used and instance name will be ignored"); | |||
log.Println("WARN: You specified both instance name and port in the connection string, port will be used and instance name will be ignored") | |||
} | |||
if p.instance != "" && p.port == 0 { | |||
p.instance = strings.ToUpper(p.instance) | |||
d := c.getDialer(&p) | |||
instances, err := getInstances(dialCtx, d, p.host) | |||
if err != nil { | |||
f := "Unable to get instances from Sql Server Browser on host %v: %v" | |||
f := "unable to get instances from Sql Server Browser on host %v: %v" | |||
return nil, fmt.Errorf(f, p.host, err.Error()) | |||
} | |||
strport, ok := instances[p.instance]["tcp"] | |||
if !ok { | |||
f := "No instance matching '%v' returned from host '%v'" | |||
f := "no instance matching '%v' returned from host '%v'" | |||
return nil, fmt.Errorf(f, p.instance, p.host) | |||
} | |||
port, err := strconv.ParseUint(strport, 0, 16) | |||
if err != nil { | |||
f := "Invalid tcp port returned from Sql Server Browser '%v': %v" | |||
f := "invalid tcp port returned from Sql Server Browser '%v': %v" | |||
return nil, fmt.Errorf(f, strport, err.Error()) | |||
} | |||
p.port = port | |||
@@ -880,25 +1068,14 @@ initiate_connection: | |||
logFlags: p.logFlags, | |||
} | |||
instance_buf := []byte(p.instance) | |||
instance_buf = append(instance_buf, 0) // zero terminate instance name | |||
var encrypt byte | |||
if p.disableEncryption { | |||
encrypt = encryptNotSup | |||
} else if p.encrypt { | |||
encrypt = encryptOn | |||
} else { | |||
encrypt = encryptOff | |||
} | |||
fields := map[uint8][]byte{ | |||
preloginVERSION: {0, 0, 0, 0, 0, 0}, | |||
preloginENCRYPTION: {encrypt}, | |||
preloginINSTOPT: instance_buf, | |||
preloginTHREADID: {0, 0, 0, 0}, | |||
preloginMARS: {0}, // MARS disabled | |||
fedAuth := &featureExtFedAuth{ | |||
FedAuthLibrary: p.fedAuthLibrary, | |||
ADALWorkflow: p.fedAuthADALWorkflow, | |||
} | |||
err = writePrelogin(outbuf, fields) | |||
fields := preparePreloginFields(p, fedAuth) | |||
err = writePrelogin(packPrelogin, outbuf, fields) | |||
if err != nil { | |||
return nil, err | |||
} | |||
@@ -908,13 +1085,9 @@ initiate_connection: | |||
return nil, err | |||
} | |||
encryptBytes, ok := fields[preloginENCRYPTION] | |||
if !ok { | |||
return nil, fmt.Errorf("Encrypt negotiation failed") | |||
} | |||
encrypt = encryptBytes[0] | |||
if p.encrypt && (encrypt == encryptNotSup || encrypt == encryptOff) { | |||
return nil, fmt.Errorf("Server does not support encryption") | |||
encrypt, err := interpretPreloginResponse(p, fedAuth, fields) | |||
if err != nil { | |||
return nil, err | |||
} | |||
if encrypt != encryptNotSup { | |||
@@ -922,7 +1095,7 @@ initiate_connection: | |||
if p.certificate != "" { | |||
pem, err := ioutil.ReadFile(p.certificate) | |||
if err != nil { | |||
return nil, fmt.Errorf("Cannot read certificate %q: %v", p.certificate, err) | |||
return nil, fmt.Errorf("cannot read certificate %q: %v", p.certificate, err) | |||
} | |||
certs := x509.NewCertPool() | |||
certs.AppendCertsFromPEM(pem) | |||
@@ -954,54 +1127,46 @@ initiate_connection: | |||
} | |||
} | |||
login := login{ | |||
TDSVersion: verTDS74, | |||
PacketSize: uint32(outbuf.PackageSize()), | |||
Database: p.database, | |||
OptionFlags2: fODBC, // to get unlimited TEXTSIZE | |||
HostName: p.workstation, | |||
ServerName: p.host, | |||
AppName: p.appname, | |||
TypeFlags: p.typeFlags, | |||
} | |||
auth, authOk := getAuth(p.user, p.password, p.serverSPN, p.workstation) | |||
switch { | |||
case p.fedAuthAccessToken != "": // accesstoken ignores user/password | |||
featurext := &featureExtFedAuthSTS{ | |||
FedAuthEcho: len(fields[preloginFEDAUTHREQUIRED]) > 0 && fields[preloginFEDAUTHREQUIRED][0] == 1, | |||
FedAuthToken: p.fedAuthAccessToken, | |||
Nonce: fields[preloginNONCEOPT], | |||
} | |||
login.FeatureExt.Add(featurext) | |||
case authOk: | |||
login.SSPI, err = auth.InitialBytes() | |||
if err != nil { | |||
return nil, err | |||
} | |||
login.OptionFlags2 |= fIntSecurity | |||
if authOk { | |||
defer auth.Free() | |||
default: | |||
login.UserName = p.user | |||
login.Password = p.password | |||
} else { | |||
auth = nil | |||
} | |||
login, err := prepareLogin(ctx, c, p, log, auth, fedAuth, uint32(outbuf.PackageSize())) | |||
if err != nil { | |||
return nil, err | |||
} | |||
err = sendLogin(outbuf, login) | |||
if err != nil { | |||
return nil, err | |||
} | |||
// processing login response | |||
success := false | |||
for { | |||
tokchan := make(chan tokenStruct, 5) | |||
go processResponse(context.Background(), &sess, tokchan, nil) | |||
for tok := range tokchan { | |||
// Loop until a packet containing a login acknowledgement is received. | |||
// SSPI and federated authentication scenarios may require multiple | |||
// packet exchanges to complete the login sequence. | |||
for loginAck := false; !loginAck; { | |||
reader := startReading(&sess, ctx, nil) | |||
for { | |||
tok, err := reader.nextToken() | |||
if err != nil { | |||
return nil, err | |||
} | |||
if tok == nil { | |||
break | |||
} | |||
switch token := tok.(type) { | |||
case sspiMsg: | |||
sspi_msg, err := auth.NextBytes(token) | |||
if err != nil { | |||
return nil, err | |||
} | |||
if sspi_msg != nil && len(sspi_msg) > 0 { | |||
if len(sspi_msg) > 0 { | |||
outbuf.BeginPacket(packSSPIMessage, false) | |||
_, err = outbuf.Write(sspi_msg) | |||
if err != nil { | |||
@@ -1013,23 +1178,41 @@ initiate_connection: | |||
} | |||
sspi_msg = nil | |||
} | |||
// TODO: for Live ID authentication it may be necessary to | |||
// compare fedAuth.Nonce == token.Nonce and keep track of signature | |||
//case fedAuthAckStruct: | |||
//fedAuth.Signature = token.Signature | |||
case fedAuthInfoStruct: | |||
// For ADAL workflows this contains the STS URL and server SPN. | |||
// If received outside of an ADAL workflow, ignore. | |||
if c == nil || c.adalTokenProvider == nil { | |||
continue | |||
} | |||
// Request the AD token given the server SPN and STS URL | |||
fedAuth.FedAuthToken, err = c.adalTokenProvider(ctx, token.ServerSPN, token.STSURL) | |||
if err != nil { | |||
return nil, err | |||
} | |||
// Now need to send the token as a FEDINFO packet | |||
err = sendFedAuthInfo(outbuf, fedAuth) | |||
if err != nil { | |||
return nil, err | |||
} | |||
case loginAckStruct: | |||
success = true | |||
sess.loginAck = token | |||
case error: | |||
return nil, fmt.Errorf("Login error: %s", token.Error()) | |||
loginAck = true | |||
case doneStruct: | |||
if token.isError() { | |||
return nil, fmt.Errorf("Login error: %s", token.getError()) | |||
return nil, fmt.Errorf("login error: %s", token.getError()) | |||
} | |||
goto loginEnd | |||
case error: | |||
return nil, fmt.Errorf("login error: %s", token.Error()) | |||
} | |||
} | |||
} | |||
loginEnd: | |||
if !success { | |||
return nil, fmt.Errorf("Login failed") | |||
} | |||
if sess.routedServer != "" { | |||
toconn.Close() | |||
p.host = sess.routedServer | |||
@@ -1041,3 +1224,9 @@ loginEnd: | |||
} | |||
return &sess, nil | |||
} | |||
func (sess *tdsSession) setReturnStatus(status ReturnStatus) { | |||
if sess.returnStatus != nil { | |||
*sess.returnStatus = status | |||
} | |||
} |
@@ -6,12 +6,11 @@ import ( | |||
"errors" | |||
"fmt" | |||
"io" | |||
"net" | |||
"io/ioutil" | |||
"strconv" | |||
"strings" | |||
) | |||
//go:generate stringer -type token | |||
//go:generate go run golang.org/x/tools/cmd/stringer -type token | |||
type token byte | |||
@@ -29,6 +28,7 @@ const ( | |||
tokenNbcRow token = 210 // 0xd2 | |||
tokenEnvChange token = 227 // 0xE3 | |||
tokenSSPI token = 237 // 0xED | |||
tokenFedAuthInfo token = 238 // 0xEE | |||
tokenDone token = 253 // 0xFD | |||
tokenDoneProc token = 254 | |||
tokenDoneInProc token = 255 | |||
@@ -70,6 +70,11 @@ const ( | |||
envRouting = 20 | |||
) | |||
const ( | |||
fedAuthInfoSTSURL = 0x01 | |||
fedAuthInfoSPN = 0x02 | |||
) | |||
// COLMETADATA flags | |||
// https://msdn.microsoft.com/en-us/library/dd357363.aspx | |||
const ( | |||
@@ -105,26 +110,6 @@ func (d doneStruct) getError() Error { | |||
type doneInProcStruct doneStruct | |||
var doneFlags2str = map[uint16]string{ | |||
doneFinal: "final", | |||
doneMore: "more", | |||
doneError: "error", | |||
doneInxact: "inxact", | |||
doneCount: "count", | |||
doneAttn: "attn", | |||
doneSrvError: "srverror", | |||
} | |||
func doneFlags2Str(flags uint16) string { | |||
strs := make([]string, 0, len(doneFlags2str)) | |||
for flag, tag := range doneFlags2str { | |||
if flags&flag != 0 { | |||
strs = append(strs, tag) | |||
} | |||
} | |||
return strings.Join(strs, "|") | |||
} | |||
// ENVCHANGE stream | |||
// http://msdn.microsoft.com/en-us/library/dd303449.aspx | |||
func processEnvChg(sess *tdsSession) { | |||
@@ -380,9 +365,8 @@ func processEnvChg(sess *tdsSession) { | |||
default: | |||
// ignore rest of records because we don't know how to skip those | |||
sess.log.Printf("WARN: Unknown ENVCHANGE record detected with type id = %d\n", envtype) | |||
break | |||
return | |||
} | |||
} | |||
} | |||
@@ -425,6 +409,78 @@ func parseSSPIMsg(r *tdsBuffer) sspiMsg { | |||
return sspiMsg(buf) | |||
} | |||
type fedAuthInfoStruct struct { | |||
STSURL string | |||
ServerSPN string | |||
} | |||
type fedAuthInfoOpt struct { | |||
fedAuthInfoID byte | |||
dataLength, dataOffset uint32 | |||
} | |||
func parseFedAuthInfo(r *tdsBuffer) fedAuthInfoStruct { | |||
size := r.uint32() | |||
var STSURL, SPN string | |||
var err error | |||
// Each fedAuthInfoOpt is one byte to indicate the info ID, | |||
// then a four byte offset and a four byte length. | |||
count := r.uint32() | |||
offset := uint32(4) | |||
opts := make([]fedAuthInfoOpt, count) | |||
for i := uint32(0); i < count; i++ { | |||
fedAuthInfoID := r.byte() | |||
dataLength := r.uint32() | |||
dataOffset := r.uint32() | |||
offset += 1 + 4 + 4 | |||
opts[i] = fedAuthInfoOpt{ | |||
fedAuthInfoID: fedAuthInfoID, | |||
dataLength: dataLength, | |||
dataOffset: dataOffset, | |||
} | |||
} | |||
data := make([]byte, size-offset) | |||
r.ReadFull(data) | |||
for i := uint32(0); i < count; i++ { | |||
if opts[i].dataOffset < offset { | |||
badStreamPanicf("Fed auth info opt stated data offset %d is before data begins in packet at %d", | |||
opts[i].dataOffset, offset) | |||
// returns via panic | |||
} | |||
if opts[i].dataOffset+opts[i].dataLength > size { | |||
badStreamPanicf("Fed auth info opt stated data length %d added to stated offset exceeds size of packet %d", | |||
opts[i].dataOffset+opts[i].dataLength, size) | |||
// returns via panic | |||
} | |||
optData := data[opts[i].dataOffset-offset : opts[i].dataOffset-offset+opts[i].dataLength] | |||
switch opts[i].fedAuthInfoID { | |||
case fedAuthInfoSTSURL: | |||
STSURL, err = ucs22str(optData) | |||
case fedAuthInfoSPN: | |||
SPN, err = ucs22str(optData) | |||
default: | |||
err = fmt.Errorf("Unexpected fed auth info opt ID %d", int(opts[i].fedAuthInfoID)) | |||
} | |||
if err != nil { | |||
badStreamPanic(err) | |||
} | |||
} | |||
return fedAuthInfoStruct{ | |||
STSURL: STSURL, | |||
ServerSPN: SPN, | |||
} | |||
} | |||
type loginAckStruct struct { | |||
Interface uint8 | |||
TDSVersion uint32 | |||
@@ -449,19 +505,43 @@ func parseLoginAck(r *tdsBuffer) loginAckStruct { | |||
} | |||
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/2eb82f8e-11f0-46dc-b42d-27302fa4701a | |||
func parseFeatureExtAck(r *tdsBuffer) { | |||
// at most 1 featureAck per feature in featureExt | |||
// go-mssqldb will add at most 1 feature, the spec defines 7 different features | |||
for i := 0; i < 8; i++ { | |||
featureID := r.byte() // FeatureID | |||
if featureID == 0xff { | |||
return | |||
type fedAuthAckStruct struct { | |||
Nonce []byte | |||
Signature []byte | |||
} | |||
func parseFeatureExtAck(r *tdsBuffer) map[byte]interface{} { | |||
ack := map[byte]interface{}{} | |||
for feature := r.byte(); feature != featExtTERMINATOR; feature = r.byte() { | |||
length := r.uint32() | |||
switch feature { | |||
case featExtFEDAUTH: | |||
// In theory we need to know the federated authentication library to | |||
// know how to parse, but the alternatives provide compatible structures. | |||
fedAuthAck := fedAuthAckStruct{} | |||
if length >= 32 { | |||
fedAuthAck.Nonce = make([]byte, 32) | |||
r.ReadFull(fedAuthAck.Nonce) | |||
length -= 32 | |||
} | |||
if length >= 32 { | |||
fedAuthAck.Signature = make([]byte, 32) | |||
r.ReadFull(fedAuthAck.Signature) | |||
length -= 32 | |||
} | |||
ack[feature] = fedAuthAck | |||
} | |||
// Skip unprocessed bytes | |||
if length > 0 { | |||
io.CopyN(ioutil.Discard, r, int64(length)) | |||
} | |||
size := r.uint32() // FeatureAckDataLen | |||
d := make([]byte, size) | |||
r.ReadFull(d) | |||
} | |||
panic("parsed more than 7 featureAck's, protocol implementation error?") | |||
return ack | |||
} | |||
// http://msdn.microsoft.com/en-us/library/dd357363.aspx | |||
@@ -579,7 +659,7 @@ func processSingleResponse(sess *tdsSession, ch chan tokenStruct, outs map[strin | |||
} | |||
var columns []columnStruct | |||
errs := make([]Error, 0, 5) | |||
for { | |||
for tokens := 0; ; tokens += 1 { | |||
token := token(sess.buf.byte()) | |||
if sess.logFlags&logDebug != 0 { | |||
sess.log.Printf("got token %v", token) | |||
@@ -588,6 +668,9 @@ func processSingleResponse(sess *tdsSession, ch chan tokenStruct, outs map[strin | |||
case tokenSSPI: | |||
ch <- parseSSPIMsg(sess.buf) | |||
return | |||
case tokenFedAuthInfo: | |||
ch <- parseFedAuthInfo(sess.buf) | |||
return | |||
case tokenReturnStatus: | |||
returnStatus := parseReturnStatus(sess.buf) | |||
ch <- returnStatus | |||
@@ -595,7 +678,8 @@ func processSingleResponse(sess *tdsSession, ch chan tokenStruct, outs map[strin | |||
loginAck := parseLoginAck(sess.buf) | |||
ch <- loginAck | |||
case tokenFeatureExtAck: | |||
parseFeatureExtAck(sess.buf) | |||
featureExtAck := parseFeatureExtAck(sess.buf) | |||
ch <- featureExtAck | |||
case tokenOrder: | |||
order := parseOrder(sess.buf) | |||
ch <- order | |||
@@ -670,158 +754,137 @@ func processSingleResponse(sess *tdsSession, ch chan tokenStruct, outs map[strin | |||
} | |||
} | |||
type parseRespIter byte | |||
const ( | |||
parseRespIterContinue parseRespIter = iota // Continue parsing current token. | |||
parseRespIterNext // Fetch the next token. | |||
parseRespIterDone // Done with parsing the response. | |||
) | |||
type parseRespState byte | |||
const ( | |||
parseRespStateNormal parseRespState = iota // Normal response state. | |||
parseRespStateCancel // Query is canceled, wait for server to confirm. | |||
parseRespStateClosing // Waiting for tokens to come through. | |||
) | |||
type parseResp struct { | |||
sess *tdsSession | |||
ctxDone <-chan struct{} | |||
state parseRespState | |||
cancelError error | |||
type tokenProcessor struct { | |||
tokChan chan tokenStruct | |||
ctx context.Context | |||
sess *tdsSession | |||
outs map[string]interface{} | |||
lastRow []interface{} | |||
rowCount int64 | |||
firstError error | |||
} | |||
func (ts *parseResp) sendAttention(ch chan tokenStruct) parseRespIter { | |||
if err := sendAttention(ts.sess.buf); err != nil { | |||
ts.dlogf("failed to send attention signal %v", err) | |||
ch <- err | |||
return parseRespIterDone | |||
func startReading(sess *tdsSession, ctx context.Context, outs map[string]interface{}) *tokenProcessor { | |||
tokChan := make(chan tokenStruct, 5) | |||
go processSingleResponse(sess, tokChan, outs) | |||
return &tokenProcessor{ | |||
tokChan: tokChan, | |||
ctx: ctx, | |||
sess: sess, | |||
outs: outs, | |||
} | |||
ts.state = parseRespStateCancel | |||
return parseRespIterContinue | |||
} | |||
func (ts *parseResp) dlog(msg string) { | |||
// logging from goroutine is disabled to prevent | |||
// data race detection from firing | |||
// The race is probably happening when | |||
// test logger changes between tests. | |||
/*if ts.sess.logFlags&logDebug != 0 { | |||
ts.sess.log.Println(msg) | |||
}*/ | |||
} | |||
func (ts *parseResp) dlogf(f string, v ...interface{}) { | |||
/*if ts.sess.logFlags&logDebug != 0 { | |||
ts.sess.log.Printf(f, v...) | |||
}*/ | |||
func (t *tokenProcessor) iterateResponse() error { | |||
for { | |||
tok, err := t.nextToken() | |||
if err == nil { | |||
if tok == nil { | |||
return t.firstError | |||
} else { | |||
switch token := tok.(type) { | |||
case []columnStruct: | |||
t.sess.columns = token | |||
case []interface{}: | |||
t.lastRow = token | |||
case doneInProcStruct: | |||
if token.Status&doneCount != 0 { | |||
t.rowCount += int64(token.RowCount) | |||
} | |||
case doneStruct: | |||
if token.Status&doneCount != 0 { | |||
t.rowCount += int64(token.RowCount) | |||
} | |||
if token.isError() && t.firstError == nil { | |||
t.firstError = token.getError() | |||
} | |||
case ReturnStatus: | |||
t.sess.setReturnStatus(token) | |||
/*case error: | |||
if resultError == nil { | |||
resultError = token | |||
}*/ | |||
} | |||
} | |||
} else { | |||
return err | |||
} | |||
} | |||
} | |||
func (ts *parseResp) iter(ctx context.Context, ch chan tokenStruct, tokChan chan tokenStruct) parseRespIter { | |||
switch ts.state { | |||
func (t tokenProcessor) nextToken() (tokenStruct, error) { | |||
// we do this separate non-blocking check on token channel to | |||
// prioritize it over cancellation channel | |||
select { | |||
case tok, more := <-t.tokChan: | |||
err, more := tok.(error) | |||
if more { | |||
// this is an error and not a token | |||
return nil, err | |||
} else { | |||
return tok, nil | |||
} | |||
default: | |||
panic("unknown state") | |||
case parseRespStateNormal: | |||
select { | |||
case tok, ok := <-tokChan: | |||
if !ok { | |||
ts.dlog("response finished") | |||
return parseRespIterDone | |||
} | |||
if err, ok := tok.(net.Error); ok && err.Timeout() { | |||
ts.cancelError = err | |||
ts.dlog("got timeout error, sending attention signal to server") | |||
return ts.sendAttention(ch) | |||
} | |||
// Pass the token along. | |||
ch <- tok | |||
return parseRespIterContinue | |||
case <-ts.ctxDone: | |||
ts.ctxDone = nil | |||
ts.dlog("got cancel message, sending attention signal to server") | |||
return ts.sendAttention(ch) | |||
// there are no tokens on the channel, will need to wait | |||
} | |||
select { | |||
case tok, more := <-t.tokChan: | |||
if more { | |||
err, ok := tok.(error) | |||
if ok { | |||
// this is an error and not a token | |||
return nil, err | |||
} else { | |||
return tok, nil | |||
} | |||
} else { | |||
// completed reading response | |||
return nil, nil | |||
} | |||
case <-t.ctx.Done(): | |||
if err := sendAttention(t.sess.buf); err != nil { | |||
// unable to send attention, current connection is bad | |||
// notify caller and close channel | |||
return nil, err | |||
} | |||
case parseRespStateCancel: // Read all responses until a DONE or error is received.Auth | |||
select { | |||
case tok, ok := <-tokChan: | |||
if !ok { | |||
ts.dlog("response finished but waiting for attention ack") | |||
return parseRespIterNext | |||
} | |||
switch tok := tok.(type) { | |||
default: | |||
// Ignore all other tokens while waiting. | |||
// The TDS spec says other tokens may arrive after an attention | |||
// signal is sent. Ignore these tokens and continue looking for | |||
// a DONE with attention confirm mark. | |||
case doneStruct: | |||
if tok.Status&doneAttn != 0 { | |||
ts.dlog("got cancellation confirmation from server") | |||
if ts.cancelError != nil { | |||
ch <- ts.cancelError | |||
ts.cancelError = nil | |||
} else { | |||
ch <- ctx.Err() | |||
} | |||
return parseRespIterDone | |||
} | |||
// If an error happens during cancel, pass it along and just stop. | |||
// We are uncertain to receive more tokens. | |||
case error: | |||
ch <- tok | |||
ts.state = parseRespStateClosing | |||
} | |||
return parseRespIterContinue | |||
case <-ts.ctxDone: | |||
ts.ctxDone = nil | |||
ts.state = parseRespStateClosing | |||
return parseRespIterContinue | |||
// now the server should send cancellation confirmation | |||
// it is possible that we already received full response | |||
// just before we sent cancellation request | |||
// in this case current response would not contain confirmation | |||
// and we would need to read one more response | |||
// first lets finish reading current response and look | |||
// for confirmation in it | |||
if readCancelConfirmation(t.tokChan) { | |||
// we got confirmation in current response | |||
return nil, t.ctx.Err() | |||
} | |||
case parseRespStateClosing: // Wait for current token chan to close. | |||
if _, ok := <-tokChan; !ok { | |||
ts.dlog("response finished") | |||
return parseRespIterDone | |||
// we did not get cancellation confirmation in the current response | |||
// read one more response, it must be there | |||
t.tokChan = make(chan tokenStruct, 5) | |||
go processSingleResponse(t.sess, t.tokChan, t.outs) | |||
if readCancelConfirmation(t.tokChan) { | |||
return nil, t.ctx.Err() | |||
} | |||
return parseRespIterContinue | |||
// we did not get cancellation confirmation, something is not | |||
// right, this connection is not usable anymore | |||
return nil, errors.New("did not get cancellation confirmation from the server") | |||
} | |||
} | |||
func processResponse(ctx context.Context, sess *tdsSession, ch chan tokenStruct, outs map[string]interface{}) { | |||
ts := &parseResp{ | |||
sess: sess, | |||
ctxDone: ctx.Done(), | |||
} | |||
defer func() { | |||
// Ensure any remaining error is piped through | |||
// or the query may look like it executed when it actually failed. | |||
if ts.cancelError != nil { | |||
ch <- ts.cancelError | |||
ts.cancelError = nil | |||
} | |||
close(ch) | |||
}() | |||
// Loop over multiple responses. | |||
for { | |||
ts.dlog("initiating response reading") | |||
tokChan := make(chan tokenStruct) | |||
go processSingleResponse(sess, tokChan, outs) | |||
// Loop over multiple tokens in response. | |||
tokensLoop: | |||
for { | |||
switch ts.iter(ctx, ch, tokChan) { | |||
case parseRespIterContinue: | |||
// Nothing, continue to next token. | |||
case parseRespIterNext: | |||
break tokensLoop | |||
case parseRespIterDone: | |||
return | |||
func readCancelConfirmation(tokChan chan tokenStruct) bool { | |||
for tok := range tokChan { | |||
switch tok := tok.(type) { | |||
default: | |||
// just skip token | |||
case doneStruct: | |||
if tok.Status&doneAttn != 0 { | |||
// got cancellation confirmation, exit | |||
return true | |||
} | |||
} | |||
} | |||
return false | |||
} |
@@ -1,29 +1,24 @@ | |||
// Code generated by "stringer -type token"; DO NOT EDIT | |||
// Code generated by "stringer -type token"; DO NOT EDIT. | |||
package mssql | |||
import "fmt" | |||
import "strconv" | |||
const ( | |||
_token_name_0 = "tokenReturnStatus" | |||
_token_name_1 = "tokenColMetadata" | |||
_token_name_2 = "tokenOrdertokenErrortokenInfo" | |||
_token_name_3 = "tokenLoginAck" | |||
_token_name_4 = "tokenRowtokenNbcRow" | |||
_token_name_5 = "tokenEnvChange" | |||
_token_name_6 = "tokenSSPI" | |||
_token_name_7 = "tokenDonetokenDoneProctokenDoneInProc" | |||
_token_name_2 = "tokenOrdertokenErrortokenInfotokenReturnValuetokenLoginAcktokenFeatureExtAck" | |||
_token_name_3 = "tokenRowtokenNbcRow" | |||
_token_name_4 = "tokenEnvChange" | |||
_token_name_5 = "tokenSSPItokenFedAuthInfo" | |||
_token_name_6 = "tokenDonetokenDoneProctokenDoneInProc" | |||
) | |||
var ( | |||
_token_index_0 = [...]uint8{0, 17} | |||
_token_index_1 = [...]uint8{0, 16} | |||
_token_index_2 = [...]uint8{0, 10, 20, 29} | |||
_token_index_3 = [...]uint8{0, 13} | |||
_token_index_4 = [...]uint8{0, 8, 19} | |||
_token_index_5 = [...]uint8{0, 14} | |||
_token_index_6 = [...]uint8{0, 9} | |||
_token_index_7 = [...]uint8{0, 9, 22, 37} | |||
_token_index_2 = [...]uint8{0, 10, 20, 29, 45, 58, 76} | |||
_token_index_3 = [...]uint8{0, 8, 19} | |||
_token_index_5 = [...]uint8{0, 9, 25} | |||
_token_index_6 = [...]uint8{0, 9, 22, 37} | |||
) | |||
func (i token) String() string { | |||
@@ -32,22 +27,21 @@ func (i token) String() string { | |||
return _token_name_0 | |||
case i == 129: | |||
return _token_name_1 | |||
case 169 <= i && i <= 171: | |||
case 169 <= i && i <= 174: | |||
i -= 169 | |||
return _token_name_2[_token_index_2[i]:_token_index_2[i+1]] | |||
case i == 173: | |||
return _token_name_3 | |||
case 209 <= i && i <= 210: | |||
i -= 209 | |||
return _token_name_4[_token_index_4[i]:_token_index_4[i+1]] | |||
return _token_name_3[_token_index_3[i]:_token_index_3[i+1]] | |||
case i == 227: | |||
return _token_name_5 | |||
case i == 237: | |||
return _token_name_6 | |||
return _token_name_4 | |||
case 237 <= i && i <= 238: | |||
i -= 237 | |||
return _token_name_5[_token_index_5[i]:_token_index_5[i+1]] | |||
case 253 <= i && i <= 255: | |||
i -= 253 | |||
return _token_name_7[_token_index_7[i]:_token_index_7[i+1]] | |||
return _token_name_6[_token_index_6[i]:_token_index_6[i+1]] | |||
default: | |||
return fmt.Sprintf("token(%d)", i) | |||
return "token(" + strconv.FormatInt(int64(i), 10) + ")" | |||
} | |||
} |
@@ -21,11 +21,11 @@ type isoLevel uint8 | |||
const ( | |||
isolationUseCurrent isoLevel = 0 | |||
isolationReadUncommited = 1 | |||
isolationReadCommited = 2 | |||
isolationRepeatableRead = 3 | |||
isolationSerializable = 4 | |||
isolationSnapshot = 5 | |||
isolationReadUncommited isoLevel = 1 | |||
isolationReadCommited isoLevel = 2 | |||
isolationRepeatableRead isoLevel = 3 | |||
isolationSerializable isoLevel = 4 | |||
isolationSnapshot isoLevel = 5 | |||
) | |||
func sendBeginXact(buf *tdsBuffer, headers []headerStruct, isolation isoLevel, name string, resetSession bool) (err error) { |
@@ -4,6 +4,7 @@ package mssql | |||
import ( | |||
"bytes" | |||
"database/sql" | |||
"encoding/binary" | |||
"errors" | |||
"fmt" | |||
@@ -97,6 +98,9 @@ func (tvp TVP) encode(schema, name string, columnStr []columnStruct, tvpFieldInd | |||
for columnStrIdx, fieldIdx := range tvpFieldIndexes { | |||
field := refStr.Field(fieldIdx) | |||
tvpVal := field.Interface() | |||
if tvp.verifyStandardTypeOnNull(buf, tvpVal) { | |||
continue | |||
} | |||
valOf := reflect.ValueOf(tvpVal) | |||
elemKind := field.Kind() | |||
if elemKind == reflect.Ptr && valOf.IsNil() { | |||
@@ -155,7 +159,7 @@ func (tvp TVP) columnTypes() ([]columnStruct, []int, error) { | |||
defaultValues = append(defaultValues, v.Interface()) | |||
continue | |||
} | |||
defaultValues = append(defaultValues, reflect.Zero(field.Type).Interface()) | |||
defaultValues = append(defaultValues, tvp.createZeroType(reflect.Zero(field.Type).Interface())) | |||
} | |||
if columnCount-len(tvpFieldIndexes) == columnCount { | |||
@@ -209,19 +213,23 @@ func getSchemeAndName(tvpName string) (string, string, error) { | |||
} | |||
splitVal := strings.Split(tvpName, ".") | |||
if len(splitVal) > 2 { | |||
return "", "", errors.New("wrong tvp name") | |||
return "", "", ErrorObjectName | |||
} | |||
const ( | |||
openSquareBrackets = "[" | |||
closeSquareBrackets = "]" | |||
) | |||
if len(splitVal) == 2 { | |||
res := make([]string, 2) | |||
for key, value := range splitVal { | |||
tmp := strings.Replace(value, "[", "", -1) | |||
tmp = strings.Replace(tmp, "]", "", -1) | |||
tmp := strings.Replace(value, openSquareBrackets, "", -1) | |||
tmp = strings.Replace(tmp, closeSquareBrackets, "", -1) | |||
res[key] = tmp | |||
} | |||
return res[0], res[1], nil | |||
} | |||
tmp := strings.Replace(splitVal[0], "[", "", -1) | |||
tmp = strings.Replace(tmp, "]", "", -1) | |||
tmp := strings.Replace(splitVal[0], openSquareBrackets, "", -1) | |||
tmp = strings.Replace(tmp, closeSquareBrackets, "", -1) | |||
return "", tmp, nil | |||
} | |||
@@ -229,3 +237,56 @@ func getSchemeAndName(tvpName string) (string, string, error) { | |||
func getCountSQLSeparators(str string) int { | |||
return strings.Count(str, sqlSeparator) | |||
} | |||
// verify types https://golang.org/pkg/database/sql/ | |||
func (tvp TVP) createZeroType(fieldVal interface{}) interface{} { | |||
const ( | |||
defaultBool = false | |||
defaultFloat64 = float64(0) | |||
defaultInt64 = int64(0) | |||
defaultString = "" | |||
) | |||
switch fieldVal.(type) { | |||
case sql.NullBool: | |||
return defaultBool | |||
case sql.NullFloat64: | |||
return defaultFloat64 | |||
case sql.NullInt64: | |||
return defaultInt64 | |||
case sql.NullString: | |||
return defaultString | |||
} | |||
return fieldVal | |||
} | |||
// verify types https://golang.org/pkg/database/sql/ | |||
func (tvp TVP) verifyStandardTypeOnNull(buf *bytes.Buffer, tvpVal interface{}) bool { | |||
const ( | |||
defaultNull = uint8(0) | |||
) | |||
switch val := tvpVal.(type) { | |||
case sql.NullBool: | |||
if !val.Valid { | |||
binary.Write(buf, binary.LittleEndian, defaultNull) | |||
return true | |||
} | |||
case sql.NullFloat64: | |||
if !val.Valid { | |||
binary.Write(buf, binary.LittleEndian, defaultNull) | |||
return true | |||
} | |||
case sql.NullInt64: | |||
if !val.Valid { | |||
binary.Write(buf, binary.LittleEndian, defaultNull) | |||
return true | |||
} | |||
case sql.NullString: | |||
if !val.Valid { | |||
binary.Write(buf, binary.LittleEndian, uint64(_PLP_NULL)) | |||
return true | |||
} | |||
} | |||
return false | |||
} |
@@ -665,7 +665,7 @@ func readPLPType(ti *typeInfo, r *tdsBuffer) interface{} { | |||
default: | |||
buf = bytes.NewBuffer(make([]byte, 0, size)) | |||
} | |||
for true { | |||
for { | |||
chunksize := r.uint32() | |||
if chunksize == 0 { | |||
break | |||
@@ -690,6 +690,10 @@ func readPLPType(ti *typeInfo, r *tdsBuffer) interface{} { | |||
} | |||
func writePLPType(w io.Writer, ti typeInfo, buf []byte) (err error) { | |||
if buf == nil { | |||
err = binary.Write(w, binary.LittleEndian, uint64(_PLP_NULL)) | |||
return | |||
} | |||
if err = binary.Write(w, binary.LittleEndian, uint64(_UNKNOWN_PLP_LEN)); err != nil { | |||
return | |||
} | |||
@@ -807,7 +811,6 @@ func readVarLen(ti *typeInfo, r *tdsBuffer) { | |||
default: | |||
badStreamPanicf("Invalid type %d", ti.TypeId) | |||
} | |||
return | |||
} | |||
func decodeMoney(buf []byte) []byte { | |||
@@ -834,8 +837,7 @@ func decodeGuid(buf []byte) []byte { | |||
} | |||
func decodeDecimal(prec uint8, scale uint8, buf []byte) []byte { | |||
var sign uint8 | |||
sign = buf[0] | |||
sign := buf[0] | |||
var dec decimal.Decimal | |||
dec.SetPositive(sign != 0) | |||
dec.SetPrec(prec) | |||
@@ -1187,7 +1189,7 @@ func makeDecl(ti typeInfo) string { | |||
return fmt.Sprintf("char(%d)", ti.Size) | |||
case typeBigVarChar, typeVarChar: | |||
if ti.Size > 8000 || ti.Size == 0 { | |||
return fmt.Sprintf("varchar(max)") | |||
return "varchar(max)" | |||
} else { | |||
return fmt.Sprintf("varchar(%d)", ti.Size) | |||
} |
@@ -1,11 +1,16 @@ | |||
linters-settings: | |||
golint: | |||
min-confidence: 0.3 | |||
cyclop: | |||
max-complexity: 15 | |||
package-average: 10 | |||
linters: | |||
disable: | |||
- exhaustivestruct | |||
- gomnd | |||
- interfacer | |||
- maligned | |||
presets: | |||
- bugs | |||
- complexity |
@@ -1,5 +1,12 @@ | |||
# Change log | |||
## v2.4.2 - 2021-03-21 | |||
- Upgrade google/go-cmp v0.5.5 | |||
([#105](https://github.com/editorconfig/editorconfig-core-go/pull/105)); | |||
- Upgrade x/mod v0.4.2 | |||
([#106](https://github.com/editorconfig/editorconfig-core-go/pull/106)). | |||
## v2.4.1 - 2021-02-25 | |||
- Fix for Go 1.16 os.IsNotExist wrapping |
@@ -121,7 +121,7 @@ func (d *Definition) merge(md *Definition) { | |||
} | |||
// InsertToIniFile writes the definition into a ini file. | |||
func (d *Definition) InsertToIniFile(iniFile *ini.File) { // nolint: funlen,gocognit | |||
func (d *Definition) InsertToIniFile(iniFile *ini.File) { // nolint: funlen,gocognit,cyclop | |||
iniSec := iniFile.Section(d.Selector) | |||
for k, v := range d.Raw { |
@@ -33,7 +33,7 @@ func FnmatchCase(pattern, name string) (bool, error) { | |||
return r.MatchString(name), nil | |||
} | |||
func translate(pattern string) string { // nolint: funlen,gocognit,gocyclo | |||
func translate(pattern string) string { // nolint: funlen,gocognit,gocyclo,cyclop | |||
index := 0 | |||
pat := []rune(pattern) | |||
length := len(pat) |
@@ -3,8 +3,8 @@ module github.com/editorconfig/editorconfig-core-go/v2 | |||
go 1.13 | |||
require ( | |||
github.com/google/go-cmp v0.5.4 | |||
github.com/google/go-cmp v0.5.5 | |||
github.com/smartystreets/goconvey v1.6.4 // indirect | |||
golang.org/x/mod v0.4.1 | |||
golang.org/x/mod v0.4.2 | |||
gopkg.in/ini.v1 v1.62.0 | |||
) |
@@ -1,5 +1,5 @@ | |||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= | |||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= | |||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= | |||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | |||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= | |||
@@ -10,8 +10,8 @@ github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIK | |||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= | |||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||
golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY= | |||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= | |||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= |
@@ -1,21 +0,0 @@ | |||
The MIT license. | |||
Copyright (c) 2014 the go-unsnap-stream authors. | |||
Permission is hereby granted, free of charge, to any person obtaining a copy of | |||
this software and associated documentation files (the "Software"), to deal in | |||
the Software without restriction, including without limitation the rights to | |||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | |||
the Software, and to permit persons to whom the Software is furnished to do so, | |||
subject to the following conditions: | |||
The above copyright notice and this permission notice shall be included in all | |||
copies or substantial portions of the Software. | |||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | |||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | |||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | |||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
@@ -1,22 +0,0 @@ | |||
go-unsnap-stream | |||
================ | |||
This is a small golang library for decoding and encoding the snappy *streaming* format, specified here: https://github.com/google/snappy/blob/master/framing_format.txt | |||
Note that the *streaming or framing format* for snappy is different from snappy itself. Think of it as a train of boxcars: the streaming format breaks your data in chunks, applies snappy to each chunk alone, then puts a thin wrapper around the chunk, and sends it along in turn. You can begin decoding before receiving everything. And memory requirements for decoding are sane. | |||
Strangely, though the streaming format was first proposed in Go[1][2], it was never upated, and I could not locate any other library for Go that would handle the streaming/framed snappy format. Hence this implementation of the spec. There is a command line tool[3] that has a C implementation, but this is the only Go implementation that I am aware of. The reference for the framing/streaming spec seems to be the python implementation[4]. | |||
Update to the previous paragraph: Horray! Good news: Thanks to @nigeltao, we have since learned that the [github.com/golang/snappy](https://github.com/golang/snappy) package now provides the snappy streaming format too. Even though the type level descriptions are a little misleading because they don't mention that they are for the stream format, the [snappy package header documentation](https://godoc.org/github.com/golang/snappy) points out that the [snappy.Reader](https://godoc.org/github.com/golang/snappy#Reader) and [snappy.Writer](https://godoc.org/github.com/golang/snappy#Writer) types do indeed provide stream (vs block) handling. Although I have not benchmarked, you should probably prefer that package as it will likely be maintained more than I have time to devote, and also perhaps better integrated with the underlying snappy as they share the same repo. | |||
For binary compatibility with the [python implementation](https://pypi.python.org/pypi/python-snappy) in [4], one could use the C-snappy compressor/decompressor code directly; using github.com/dgryski/go-csnappy. In fact we did this for a while to verify byte-for-byte compatiblity, as the native Go implementation produces slightly different binary compression (still conformant with the standard of course), which made test-diffs harder, and some have complained about it being slower than the C. | |||
However, while the c-snappy was useful for checking compatibility, it introduced dependencies on external C libraries (both the c-snappy library and the C standard library). Our go binary executable that used the go-unsnap-stream library was no longer standalone, and deployment was painful if not impossible if the target had a different C standard library. So we've gone back to using the snappy-go implementation (entirely in Go) for ease of deployment. See the comments at the top of unsnap.go if you wish to use c-snappy instead. | |||
[1] https://groups.google.com/forum/#!msg/snappy-compression/qvLNe2cSH9s/R19oBC-p7g4J | |||
[2] https://codereview.appspot.com/5167058 | |||
[3] https://github.com/kubo/snzip | |||
[4] https://pypi.python.org/pypi/python-snappy |
@@ -1,375 +0,0 @@ | |||
package unsnap | |||
// copyright (c) 2014, Jason E. Aten | |||
// license: MIT | |||
// Some text from the Golang standard library doc is adapted and | |||
// reproduced in fragments below to document the expected behaviors | |||
// of the interface functions Read()/Write()/ReadFrom()/WriteTo() that | |||
// are implemented here. Those descriptions (see | |||
// http://golang.org/pkg/io/#Reader for example) are | |||
// copyright 2010 The Go Authors. | |||
import "io" | |||
// FixedSizeRingBuf: | |||
// | |||
// a fixed-size circular ring buffer. Yes, just what is says. | |||
// | |||
// We keep a pair of ping/pong buffers so that we can linearize | |||
// the circular buffer into a contiguous slice if need be. | |||
// | |||
// For efficiency, a FixedSizeRingBuf may be vastly preferred to | |||
// a bytes.Buffer. The ReadWithoutAdvance(), Advance(), and Adopt() | |||
// methods are all non-standard methods written for speed. | |||
// | |||
// For an I/O heavy application, I have replaced bytes.Buffer with | |||
// FixedSizeRingBuf and seen memory consumption go from 8GB to 25MB. | |||
// Yes, that is a 300x reduction in memory footprint. Everything ran | |||
// faster too. | |||
// | |||
// Note that Bytes(), while inescapable at times, is expensive: avoid | |||
// it if possible. Instead it is better to use the FixedSizeRingBuf.Readable | |||
// member to get the number of bytes available. Bytes() is expensive because | |||
// it may copy the back and then the front of a wrapped buffer A[Use] | |||
// into A[1-Use] in order to get a contiguous slice. If possible use ContigLen() | |||
// first to get the size that can be read without copying, Read() that | |||
// amount, and then Read() a second time -- to avoid the copy. | |||
type FixedSizeRingBuf struct { | |||
A [2][]byte // a pair of ping/pong buffers. Only one is active. | |||
Use int // which A buffer is in active use, 0 or 1 | |||
N int // MaxViewInBytes, the size of A[0] and A[1] in bytes. | |||
Beg int // start of data in A[Use] | |||
Readable int // number of bytes available to read in A[Use] | |||
OneMade bool // lazily instantiate the [1] buffer. If we never call Bytes(), | |||
// we may never need it. If OneMade is false, the Use must be = 0. | |||
} | |||
func (b *FixedSizeRingBuf) Make2ndBuffer() { | |||
if b.OneMade { | |||
return | |||
} | |||
b.A[1] = make([]byte, b.N, b.N) | |||
b.OneMade = true | |||
} | |||
// get the length of the largest read that we can provide to a contiguous slice | |||
// without an extra linearizing copy of all bytes internally. | |||
func (b *FixedSizeRingBuf) ContigLen() int { | |||
extent := b.Beg + b.Readable | |||
firstContigLen := intMin(extent, b.N) - b.Beg | |||
return firstContigLen | |||
} | |||
func NewFixedSizeRingBuf(maxViewInBytes int) *FixedSizeRingBuf { | |||
n := maxViewInBytes | |||
r := &FixedSizeRingBuf{ | |||
Use: 0, // 0 or 1, whichever is actually in use at the moment. | |||
// If we are asked for Bytes() and we wrap, linearize into the other. | |||
N: n, | |||
Beg: 0, | |||
Readable: 0, | |||
OneMade: false, | |||
} | |||
r.A[0] = make([]byte, n, n) | |||
// r.A[1] initialized lazily now. | |||
return r | |||
} | |||
// from the standard library description of Bytes(): | |||
// Bytes() returns a slice of the contents of the unread portion of the buffer. | |||
// If the caller changes the contents of the | |||
// returned slice, the contents of the buffer will change provided there | |||
// are no intervening method calls on the Buffer. | |||
// | |||
func (b *FixedSizeRingBuf) Bytes() []byte { | |||
extent := b.Beg + b.Readable | |||
if extent <= b.N { | |||
// we fit contiguously in this buffer without wrapping to the other | |||
return b.A[b.Use][b.Beg:(b.Beg + b.Readable)] | |||
} | |||
// wrap into the other buffer | |||
b.Make2ndBuffer() | |||
src := b.Use | |||
dest := 1 - b.Use | |||
n := copy(b.A[dest], b.A[src][b.Beg:]) | |||
n += copy(b.A[dest][n:], b.A[src][0:(extent%b.N)]) | |||
b.Use = dest | |||
b.Beg = 0 | |||
return b.A[b.Use][:n] | |||
} | |||
// Read(): | |||
// | |||
// from bytes.Buffer.Read(): Read reads the next len(p) bytes | |||
// from the buffer or until the buffer is drained. The return | |||
// value n is the number of bytes read. If the buffer has no data | |||
// to return, err is io.EOF (unless len(p) is zero); otherwise it is nil. | |||
// | |||
// from the description of the Reader interface, | |||
// http://golang.org/pkg/io/#Reader | |||
// | |||
/* | |||
Reader is the interface that wraps the basic Read method. | |||
Read reads up to len(p) bytes into p. It returns the number | |||
of bytes read (0 <= n <= len(p)) and any error encountered. | |||
Even if Read returns n < len(p), it may use all of p as scratch | |||
space during the call. If some data is available but not | |||
len(p) bytes, Read conventionally returns what is available | |||
instead of waiting for more. | |||
When Read encounters an error or end-of-file condition after | |||
successfully reading n > 0 bytes, it returns the number of bytes | |||
read. It may return the (non-nil) error from the same call or | |||
return the error (and n == 0) from a subsequent call. An instance | |||
of this general case is that a Reader returning a non-zero number | |||
of bytes at the end of the input stream may return | |||
either err == EOF or err == nil. The next Read should | |||
return 0, EOF regardless. | |||
Callers should always process the n > 0 bytes returned before | |||
considering the error err. Doing so correctly handles I/O errors | |||
that happen after reading some bytes and also both of the | |||
allowed EOF behaviors. | |||
Implementations of Read are discouraged from returning a zero | |||
byte count with a nil error, and callers should treat that | |||
situation as a no-op. | |||
*/ | |||
// | |||
func (b *FixedSizeRingBuf) Read(p []byte) (n int, err error) { | |||
return b.ReadAndMaybeAdvance(p, true) | |||
} | |||
// if you want to Read the data and leave it in the buffer, so as | |||
// to peek ahead for example. | |||
func (b *FixedSizeRingBuf) ReadWithoutAdvance(p []byte) (n int, err error) { | |||
return b.ReadAndMaybeAdvance(p, false) | |||
} | |||
func (b *FixedSizeRingBuf) ReadAndMaybeAdvance(p []byte, doAdvance bool) (n int, err error) { | |||
if len(p) == 0 { | |||
return 0, nil | |||
} | |||
if b.Readable == 0 { | |||
return 0, io.EOF | |||
} | |||
extent := b.Beg + b.Readable | |||
if extent <= b.N { | |||
n += copy(p, b.A[b.Use][b.Beg:extent]) | |||
} else { | |||
n += copy(p, b.A[b.Use][b.Beg:b.N]) | |||
if n < len(p) { | |||
n += copy(p[n:], b.A[b.Use][0:(extent%b.N)]) | |||
} | |||
} | |||
if doAdvance { | |||
b.Advance(n) | |||
} | |||
return | |||
} | |||
// | |||
// Write writes len(p) bytes from p to the underlying data stream. | |||
// It returns the number of bytes written from p (0 <= n <= len(p)) | |||
// and any error encountered that caused the write to stop early. | |||
// Write must return a non-nil error if it returns n < len(p). | |||
// | |||
func (b *FixedSizeRingBuf) Write(p []byte) (n int, err error) { | |||
for { | |||
if len(p) == 0 { | |||
// nothing (left) to copy in; notice we shorten our | |||
// local copy p (below) as we read from it. | |||
return | |||
} | |||
writeCapacity := b.N - b.Readable | |||
if writeCapacity <= 0 { | |||
// we are all full up already. | |||
return n, io.ErrShortWrite | |||
} | |||
if len(p) > writeCapacity { | |||
err = io.ErrShortWrite | |||
// leave err set and | |||
// keep going, write what we can. | |||
} | |||
writeStart := (b.Beg + b.Readable) % b.N | |||
upperLim := intMin(writeStart+writeCapacity, b.N) | |||
k := copy(b.A[b.Use][writeStart:upperLim], p) | |||
n += k | |||
b.Readable += k | |||
p = p[k:] | |||
// we can fill from b.A[b.Use][0:something] from | |||
// p's remainder, so loop | |||
} | |||
} | |||
// WriteTo and ReadFrom avoid intermediate allocation and copies. | |||
// WriteTo writes data to w until there's no more data to write | |||
// or when an error occurs. The return value n is the number of | |||
// bytes written. Any error encountered during the write is also returned. | |||
func (b *FixedSizeRingBuf) WriteTo(w io.Writer) (n int64, err error) { | |||
if b.Readable == 0 { | |||
return 0, io.EOF | |||
} | |||
extent := b.Beg + b.Readable | |||
firstWriteLen := intMin(extent, b.N) - b.Beg | |||
secondWriteLen := b.Readable - firstWriteLen | |||
if firstWriteLen > 0 { | |||
m, e := w.Write(b.A[b.Use][b.Beg:(b.Beg + firstWriteLen)]) | |||
n += int64(m) | |||
b.Advance(m) | |||
if e != nil { | |||
return n, e | |||
} | |||
// all bytes should have been written, by definition of | |||
// Write method in io.Writer | |||
if m != firstWriteLen { | |||
return n, io.ErrShortWrite | |||
} | |||
} | |||
if secondWriteLen > 0 { | |||
m, e := w.Write(b.A[b.Use][0:secondWriteLen]) | |||
n += int64(m) | |||
b.Advance(m) | |||
if e != nil { | |||
return n, e | |||
} | |||
// all bytes should have been written, by definition of | |||
// Write method in io.Writer | |||
if m != secondWriteLen { | |||
return n, io.ErrShortWrite | |||
} | |||
} | |||
return n, nil | |||
} | |||
// ReadFrom() reads data from r until EOF or error. The return value n | |||
// is the number of bytes read. Any error except io.EOF encountered | |||
// during the read is also returned. | |||
func (b *FixedSizeRingBuf) ReadFrom(r io.Reader) (n int64, err error) { | |||
for { | |||
writeCapacity := b.N - b.Readable | |||
if writeCapacity <= 0 { | |||
// we are all full | |||
return n, nil | |||
} | |||
writeStart := (b.Beg + b.Readable) % b.N | |||
upperLim := intMin(writeStart+writeCapacity, b.N) | |||
m, e := r.Read(b.A[b.Use][writeStart:upperLim]) | |||
n += int64(m) | |||
b.Readable += m | |||
if e == io.EOF { | |||
return n, nil | |||
} | |||
if e != nil { | |||
return n, e | |||
} | |||
} | |||
} | |||
func (b *FixedSizeRingBuf) Reset() { | |||
b.Beg = 0 | |||
b.Readable = 0 | |||
b.Use = 0 | |||
} | |||
// Advance(): non-standard, but better than Next(), | |||
// because we don't have to unwrap our buffer and pay the cpu time | |||
// for the copy that unwrapping may need. | |||
// Useful in conjuction/after ReadWithoutAdvance() above. | |||
func (b *FixedSizeRingBuf) Advance(n int) { | |||
if n <= 0 { | |||
return | |||
} | |||
if n > b.Readable { | |||
n = b.Readable | |||
} | |||
b.Readable -= n | |||
b.Beg = (b.Beg + n) % b.N | |||
} | |||
// Adopt(): non-standard. | |||
// | |||
// For efficiency's sake, (possibly) take ownership of | |||
// already allocated slice offered in me. | |||
// | |||
// If me is large we will adopt it, and we will potentially then | |||
// write to the me buffer. | |||
// If we already have a bigger buffer, copy me into the existing | |||
// buffer instead. | |||
func (b *FixedSizeRingBuf) Adopt(me []byte) { | |||
n := len(me) | |||
if n > b.N { | |||
b.A[0] = me | |||
b.OneMade = false | |||
b.N = n | |||
b.Use = 0 | |||
b.Beg = 0 | |||
b.Readable = n | |||
} else { | |||
// we already have a larger buffer, reuse it. | |||
copy(b.A[0], me) | |||
b.Use = 0 | |||
b.Beg = 0 | |||
b.Readable = n | |||
} | |||
} | |||
func intMax(a, b int) int { | |||
if a > b { | |||
return a | |||
} else { | |||
return b | |||
} | |||
} | |||
func intMin(a, b int) int { | |||
if a < b { | |||
return a | |||
} else { | |||
return b | |||
} | |||
} | |||
// Get the (beg, end] indices of the tailing empty buffer of bytes slice that from that is free for writing. | |||
// Note: not guaranteed to be zeroed. At all. | |||
func (b *FixedSizeRingBuf) GetEndmostWritable() (beg int, end int) { | |||
extent := b.Beg + b.Readable | |||
if extent < b.N { | |||
return extent, b.N | |||
} | |||
return extent % b.N, b.Beg | |||
} | |||
// Note: not guaranteed to be zeroed. | |||
func (b *FixedSizeRingBuf) GetEndmostWritableSlice() []byte { | |||
beg, e := b.GetEndmostWritable() | |||
return b.A[b.Use][beg:e] | |||
} |
@@ -1,100 +0,0 @@ | |||
package unsnap | |||
import ( | |||
"encoding/binary" | |||
// no c lib dependency | |||
snappy "github.com/golang/snappy" | |||
// or, use the C wrapper for speed | |||
//snappy "github.com/dgryski/go-csnappy" | |||
) | |||
// add Write() method for SnappyFile (see unsnap.go) | |||
// reference for snappy framing/streaming format: | |||
// http://code.google.com/p/snappy/source/browse/trunk/framing_format.txt | |||
// ?spec=svn68&r=71 | |||
// | |||
// Write writes len(p) bytes from p to the underlying data stream. | |||
// It returns the number of bytes written from p (0 <= n <= len(p)) and | |||
// any error encountered that caused the write to stop early. Write | |||
// must return a non-nil error if it returns n < len(p). | |||
// | |||
func (sf *SnappyFile) Write(p []byte) (n int, err error) { | |||
if sf.SnappyEncodeDecodeOff { | |||
return sf.Writer.Write(p) | |||
} | |||
if !sf.Writing { | |||
panic("Writing on a read-only SnappyFile") | |||
} | |||
// encoding in snappy can apparently go beyond the original size, beware. | |||
// so our buffers must be sized 2*max snappy chunk => 2 * CHUNK_MAX(65536) | |||
sf.DecBuf.Reset() | |||
sf.EncBuf.Reset() | |||
if !sf.HeaderChunkWritten { | |||
sf.HeaderChunkWritten = true | |||
_, err = sf.Writer.Write(SnappyStreamHeaderMagic) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
var chunk []byte | |||
var chunk_type byte | |||
var crc uint32 | |||
for len(p) > 0 { | |||
// chunk points to input p by default, unencoded input. | |||
chunk = p[:IntMin(len(p), CHUNK_MAX)] | |||
crc = masked_crc32c(chunk) | |||
writeme := chunk[:] | |||
// first write to EncBuf, as a temp, in case we want | |||
// to discard and send uncompressed instead. | |||
compressed_chunk := snappy.Encode(sf.EncBuf.GetEndmostWritableSlice(), chunk) | |||
if len(compressed_chunk) <= int((1-_COMPRESSION_THRESHOLD)*float64(len(chunk))) { | |||
writeme = compressed_chunk | |||
chunk_type = _COMPRESSED_CHUNK | |||
} else { | |||
// keep writeme pointing at original chunk (uncompressed) | |||
chunk_type = _UNCOMPRESSED_CHUNK | |||
} | |||
const crc32Sz = 4 | |||
var tag32 uint32 = uint32(chunk_type) + (uint32(len(writeme)+crc32Sz) << 8) | |||
err = binary.Write(sf.Writer, binary.LittleEndian, tag32) | |||
if err != nil { | |||
return | |||
} | |||
err = binary.Write(sf.Writer, binary.LittleEndian, crc) | |||
if err != nil { | |||
return | |||
} | |||
_, err = sf.Writer.Write(writeme) | |||
if err != nil { | |||
return | |||
} | |||
n += len(chunk) | |||
p = p[len(chunk):] | |||
} | |||
return n, nil | |||
} | |||
func IntMin(a int, b int) int { | |||
if a < b { | |||
return a | |||
} | |||
return b | |||
} |
@@ -1 +0,0 @@ | |||
hello_snappy |
@@ -1,520 +0,0 @@ | |||
package unsnap | |||
import ( | |||
"bytes" | |||
"encoding/binary" | |||
"fmt" | |||
"io" | |||
"io/ioutil" | |||
"os" | |||
"strings" | |||
"hash/crc32" | |||
snappy "github.com/golang/snappy" | |||
// The C library can be used, but this makes the binary dependent | |||
// lots of extraneous c-libraries; it is no longer stand-alone. Yuck. | |||
// | |||
// Therefore we comment out the "dgryski/go-csnappy" path and use the | |||
// "github.com/golang/snappy/snappy" above instead. If you are | |||
// performance limited and can deal with distributing more libraries, | |||
// then this is easy to swap. | |||
// | |||
// If you swap, note that some of the tests won't pass | |||
// because snappy-go produces slightly different (but still | |||
// conformant) encodings on some data. Here are bindings | |||
// to the C-snappy: | |||
// snappy "github.com/dgryski/go-csnappy" | |||
) | |||
// SnappyFile: create a drop-in-replacement/wrapper for an *os.File that handles doing the unsnappification online as more is read from it | |||
type SnappyFile struct { | |||
Fname string | |||
Reader io.Reader | |||
Writer io.Writer | |||
// allow clients to substitute us for an os.File and just switch | |||
// off compression if they don't want it. | |||
SnappyEncodeDecodeOff bool // if true, we bypass straight to Filep | |||
EncBuf FixedSizeRingBuf // holds any extra that isn't yet returned, encoded | |||
DecBuf FixedSizeRingBuf // holds any extra that isn't yet returned, decoded | |||
// for writing to stream-framed snappy | |||
HeaderChunkWritten bool | |||
// Sanity check: we can only read, or only write, to one SnappyFile. | |||
// EncBuf and DecBuf are used differently in each mode. Verify | |||
// that we are consistent with this flag. | |||
Writing bool | |||
} | |||
var total int | |||
// for debugging, show state of buffers | |||
func (f *SnappyFile) Dump() { | |||
fmt.Printf("EncBuf has length %d and contents:\n%s\n", len(f.EncBuf.Bytes()), string(f.EncBuf.Bytes())) | |||
fmt.Printf("DecBuf has length %d and contents:\n%s\n", len(f.DecBuf.Bytes()), string(f.DecBuf.Bytes())) | |||
} | |||
func (f *SnappyFile) Read(p []byte) (n int, err error) { | |||
if f.SnappyEncodeDecodeOff { | |||
return f.Reader.Read(p) | |||
} | |||
if f.Writing { | |||
panic("Reading on a write-only SnappyFile") | |||
} | |||
// before we unencrypt more, try to drain the DecBuf first | |||
n, _ = f.DecBuf.Read(p) | |||
if n > 0 { | |||
total += n | |||
return n, nil | |||
} | |||
//nEncRead, nDecAdded, err := UnsnapOneFrame(f.Filep, &f.EncBuf, &f.DecBuf, f.Fname) | |||
_, _, err = UnsnapOneFrame(f.Reader, &f.EncBuf, &f.DecBuf, f.Fname) | |||
if err != nil && err != io.EOF { | |||
return | |||
} | |||
n, _ = f.DecBuf.Read(p) | |||
if n > 0 { | |||
total += n | |||
return n, nil | |||
} | |||
if f.DecBuf.Readable == 0 { | |||
if f.DecBuf.Readable == 0 && f.EncBuf.Readable == 0 { | |||
// only now (when EncBuf is empty) can we give io.EOF. | |||
// Any earlier, and we leave stuff un-decoded! | |||
return 0, io.EOF | |||
} | |||
} | |||
return 0, nil | |||
} | |||
func Open(name string) (file *SnappyFile, err error) { | |||
fp, err := os.Open(name) | |||
if err != nil { | |||
return nil, err | |||
} | |||
// encoding in snappy can apparently go beyond the original size, so | |||
// we make our buffers big enough, 2*max snappy chunk => 2 * CHUNK_MAX(65536) | |||
snap := NewReader(fp) | |||
snap.Fname = name | |||
return snap, nil | |||
} | |||
func NewReader(r io.Reader) *SnappyFile { | |||
return &SnappyFile{ | |||
Reader: r, | |||
EncBuf: *NewFixedSizeRingBuf(CHUNK_MAX * 2), // buffer of snappy encoded bytes | |||
DecBuf: *NewFixedSizeRingBuf(CHUNK_MAX * 2), // buffer of snapppy decoded bytes | |||
Writing: false, | |||
} | |||
} | |||
func NewWriter(w io.Writer) *SnappyFile { | |||
return &SnappyFile{ | |||
Writer: w, | |||
EncBuf: *NewFixedSizeRingBuf(65536), // on writing: temp for testing compression | |||
DecBuf: *NewFixedSizeRingBuf(65536 * 2), // on writing: final buffer of snappy framed and encoded bytes | |||
Writing: true, | |||
} | |||
} | |||
func Create(name string) (file *SnappyFile, err error) { | |||
fp, err := os.Create(name) | |||
if err != nil { | |||
return nil, err | |||
} | |||
snap := NewWriter(fp) | |||
snap.Fname = name | |||
return snap, nil | |||
} | |||
func (f *SnappyFile) Close() error { | |||
if f.Writing { | |||
wc, ok := f.Writer.(io.WriteCloser) | |||
if ok { | |||
return wc.Close() | |||
} | |||
return nil | |||
} | |||
rc, ok := f.Reader.(io.ReadCloser) | |||
if ok { | |||
return rc.Close() | |||
} | |||
return nil | |||
} | |||
func (f *SnappyFile) Sync() error { | |||
file, ok := f.Writer.(*os.File) | |||
if ok { | |||
return file.Sync() | |||
} | |||
return nil | |||
} | |||
// for an increment of a frame at a time: | |||
// read from r into encBuf (encBuf is still encoded, thus the name), and write unsnappified frames into outDecodedBuf | |||
// the returned n: number of bytes read from the encrypted encBuf | |||
func UnsnapOneFrame(r io.Reader, encBuf *FixedSizeRingBuf, outDecodedBuf *FixedSizeRingBuf, fname string) (nEnc int64, nDec int64, err error) { | |||
// b, err := ioutil.ReadAll(r) | |||
// if err != nil { | |||
// panic(err) | |||
// } | |||
nEnc = 0 | |||
nDec = 0 | |||
// read up to 65536 bytes from r into encBuf, at least a snappy frame | |||
nread, err := io.CopyN(encBuf, r, 65536) // returns nwrotebytes, err | |||
nEnc += nread | |||
if err != nil { | |||
if err == io.EOF { | |||
if nread == 0 { | |||
if encBuf.Readable == 0 { | |||
return nEnc, nDec, io.EOF | |||
} | |||
// else we have bytes in encBuf, so decode them! | |||
err = nil | |||
} else { | |||
// continue below, processing the nread bytes | |||
err = nil | |||
} | |||
} else { | |||
// may be an odd already closed... don't panic on that | |||
if strings.Contains(err.Error(), "file already closed") { | |||
err = nil | |||
} else { | |||
panic(err) | |||
} | |||
} | |||
} | |||
// flag for printing chunk size alignment messages | |||
verbose := false | |||
const snappyStreamHeaderSz = 10 | |||
const headerSz = 4 | |||
const crc32Sz = 4 | |||
// the magic 18 bytes accounts for the snappy streaming header and the first chunks size and checksum | |||
// http://code.google.com/p/snappy/source/browse/trunk/framing_format.txt | |||
chunk := (*encBuf).Bytes() | |||
// however we exit, advance as | |||
// defer func() { (*encBuf).Next(N) }() | |||
// 65536 is the max size of a snappy framed chunk. See | |||
// http://code.google.com/p/snappy/source/browse/trunk/framing_format.txt:91 | |||
// buf := make([]byte, 65536) | |||
// fmt.Printf("read from file, b is len:%d with value: %#v\n", len(b), b) | |||
// fmt.Printf("read from file, bcut is len:%d with value: %#v\n", len(bcut), bcut) | |||
//fmt.Printf("raw bytes of chunksz are: %v\n", b[11:14]) | |||
fourbytes := make([]byte, 4) | |||
chunkCount := 0 | |||
for nDec < 65536 { | |||
if len(chunk) == 0 { | |||
break | |||
} | |||
chunkCount++ | |||
fourbytes[3] = 0 | |||
copy(fourbytes, chunk[1:4]) | |||
chunksz := binary.LittleEndian.Uint32(fourbytes) | |||
chunk_type := chunk[0] | |||
switch true { | |||
case chunk_type == 0xff: | |||
{ // stream identifier | |||
streamHeader := chunk[:snappyStreamHeaderSz] | |||
if 0 != bytes.Compare(streamHeader, []byte{0xff, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61, 0x50, 0x70, 0x59}) { | |||
panic("file had chunk starting with 0xff but then no magic snappy streaming protocol bytes, aborting.") | |||
} else { | |||
//fmt.Printf("got streaming snappy magic header just fine.\n") | |||
} | |||
chunk = chunk[snappyStreamHeaderSz:] | |||
(*encBuf).Advance(snappyStreamHeaderSz) | |||
nEnc += snappyStreamHeaderSz | |||
continue | |||
} | |||
case chunk_type == 0x00: | |||
{ // compressed data | |||
if verbose { | |||
fmt.Fprintf(os.Stderr, "chunksz is %d while total bytes avail are: %d\n", int(chunksz), len(chunk)-4) | |||
} | |||
crc := binary.LittleEndian.Uint32(chunk[headerSz:(headerSz + crc32Sz)]) | |||
section := chunk[(headerSz + crc32Sz):(headerSz + chunksz)] | |||
dec, ok := snappy.Decode(nil, section) | |||
if ok != nil { | |||
// we've probably truncated a snappy frame at this point | |||
// ok=snappy: corrupt input | |||
// len(dec) == 0 | |||
// | |||
err = fmt.Errorf("could not decode snappy stream: '%s' and len dec=%d and error='%v'\n", fname, len(dec), ok) | |||
// get back to caller with what we've got so far | |||
return nEnc, nDec, err | |||
} | |||
// fmt.Printf("ok, b is %#v , %#v\n", ok, dec) | |||
// spit out decoded text | |||
// n, err := w.Write(dec) | |||
//fmt.Printf("len(dec) = %d, outDecodedBuf.Readable=%d\n", len(dec), outDecodedBuf.Readable) | |||
bnb := bytes.NewBuffer(dec) | |||
n, err := io.Copy(outDecodedBuf, bnb) | |||
if err != nil { | |||
//fmt.Printf("got n=%d, err= %s ; when trying to io.Copy(outDecodedBuf: N=%d, Readable=%d)\n", n, err, outDecodedBuf.N, outDecodedBuf.Readable) | |||
panic(err) | |||
} | |||
if n != int64(len(dec)) { | |||
panic("could not write all bytes to outDecodedBuf") | |||
} | |||
nDec += n | |||
// verify the crc32 rotated checksum | |||
m32 := masked_crc32c(dec) | |||
if m32 != crc { | |||
panic(fmt.Sprintf("crc32 masked failiure. expected: %v but got: %v", crc, m32)) | |||
} else { | |||
//fmt.Printf("\nchecksums match: %v == %v\n", crc, m32) | |||
} | |||
// move to next header | |||
inc := (headerSz + int(chunksz)) | |||
chunk = chunk[inc:] | |||
(*encBuf).Advance(inc) | |||
nEnc += int64(inc) | |||
continue | |||
} | |||
case chunk_type == 0x01: | |||
{ // uncompressed data | |||
//n, err := w.Write(chunk[(headerSz+crc32Sz):(headerSz + int(chunksz))]) | |||
n, err := io.Copy(outDecodedBuf, bytes.NewBuffer(chunk[(headerSz+crc32Sz):(headerSz+int(chunksz))])) | |||
if verbose { | |||
//fmt.Printf("debug: n=%d err=%v chunksz=%d outDecodedBuf='%v'\n", n, err, chunksz, outDecodedBuf) | |||
} | |||
if err != nil { | |||
panic(err) | |||
} | |||
if n != int64(chunksz-crc32Sz) { | |||
panic("could not write all bytes to stdout") | |||
} | |||
nDec += n | |||
inc := (headerSz + int(chunksz)) | |||
chunk = chunk[inc:] | |||
(*encBuf).Advance(inc) | |||
nEnc += int64(inc) | |||
continue | |||
} | |||
case chunk_type == 0xfe: | |||
fallthrough // padding, just skip it | |||
case chunk_type >= 0x80 && chunk_type <= 0xfd: | |||
{ // Reserved skippable chunks | |||
//fmt.Printf("\nin reserved skippable chunks, at nEnc=%v\n", nEnc) | |||
inc := (headerSz + int(chunksz)) | |||
chunk = chunk[inc:] | |||
nEnc += int64(inc) | |||
(*encBuf).Advance(inc) | |||
continue | |||
} | |||
default: | |||
err = fmt.Errorf("unrecognized/unsupported chunk type %#v; on fname='%v'", chunk_type, fname) | |||
return nEnc, nDec, err | |||
} | |||
} // end for{} | |||
return nEnc, nDec, err | |||
//return int64(N), nil | |||
} | |||
// for whole file at once: | |||
// | |||
// receive on stdin a stream of bytes in the snappy-streaming framed | |||
// format, defined here: http://code.google.com/p/snappy/source/browse/trunk/framing_format.txt | |||
// Grab each frame, run it through the snappy decoder, and spit out | |||
// each frame all joined back-to-back on stdout. | |||
// | |||
func Unsnappy(r io.Reader, w io.Writer) (err error) { | |||
b, err := ioutil.ReadAll(r) | |||
if err != nil { | |||
panic(err) | |||
} | |||
// flag for printing chunk size alignment messages | |||
verbose := false | |||
const snappyStreamHeaderSz = 10 | |||
const headerSz = 4 | |||
const crc32Sz = 4 | |||
// the magic 18 bytes accounts for the snappy streaming header and the first chunks size and checksum | |||
// http://code.google.com/p/snappy/source/browse/trunk/framing_format.txt | |||
chunk := b[:] | |||
// 65536 is the max size of a snappy framed chunk. See | |||
// http://code.google.com/p/snappy/source/browse/trunk/framing_format.txt:91 | |||
//buf := make([]byte, 65536) | |||
// fmt.Printf("read from file, b is len:%d with value: %#v\n", len(b), b) | |||
// fmt.Printf("read from file, bcut is len:%d with value: %#v\n", len(bcut), bcut) | |||
//fmt.Printf("raw bytes of chunksz are: %v\n", b[11:14]) | |||
fourbytes := make([]byte, 4) | |||
chunkCount := 0 | |||
for { | |||
if len(chunk) == 0 { | |||
break | |||
} | |||
chunkCount++ | |||
fourbytes[3] = 0 | |||
copy(fourbytes, chunk[1:4]) | |||
chunksz := binary.LittleEndian.Uint32(fourbytes) | |||
chunk_type := chunk[0] | |||
switch true { | |||
case chunk_type == 0xff: | |||
{ // stream identifier | |||
streamHeader := chunk[:snappyStreamHeaderSz] | |||
if 0 != bytes.Compare(streamHeader, []byte{0xff, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61, 0x50, 0x70, 0x59}) { | |||
panic("file had chunk starting with 0xff but then no magic snappy streaming protocol bytes, aborting.") | |||
} else { | |||
//fmt.Printf("got streaming snappy magic header just fine.\n") | |||
} | |||
chunk = chunk[snappyStreamHeaderSz:] | |||
continue | |||
} | |||
case chunk_type == 0x00: | |||
{ // compressed data | |||
if verbose { | |||
fmt.Fprintf(os.Stderr, "chunksz is %d while total bytes avail are: %d\n", int(chunksz), len(chunk)-4) | |||
} | |||
//crc := binary.LittleEndian.Uint32(chunk[headerSz:(headerSz + crc32Sz)]) | |||
section := chunk[(headerSz + crc32Sz):(headerSz + chunksz)] | |||
dec, ok := snappy.Decode(nil, section) | |||
if ok != nil { | |||
panic("could not decode snappy stream") | |||
} | |||
// fmt.Printf("ok, b is %#v , %#v\n", ok, dec) | |||
// spit out decoded text | |||
n, err := w.Write(dec) | |||
if err != nil { | |||
panic(err) | |||
} | |||
if n != len(dec) { | |||
panic("could not write all bytes to stdout") | |||
} | |||
// TODO: verify the crc32 rotated checksum? | |||
// move to next header | |||
chunk = chunk[(headerSz + int(chunksz)):] | |||
continue | |||
} | |||
case chunk_type == 0x01: | |||
{ // uncompressed data | |||
//crc := binary.LittleEndian.Uint32(chunk[headerSz:(headerSz + crc32Sz)]) | |||
section := chunk[(headerSz + crc32Sz):(headerSz + chunksz)] | |||
n, err := w.Write(section) | |||
if err != nil { | |||
panic(err) | |||
} | |||
if n != int(chunksz-crc32Sz) { | |||
panic("could not write all bytes to stdout") | |||
} | |||
chunk = chunk[(headerSz + int(chunksz)):] | |||
continue | |||
} | |||
case chunk_type == 0xfe: | |||
fallthrough // padding, just skip it | |||
case chunk_type >= 0x80 && chunk_type <= 0xfd: | |||
{ // Reserved skippable chunks | |||
chunk = chunk[(headerSz + int(chunksz)):] | |||
continue | |||
} | |||
default: | |||
panic(fmt.Sprintf("unrecognized/unsupported chunk type %#v", chunk_type)) | |||
} | |||
} // end for{} | |||
return nil | |||
} | |||
// 0xff 0x06 0x00 0x00 sNaPpY | |||
var SnappyStreamHeaderMagic = []byte{0xff, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61, 0x50, 0x70, 0x59} | |||
const CHUNK_MAX = 65536 | |||
const _STREAM_TO_STREAM_BLOCK_SIZE = CHUNK_MAX | |||
const _STREAM_IDENTIFIER = `sNaPpY` | |||
const _COMPRESSED_CHUNK = 0x00 | |||
const _UNCOMPRESSED_CHUNK = 0x01 | |||
const _IDENTIFIER_CHUNK = 0xff | |||
const _RESERVED_UNSKIPPABLE0 = 0x02 // chunk ranges are [inclusive, exclusive) | |||
const _RESERVED_UNSKIPPABLE1 = 0x80 | |||
const _RESERVED_SKIPPABLE0 = 0x80 | |||
const _RESERVED_SKIPPABLE1 = 0xff | |||
// the minimum percent of bytes compression must save to be enabled in automatic | |||
// mode | |||
const _COMPRESSION_THRESHOLD = .125 | |||
var crctab *crc32.Table | |||
func init() { | |||
crctab = crc32.MakeTable(crc32.Castagnoli) // this is correct table, matches the crc32c.c code used by python | |||
} | |||
func masked_crc32c(data []byte) uint32 { | |||
// see the framing format specification, http://code.google.com/p/snappy/source/browse/trunk/framing_format.txt | |||
var crc uint32 = crc32.Checksum(data, crctab) | |||
return (uint32((crc>>15)|(crc<<17)) + 0xa282ead8) | |||
} | |||
func ReadSnappyStreamCompressedFile(filename string) ([]byte, error) { | |||
snappyFile, err := Open(filename) | |||
if err != nil { | |||
return []byte{}, err | |||
} | |||
var bb bytes.Buffer | |||
_, err = bb.ReadFrom(snappyFile) | |||
if err == io.EOF { | |||
err = nil | |||
} | |||
if err != nil { | |||
panic(err) | |||
} | |||
return bb.Bytes(), err | |||
} |
@@ -16,8 +16,8 @@ func main() { | |||
// Basic CORS | |||
// for more ideas, see: https://developer.github.com/v3/#cross-origin-resource-sharing | |||
r.Use(cors.Handler(cors.Options{ | |||
// AllowedOrigins: []string{"https://foo.com"}, // Use this to allow specific origin hosts | |||
AllowedOrigins: []string{"*"}, | |||
// AllowedOrigins: []string{"https://foo.com"}, // Use this to allow specific origin hosts | |||
AllowedOrigins: []string{"https://*", "http://*"}, | |||
// AllowOriginFunc: func(r *http.Request, origin string) bool { return true }, | |||
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, | |||
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"}, |
@@ -0,0 +1,3 @@ | |||
module github.com/go-chi/cors | |||
go 1.14 |
@@ -1,4 +1,4 @@ | |||
# go-billy [![GoDoc](https://godoc.org/gopkg.in/go-git/go-billy.v5?status.svg)](https://pkg.go.dev/github.com/go-git/go-billy) [![Test](https://github.com/go-git/go-billy/workflows/Test/badge.svg)](https://github.com/go-git/go-billy/actions?query=workflow%3ATest) | |||
# go-billy [![GoDoc](https://godoc.org/gopkg.in/go-git/go-billy.v5?status.svg)](https://pkg.go.dev/github.com/go-git/go-billy/v5) [![Test](https://github.com/go-git/go-billy/workflows/Test/badge.svg)](https://github.com/go-git/go-billy/actions?query=workflow%3ATest) | |||
The missing interface filesystem abstraction for Go. | |||
Billy implements an interface based on the `os` standard library, allowing to develop applications without dependency on the underlying storage. Makes it virtually free to implement mocks and testing over filesystem operations. |
@@ -89,6 +89,13 @@ type Config struct { | |||
Window uint | |||
} | |||
Init struct { | |||
// DefaultBranch Allows overriding the default branch name | |||
// e.g. when initializing a new repository or when cloning | |||
// an empty repository. | |||
DefaultBranch string | |||
} | |||
// Remotes list of repository remotes, the key of the map is the name | |||
// of the remote, should equal to RemoteConfig.Name. | |||
Remotes map[string]*RemoteConfig | |||
@@ -98,6 +105,9 @@ type Config struct { | |||
// Branches list of branches, the key is the branch name and should | |||
// equal Branch.Name | |||
Branches map[string]*Branch | |||
// URLs list of url rewrite rules, if repo url starts with URL.InsteadOf value, it will be replaced with the | |||
// key instead. | |||
URLs map[string]*URL | |||
// Raw contains the raw information of a config file. The main goal is | |||
// preserve the parsed information from the original format, to avoid | |||
// dropping unsupported fields. | |||
@@ -110,6 +120,7 @@ func NewConfig() *Config { | |||
Remotes: make(map[string]*RemoteConfig), | |||
Submodules: make(map[string]*Submodule), | |||
Branches: make(map[string]*Branch), | |||
URLs: make(map[string]*URL), | |||
Raw: format.New(), | |||
} | |||
@@ -223,6 +234,8 @@ const ( | |||
userSection = "user" | |||
authorSection = "author" | |||
committerSection = "committer" | |||
initSection = "init" | |||
urlSection = "url" | |||
fetchKey = "fetch" | |||
urlKey = "url" | |||
bareKey = "bare" | |||
@@ -233,6 +246,7 @@ const ( | |||
rebaseKey = "rebase" | |||
nameKey = "name" | |||
emailKey = "email" | |||
defaultBranchKey = "defaultBranch" | |||
// DefaultPackWindow holds the number of previous objects used to | |||
// generate deltas. The value 10 is the same used by git command. | |||
@@ -251,6 +265,7 @@ func (c *Config) Unmarshal(b []byte) error { | |||
c.unmarshalCore() | |||
c.unmarshalUser() | |||
c.unmarshalInit() | |||
if err := c.unmarshalPack(); err != nil { | |||
return err | |||
} | |||
@@ -260,6 +275,10 @@ func (c *Config) Unmarshal(b []byte) error { | |||
return err | |||
} | |||
if err := c.unmarshalURLs(); err != nil { | |||
return err | |||
} | |||
return c.unmarshalRemotes() | |||
} | |||
@@ -313,6 +332,25 @@ func (c *Config) unmarshalRemotes() error { | |||
c.Remotes[r.Name] = r | |||
} | |||
// Apply insteadOf url rules | |||
for _, r := range c.Remotes { | |||
r.applyURLRules(c.URLs) | |||
} | |||
return nil | |||
} | |||
func (c *Config) unmarshalURLs() error { | |||
s := c.Raw.Section(urlSection) | |||
for _, sub := range s.Subsections { | |||
r := &URL{} | |||
if err := r.unmarshal(sub); err != nil { | |||
return err | |||
} | |||
c.URLs[r.Name] = r | |||
} | |||
return nil | |||
} | |||
@@ -344,6 +382,11 @@ func (c *Config) unmarshalBranches() error { | |||
return nil | |||
} | |||
func (c *Config) unmarshalInit() { | |||
s := c.Raw.Section(initSection) | |||
c.Init.DefaultBranch = s.Options.Get(defaultBranchKey) | |||
} | |||
// Marshal returns Config encoded as a git-config file. | |||
func (c *Config) Marshal() ([]byte, error) { | |||
c.marshalCore() | |||
@@ -352,6 +395,8 @@ func (c *Config) Marshal() ([]byte, error) { | |||
c.marshalRemotes() | |||
c.marshalSubmodules() | |||
c.marshalBranches() | |||
c.marshalURLs() | |||
c.marshalInit() | |||
buf := bytes.NewBuffer(nil) | |||
if err := format.NewEncoder(buf).Encode(c.Raw); err != nil { | |||
@@ -475,6 +520,27 @@ func (c *Config) marshalBranches() { | |||
s.Subsections = newSubsections | |||
} | |||
func (c *Config) marshalURLs() { | |||
s := c.Raw.Section(urlSection) | |||
s.Subsections = make(format.Subsections, len(c.URLs)) | |||
var i int | |||
for _, r := range c.URLs { | |||
section := r.marshal() | |||
// the submodule section at config is a subset of the .gitmodule file | |||
// we should remove the non-valid options for the config file. | |||
s.Subsections[i] = section | |||
i++ | |||
} | |||
} | |||
func (c *Config) marshalInit() { | |||
s := c.Raw.Section(initSection) | |||
if c.Init.DefaultBranch != "" { | |||
s.SetOption(defaultBranchKey, c.Init.DefaultBranch) | |||
} | |||
} | |||
// RemoteConfig contains the configuration for a given remote repository. | |||
type RemoteConfig struct { | |||
// Name of the remote | |||
@@ -482,6 +548,12 @@ type RemoteConfig struct { | |||
// URLs the URLs of a remote repository. It must be non-empty. Fetch will | |||
// always use the first URL, while push will use all of them. | |||
URLs []string | |||
// insteadOfRulesApplied have urls been modified | |||
insteadOfRulesApplied bool | |||
// originalURLs are the urls before applying insteadOf rules | |||
originalURLs []string | |||
// Fetch the default set of "refspec" for fetch operation | |||
Fetch []RefSpec | |||
@@ -542,7 +614,12 @@ func (c *RemoteConfig) marshal() *format.Subsection { | |||
if len(c.URLs) == 0 { | |||
c.raw.RemoveOption(urlKey) | |||
} else { | |||
c.raw.SetOption(urlKey, c.URLs...) | |||
urls := c.URLs | |||
if c.insteadOfRulesApplied { | |||
urls = c.originalURLs | |||
} | |||
c.raw.SetOption(urlKey, urls...) | |||
} | |||
if len(c.Fetch) == 0 { | |||
@@ -562,3 +639,20 @@ func (c *RemoteConfig) marshal() *format.Subsection { | |||
func (c *RemoteConfig) IsFirstURLLocal() bool { | |||
return url.IsLocalEndpoint(c.URLs[0]) | |||
} | |||
func (c *RemoteConfig) applyURLRules(urlRules map[string]*URL) { | |||
// save original urls | |||
originalURLs := make([]string, len(c.URLs)) | |||
copy(originalURLs, c.URLs) | |||
for i, url := range c.URLs { | |||
if matchingURLRule := findLongestInsteadOfMatch(url, urlRules); matchingURLRule != nil { | |||
c.URLs[i] = matchingURLRule.ApplyInsteadOf(c.URLs[i]) | |||
c.insteadOfRulesApplied = true | |||
} | |||
} | |||
if c.insteadOfRulesApplied { | |||
c.originalURLs = originalURLs | |||
} | |||
} |
@@ -0,0 +1,81 @@ | |||
package config | |||
import ( | |||
"errors" | |||
"strings" | |||
format "github.com/go-git/go-git/v5/plumbing/format/config" | |||
) | |||
var ( | |||
errURLEmptyInsteadOf = errors.New("url config: empty insteadOf") | |||
) | |||
// Url defines Url rewrite rules | |||
type URL struct { | |||
// Name new base url | |||
Name string | |||
// Any URL that starts with this value will be rewritten to start, instead, with <base>. | |||
// When more than one insteadOf strings match a given URL, the longest match is used. | |||
InsteadOf string | |||
// raw representation of the subsection, filled by marshal or unmarshal are | |||
// called. | |||
raw *format.Subsection | |||
} | |||
// Validate validates fields of branch | |||
func (b *URL) Validate() error { | |||
if b.InsteadOf == "" { | |||
return errURLEmptyInsteadOf | |||
} | |||
return nil | |||
} | |||
const ( | |||
insteadOfKey = "insteadOf" | |||
) | |||
func (u *URL) unmarshal(s *format.Subsection) error { | |||
u.raw = s | |||
u.Name = s.Name | |||
u.InsteadOf = u.raw.Option(insteadOfKey) | |||
return nil | |||
} | |||
func (u *URL) marshal() *format.Subsection { | |||
if u.raw == nil { | |||
u.raw = &format.Subsection{} | |||
} | |||
u.raw.Name = u.Name | |||
u.raw.SetOption(insteadOfKey, u.InsteadOf) | |||
return u.raw | |||
} | |||
func findLongestInsteadOfMatch(remoteURL string, urls map[string]*URL) *URL { | |||
var longestMatch *URL | |||
for _, u := range urls { | |||
if !strings.HasPrefix(remoteURL, u.InsteadOf) { | |||
continue | |||
} | |||
// according to spec if there is more than one match, take the logest | |||
if longestMatch == nil || len(longestMatch.InsteadOf) < len(u.InsteadOf) { | |||
longestMatch = u | |||
} | |||
} | |||
return longestMatch | |||
} | |||
func (u *URL) ApplyInsteadOf(url string) string { | |||
if !strings.HasPrefix(url, u.InsteadOf) { | |||
return url | |||
} | |||
return u.Name + url[len(u.InsteadOf):] | |||
} |
@@ -1,27 +1,27 @@ | |||
module github.com/go-git/go-git/v5 | |||
require ( | |||
github.com/Microsoft/go-winio v0.4.16 // indirect | |||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 // indirect | |||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 | |||
github.com/emirpasic/gods v1.12.0 | |||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect | |||
github.com/gliderlabs/ssh v0.2.2 | |||
github.com/go-git/gcfg v1.5.0 | |||
github.com/go-git/go-billy/v5 v5.0.0 | |||
github.com/go-git/go-billy/v5 v5.1.0 | |||
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 | |||
github.com/google/go-cmp v0.3.0 | |||
github.com/imdario/mergo v0.3.9 | |||
github.com/imdario/mergo v0.3.12 | |||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 | |||
github.com/jessevdk/go-flags v1.4.0 | |||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd | |||
github.com/jessevdk/go-flags v1.5.0 | |||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 | |||
github.com/mitchellh/go-homedir v1.1.0 | |||
github.com/pkg/errors v0.8.1 // indirect | |||
github.com/sergi/go-diff v1.1.0 | |||
github.com/xanzy/ssh-agent v0.2.1 | |||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 | |||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a | |||
golang.org/x/text v0.3.2 | |||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f | |||
github.com/xanzy/ssh-agent v0.3.0 | |||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 | |||
golang.org/x/net v0.0.0-20210326060303-6b1517762897 | |||
golang.org/x/text v0.3.3 | |||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c | |||
gopkg.in/warnings.v0 v0.1.2 // indirect | |||
) | |||
@@ -1,3 +1,6 @@ | |||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= | |||
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= | |||
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= | |||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= | |||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= | |||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= | |||
@@ -18,6 +21,8 @@ github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= | |||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= | |||
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM= | |||
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= | |||
github.com/go-git/go-billy/v5 v5.1.0 h1:4pl5BV4o7ZG/lterP4S6WzJ6xr49Ba5ET9ygheTYahk= | |||
github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= | |||
github.com/go-git/go-git-fixtures/v4 v4.0.1 h1:q+IFMfLx200Q3scvt2hN79JsEzy4AmBTp/pqnefH+Bc= | |||
github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= | |||
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= | |||
@@ -26,14 +31,23 @@ github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= | |||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | |||
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= | |||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= | |||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= | |||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= | |||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= | |||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= | |||
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= | |||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= | |||
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= | |||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= | |||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= | |||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= | |||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= | |||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= | |||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | |||
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.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= | |||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= | |||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | |||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= | |||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | |||
@@ -45,38 +59,62 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb | |||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= | |||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= | |||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | |||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | |||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | |||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | |||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= | |||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= | |||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= | |||
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/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | |||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= | |||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | |||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= | |||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= | |||
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= | |||
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= | |||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/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-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= | |||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | |||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= | |||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= | |||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= | |||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | |||
golang.org/x/net v0.0.0-20210326060303-6b1517762897 h1:KrsHThm5nFk34YtATK1LsThyGhGbGe1olrte/HInHvs= | |||
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= | |||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20190221075227-b4e8571b14e0/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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= | |||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg= | |||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | |||
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.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= | |||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | |||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= | |||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= | |||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= | |||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= | |||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= | |||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= | |||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= | |||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
@@ -60,6 +60,10 @@ type CloneOptions struct { | |||
// Tags describe how the tags will be fetched from the remote repository, | |||
// by default is AllTags. | |||
Tags TagMode | |||
// InsecureSkipTLS skips ssl verify if protocol is https | |||
InsecureSkipTLS bool | |||
// CABundle specify additional ca bundle with system cert pool | |||
CABundle []byte | |||
} | |||
// Validate validates the fields and sets the default values. | |||
@@ -105,6 +109,10 @@ type PullOptions struct { | |||
// Force allows the pull to update a local branch even when the remote | |||
// branch does not descend from it. | |||
Force bool | |||
// InsecureSkipTLS skips ssl verify if protocol is https | |||
InsecureSkipTLS bool | |||
// CABundle specify additional ca bundle with system cert pool | |||
CABundle []byte | |||
} | |||
// Validate validates the fields and sets the default values. | |||
@@ -155,6 +163,10 @@ type FetchOptions struct { | |||
// Force allows the fetch to update a local branch even when the remote | |||
// branch does not descend from it. | |||
Force bool | |||
// InsecureSkipTLS skips ssl verify if protocol is https | |||
InsecureSkipTLS bool | |||
// CABundle specify additional ca bundle with system cert pool | |||
CABundle []byte | |||
} | |||
// Validate validates the fields and sets the default values. | |||
@@ -194,6 +206,13 @@ type PushOptions struct { | |||
// Force allows the push to update a remote branch even when the local | |||
// branch does not descend from it. | |||
Force bool | |||
// InsecureSkipTLS skips ssl verify if protocal is https | |||
InsecureSkipTLS bool | |||
// CABundle specify additional ca bundle with system cert pool | |||
CABundle []byte | |||
// RequireRemoteRefs only allows a remote ref to be updated if its current | |||
// value is the one specified here. | |||
RequireRemoteRefs []config.RefSpec | |||
} | |||
// Validate validates the fields and sets the default values. | |||
@@ -552,6 +571,10 @@ func (o *CreateTagOptions) loadConfigTagger(r *Repository) error { | |||
type ListOptions struct { | |||
// Auth credentials, if required, to use with the remote repository. | |||
Auth transport.AuthMethod | |||
// InsecureSkipTLS skips ssl verify if protocal is https | |||
InsecureSkipTLS bool | |||
// CABundle specify additional ca bundle with system cert pool | |||
CABundle []byte | |||
} | |||
// CleanOptions describes how a clean should be performed. |
@@ -38,6 +38,10 @@ type UnifiedEncoder struct { | |||
// a change. | |||
contextLines int | |||
// srcPrefix and dstPrefix are prepended to file paths when encoding a diff. | |||
srcPrefix string | |||
dstPrefix string | |||
// colorConfig is the color configuration. The default is no color. | |||
color ColorConfig | |||
} | |||
@@ -46,6 +50,8 @@ type UnifiedEncoder struct { | |||
func NewUnifiedEncoder(w io.Writer, contextLines int) *UnifiedEncoder { | |||
return &UnifiedEncoder{ | |||
Writer: w, | |||
srcPrefix: "a/", | |||
dstPrefix: "b/", | |||
contextLines: contextLines, | |||
} | |||
} | |||
@@ -56,6 +62,18 @@ func (e *UnifiedEncoder) SetColor(colorConfig ColorConfig) *UnifiedEncoder { | |||
return e | |||
} | |||
// SetSrcPrefix sets e's srcPrefix and returns e. | |||
func (e *UnifiedEncoder) SetSrcPrefix(prefix string) *UnifiedEncoder { | |||
e.srcPrefix = prefix | |||
return e | |||
} | |||
// SetDstPrefix sets e's dstPrefix and returns e. | |||
func (e *UnifiedEncoder) SetDstPrefix(prefix string) *UnifiedEncoder { | |||
e.dstPrefix = prefix | |||
return e | |||
} | |||
// Encode encodes patch. | |||
func (e *UnifiedEncoder) Encode(patch Patch) error { | |||
sb := &strings.Builder{} | |||
@@ -91,7 +109,8 @@ func (e *UnifiedEncoder) writeFilePatchHeader(sb *strings.Builder, filePatch Fil | |||
case from != nil && to != nil: | |||
hashEquals := from.Hash() == to.Hash() | |||
lines = append(lines, | |||
fmt.Sprintf("diff --git a/%s b/%s", from.Path(), to.Path()), | |||
fmt.Sprintf("diff --git %s%s %s%s", | |||
e.srcPrefix, from.Path(), e.dstPrefix, to.Path()), | |||
) | |||
if from.Mode() != to.Mode() { | |||
lines = append(lines, | |||
@@ -115,22 +134,22 @@ func (e *UnifiedEncoder) writeFilePatchHeader(sb *strings.Builder, filePatch Fil | |||
) | |||
} | |||
if !hashEquals { | |||
lines = e.appendPathLines(lines, "a/"+from.Path(), "b/"+to.Path(), isBinary) | |||
lines = e.appendPathLines(lines, e.srcPrefix+from.Path(), e.dstPrefix+to.Path(), isBinary) | |||
} | |||
case from == nil: | |||
lines = append(lines, | |||
fmt.Sprintf("diff --git a/%s b/%s", to.Path(), to.Path()), | |||
fmt.Sprintf("diff --git %s %s", e.srcPrefix+to.Path(), e.dstPrefix+to.Path()), | |||
fmt.Sprintf("new file mode %o", to.Mode()), | |||
fmt.Sprintf("index %s..%s", plumbing.ZeroHash, to.Hash()), | |||
) | |||
lines = e.appendPathLines(lines, "/dev/null", "b/"+to.Path(), isBinary) | |||
lines = e.appendPathLines(lines, "/dev/null", e.dstPrefix+to.Path(), isBinary) | |||
case to == nil: | |||
lines = append(lines, | |||
fmt.Sprintf("diff --git a/%s b/%s", from.Path(), from.Path()), | |||
fmt.Sprintf("diff --git %s %s", e.srcPrefix+from.Path(), e.dstPrefix+from.Path()), | |||
fmt.Sprintf("deleted file mode %o", from.Mode()), | |||
fmt.Sprintf("index %s..%s", from.Hash(), plumbing.ZeroHash), | |||
) | |||
lines = e.appendPathLines(lines, "a/"+from.Path(), "/dev/null", isBinary) | |||
lines = e.appendPathLines(lines, e.srcPrefix+from.Path(), "/dev/null", isBinary) | |||
} | |||
sb.WriteString(e.color[Meta]) |
@@ -125,7 +125,7 @@ func LoadGlobalPatterns(fs billy.Filesystem) (ps []Pattern, err error) { | |||
} | |||
// LoadSystemPatterns loads gitignore patterns from from the gitignore file | |||
// declared in a system's /etc/gitconfig file. If the ~/.gitconfig file does | |||
// declared in a system's /etc/gitconfig file. If the /etc/gitconfig file does | |||
// not exist the function will return nil. If the core.excludesfile property | |||
// is not declared, the function will return nil. If the file pointed to by | |||
// the core.excludesfile property does not exist, the function will return nil. |
@@ -230,6 +230,12 @@ const ( | |||
PushCert Capability = "push-cert" | |||
// SymRef symbolic reference support for better negotiation. | |||
SymRef Capability = "symref" | |||
// ObjectFormat takes a hash algorithm as an argument, indicates that the | |||
// server supports the given hash algorithms. | |||
ObjectFormat Capability = "object-format" | |||
// Filter if present, fetch-pack may send "filter" commands to request a | |||
// partial clone or partial fetch and request that the server omit various objects from the packfile | |||
Filter Capability = "filter" | |||
) | |||
const DefaultAgent = "go-git/4.x" | |||
@@ -241,10 +247,11 @@ var known = map[Capability]bool{ | |||
NoProgress: true, IncludeTag: true, ReportStatus: true, DeleteRefs: true, | |||
Quiet: true, Atomic: true, PushOptions: true, AllowTipSHA1InWant: true, | |||
AllowReachableSHA1InWant: true, PushCert: true, SymRef: true, | |||
ObjectFormat: true, Filter: true, | |||
} | |||
var requiresArgument = map[Capability]bool{ | |||
Agent: true, PushCert: true, SymRef: true, | |||
Agent: true, PushCert: true, SymRef: true, ObjectFormat: true, | |||
} | |||
var multipleArgument = map[Capability]bool{ |
@@ -3,7 +3,10 @@ | |||
package client | |||
import ( | |||
"crypto/tls" | |||
"crypto/x509" | |||
"fmt" | |||
gohttp "net/http" | |||
"github.com/go-git/go-git/v5/plumbing/transport" | |||
"github.com/go-git/go-git/v5/plumbing/transport/file" | |||
@@ -21,6 +24,14 @@ var Protocols = map[string]transport.Transport{ | |||
"file": file.DefaultClient, | |||
} | |||
var insecureClient = http.NewClient(&gohttp.Client{ | |||
Transport: &gohttp.Transport{ | |||
TLSClientConfig: &tls.Config{ | |||
InsecureSkipVerify: true, | |||
}, | |||
}, | |||
}) | |||
// InstallProtocol adds or modifies an existing protocol. | |||
func InstallProtocol(scheme string, c transport.Transport) { | |||
if c == nil { | |||
@@ -35,6 +46,31 @@ func InstallProtocol(scheme string, c transport.Transport) { | |||
// http://, https://, ssh:// and file://. | |||
// See `InstallProtocol` to add or modify protocols. | |||
func NewClient(endpoint *transport.Endpoint) (transport.Transport, error) { | |||
return getTransport(endpoint) | |||
} | |||
func getTransport(endpoint *transport.Endpoint) (transport.Transport, error) { | |||
if endpoint.Protocol == "https" { | |||
if endpoint.InsecureSkipTLS { | |||
return insecureClient, nil | |||
} | |||
if len(endpoint.CaBundle) != 0 { | |||
rootCAs, _ := x509.SystemCertPool() | |||
if rootCAs == nil { | |||
rootCAs = x509.NewCertPool() | |||
} | |||
rootCAs.AppendCertsFromPEM(endpoint.CaBundle) | |||
return http.NewClient(&gohttp.Client{ | |||
Transport: &gohttp.Transport{ | |||
TLSClientConfig: &tls.Config{ | |||
RootCAs: rootCAs, | |||
}, | |||
}, | |||
}), nil | |||
} | |||
} | |||
f, ok := Protocols[endpoint.Protocol] | |||
if !ok { | |||
return nil, fmt.Errorf("unsupported scheme %q", endpoint.Protocol) | |||
@@ -43,6 +79,5 @@ func NewClient(endpoint *transport.Endpoint) (transport.Transport, error) { | |||
if f == nil { | |||
return nil, fmt.Errorf("malformed client for scheme %q, client is defined as nil", endpoint.Protocol) | |||
} | |||
return f, nil | |||
} |
@@ -58,6 +58,11 @@ type Session interface { | |||
// If the repository does not exist, returns ErrRepositoryNotFound. | |||
// If the repository exists, but is empty, returns ErrEmptyRemoteRepository. | |||
AdvertisedReferences() (*packp.AdvRefs, error) | |||
// AdvertisedReferencesContext retrieves the advertised references for a | |||
// repository. | |||
// If the repository does not exist, returns ErrRepositoryNotFound. | |||
// If the repository exists, but is empty, returns ErrEmptyRemoteRepository. | |||
AdvertisedReferencesContext(context.Context) (*packp.AdvRefs, error) | |||
io.Closer | |||
} | |||
@@ -107,6 +112,10 @@ type Endpoint struct { | |||
Port int | |||
// Path is the repository path. | |||
Path string | |||
// InsecureSkipTLS skips ssl verify if protocal is https | |||
InsecureSkipTLS bool | |||
// CaBundle specify additional ca bundle with system cert pool | |||
CaBundle []byte | |||
} | |||
var defaultPorts = map[string]int{ |
@@ -3,6 +3,7 @@ package http | |||
import ( | |||
"bytes" | |||
"context" | |||
"fmt" | |||
"net" | |||
"net/http" | |||
@@ -32,7 +33,7 @@ func applyHeadersToRequest(req *http.Request, content *bytes.Buffer, host string | |||
const infoRefsPath = "/info/refs" | |||
func advertisedReferences(s *session, serviceName string) (ref *packp.AdvRefs, err error) { | |||
func advertisedReferences(ctx context.Context, s *session, serviceName string) (ref *packp.AdvRefs, err error) { | |||
url := fmt.Sprintf( | |||
"%s%s?service=%s", | |||
s.endpoint.String(), infoRefsPath, serviceName, | |||
@@ -45,7 +46,7 @@ func advertisedReferences(s *session, serviceName string) (ref *packp.AdvRefs, e | |||
s.ApplyAuthToRequest(req) | |||
applyHeadersToRequest(req, nil, s.endpoint.Host, serviceName) | |||
res, err := s.client.Do(req) | |||
res, err := s.client.Do(req.WithContext(ctx)) | |||
if err != nil { | |||
return nil, err | |||
} |
@@ -25,7 +25,11 @@ func newReceivePackSession(c *http.Client, ep *transport.Endpoint, auth transpor | |||
} | |||
func (s *rpSession) AdvertisedReferences() (*packp.AdvRefs, error) { | |||
return advertisedReferences(s.session, transport.ReceivePackServiceName) | |||
return advertisedReferences(context.TODO(), s.session, transport.ReceivePackServiceName) | |||
} | |||
func (s *rpSession) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) { | |||
return advertisedReferences(ctx, s.session, transport.ReceivePackServiceName) | |||
} | |||
func (s *rpSession) ReceivePack(ctx context.Context, req *packp.ReferenceUpdateRequest) ( |
@@ -25,7 +25,11 @@ func newUploadPackSession(c *http.Client, ep *transport.Endpoint, auth transport | |||
} | |||
func (s *upSession) AdvertisedReferences() (*packp.AdvRefs, error) { | |||
return advertisedReferences(s.session, transport.UploadPackServiceName) | |||
return advertisedReferences(context.TODO(), s.session, transport.UploadPackServiceName) | |||
} | |||
func (s *upSession) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) { | |||
return advertisedReferences(ctx, s.session, transport.UploadPackServiceName) | |||
} | |||
func (s *upSession) UploadPack( |
@@ -162,14 +162,18 @@ func (c *client) listenFirstError(r io.Reader) chan string { | |||
return errLine | |||
} | |||
// AdvertisedReferences retrieves the advertised references from the server. | |||
func (s *session) AdvertisedReferences() (*packp.AdvRefs, error) { | |||
return s.AdvertisedReferencesContext(context.TODO()) | |||
} | |||
// AdvertisedReferences retrieves the advertised references from the server. | |||
func (s *session) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) { | |||
if s.advRefs != nil { | |||
return s.advRefs, nil | |||
} | |||
ar := packp.NewAdvRefs() | |||
if err := ar.Decode(s.Stdout); err != nil { | |||
if err := ar.Decode(s.StdoutContext(ctx)); err != nil { | |||
if err := s.handleAdvRefDecodeError(err); err != nil { | |||
return nil, err | |||
} | |||
@@ -237,7 +241,7 @@ func (s *session) UploadPack(ctx context.Context, req *packp.UploadPackRequest) | |||
return nil, err | |||
} | |||
if _, err := s.AdvertisedReferences(); err != nil { | |||
if _, err := s.AdvertisedReferencesContext(ctx); err != nil { | |||
return nil, err | |||
} | |||
@@ -108,6 +108,10 @@ type upSession struct { | |||
} | |||
func (s *upSession) AdvertisedReferences() (*packp.AdvRefs, error) { | |||
return s.AdvertisedReferencesContext(context.TODO()) | |||
} | |||
func (s *upSession) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) { | |||
ar := packp.NewAdvRefs() | |||
if err := s.setSupportedCapabilities(ar.Capabilities); err != nil { | |||
@@ -204,6 +208,10 @@ type rpSession struct { | |||
} | |||
func (s *rpSession) AdvertisedReferences() (*packp.AdvRefs, error) { | |||
return s.AdvertisedReferencesContext(context.TODO()) | |||
} | |||
func (s *rpSession) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) { | |||
ar := packp.NewAdvRefs() | |||
if err := s.setSupportedCapabilities(ar.Capabilities); err != nil { |
@@ -6,6 +6,7 @@ import ( | |||
"fmt" | |||
"reflect" | |||
"strconv" | |||
"strings" | |||
"github.com/go-git/go-git/v5/plumbing/transport" | |||
"github.com/go-git/go-git/v5/plumbing/transport/internal/common" | |||
@@ -90,8 +91,14 @@ func (c *command) Close() error { | |||
//XXX: If did read the full packfile, then the session might be already | |||
// closed. | |||
_ = c.Session.Close() | |||
err := c.client.Close() | |||
return c.client.Close() | |||
//XXX: in go1.16+ we can use errors.Is(err, net.ErrClosed) | |||
if err != nil && strings.HasSuffix(err.Error(), "use of closed network connection") { | |||
return nil | |||
} | |||
return err | |||
} | |||
// connect connects to the SSH server, unless a AuthMethod was set with |
@@ -102,14 +102,14 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) { | |||
return fmt.Errorf("remote names don't match: %s != %s", o.RemoteName, r.c.Name) | |||
} | |||
s, err := newSendPackSession(r.c.URLs[0], o.Auth) | |||
s, err := newSendPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.CABundle) | |||
if err != nil { | |||
return err | |||
} | |||
defer ioutil.CheckClose(s, &err) | |||
ar, err := s.AdvertisedReferences() | |||
ar, err := s.AdvertisedReferencesContext(ctx) | |||
if err != nil { | |||
return err | |||
} | |||
@@ -119,6 +119,10 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) { | |||
return err | |||
} | |||
if err := r.checkRequireRemoteRefs(o.RequireRemoteRefs, remoteRefs); err != nil { | |||
return err | |||
} | |||
isDelete := false | |||
allDelete := true | |||
for _, rs := range o.RefSpecs { | |||
@@ -309,14 +313,14 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen | |||
o.RefSpecs = r.c.Fetch | |||
} | |||
s, err := newUploadPackSession(r.c.URLs[0], o.Auth) | |||
s, err := newUploadPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.CABundle) | |||
if err != nil { | |||
return nil, err | |||
} | |||
defer ioutil.CheckClose(s, &err) | |||
ar, err := s.AdvertisedReferences() | |||
ar, err := s.AdvertisedReferencesContext(ctx) | |||
if err != nil { | |||
return nil, err | |||
} | |||
@@ -369,8 +373,8 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen | |||
return remoteRefs, nil | |||
} | |||
func newUploadPackSession(url string, auth transport.AuthMethod) (transport.UploadPackSession, error) { | |||
c, ep, err := newClient(url) | |||
func newUploadPackSession(url string, auth transport.AuthMethod, insecure bool, cabundle []byte) (transport.UploadPackSession, error) { | |||
c, ep, err := newClient(url, auth, insecure, cabundle) | |||
if err != nil { | |||
return nil, err | |||
} | |||
@@ -378,8 +382,8 @@ func newUploadPackSession(url string, auth transport.AuthMethod) (transport.Uplo | |||
return c.NewUploadPackSession(ep, auth) | |||
} | |||
func newSendPackSession(url string, auth transport.AuthMethod) (transport.ReceivePackSession, error) { | |||
c, ep, err := newClient(url) | |||
func newSendPackSession(url string, auth transport.AuthMethod, insecure bool, cabundle []byte) (transport.ReceivePackSession, error) { | |||
c, ep, err := newClient(url, auth, insecure, cabundle) | |||
if err != nil { | |||
return nil, err | |||
} | |||
@@ -387,11 +391,13 @@ func newSendPackSession(url string, auth transport.AuthMethod) (transport.Receiv | |||
return c.NewReceivePackSession(ep, auth) | |||
} | |||
func newClient(url string) (transport.Transport, *transport.Endpoint, error) { | |||
func newClient(url string, auth transport.AuthMethod, insecure bool, cabundle []byte) (transport.Transport, *transport.Endpoint, error) { | |||
ep, err := transport.NewEndpoint(url) | |||
if err != nil { | |||
return nil, nil, err | |||
} | |||
ep.InsecureSkipTLS = insecure | |||
ep.CaBundle = cabundle | |||
c, err := client.NewClient(ep) | |||
if err != nil { | |||
@@ -1025,14 +1031,14 @@ func (r *Remote) buildFetchedTags(refs memory.ReferenceStorage) (updated bool, e | |||
// List the references on the remote repository. | |||
func (r *Remote) List(o *ListOptions) (rfs []*plumbing.Reference, err error) { | |||
s, err := newUploadPackSession(r.c.URLs[0], o.Auth) | |||
s, err := newUploadPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.CABundle) | |||
if err != nil { | |||
return nil, err | |||
} | |||
defer ioutil.CheckClose(s, &err) | |||
ar, err := s.AdvertisedReferences() | |||
ar, err := s.AdvertisedReferencesContext(context.TODO()) | |||
if err != nil { | |||
return nil, err | |||
} | |||
@@ -1164,3 +1170,33 @@ outer: | |||
return r.s.SetShallow(shallows) | |||
} | |||
func (r *Remote) checkRequireRemoteRefs(requires []config.RefSpec, remoteRefs storer.ReferenceStorer) error { | |||
for _, require := range requires { | |||
if require.IsWildcard() { | |||
return fmt.Errorf("wildcards not supported in RequireRemoteRefs, got %s", require.String()) | |||
} | |||
name := require.Dst("") | |||
remote, err := remoteRefs.Reference(name) | |||
if err != nil { | |||
return fmt.Errorf("remote ref %s required to be %s but is absent", name.String(), require.Src()) | |||
} | |||
var requireHash string | |||
if require.IsExactSHA1() { | |||
requireHash = require.Src() | |||
} else { | |||
target, err := storer.ResolveReference(remoteRefs, plumbing.ReferenceName(require.Src())) | |||
if err != nil { | |||
return fmt.Errorf("could not resolve ref %s in RequireRemoteRefs", require.Src()) | |||
} | |||
requireHash = target.Hash().String() | |||
} | |||
if remote.Hash().String() != requireHash { | |||
return fmt.Errorf("remote ref %s required to be %s but is %s", name.String(), requireHash, remote.Hash().String()) | |||
} | |||
} | |||
return nil | |||
} |