diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 64b3d28d6b..260727f15e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -88,7 +88,7 @@ update these instructions. ## Vendoring We keep a cached copy of dependencies within the `vendor/` directory, -managing updates via [dep](https://github.com/golang/dep). +managing updates via [Modules](https://golang.org/cmd/go/#hdr-Module_maintenance). Pull requests should only include `vendor/` updates if they are part of the same change, be it a bugfix or a feature addition. @@ -97,7 +97,7 @@ The `vendor/` update needs to be justified as part of the PR description, and must be verified by the reviewers and/or merger to always reference an existing upstream commit. -You can find more information on how to get started with it on the [dep project website](https://golang.github.io/dep/docs/introduction.html). +You can find more information on how to get started with it on the [Modules Wiki](https://github.com/golang/go/wiki/Modules). ## Translation diff --git a/Gopkg.lock b/Gopkg.lock deleted file mode 100644 index bc29e41c58..0000000000 --- a/Gopkg.lock +++ /dev/null @@ -1,1336 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "master" - digest = "1:dbf849e6552740945ac1c6c6acba590fbc594e4efa80cf05568dec8579ae0dab" - name = "code.gitea.io/sdk" - packages = ["gitea"] - pruneopts = "NUT" - revision = "a669487e86e0cc5833a2867e6476da6327244a1a" - -[[projects]] - digest = "1:5d72bbcc9c8667b11c3dc3cbe681c5a6f71e5096744c0bf7726ab5c6425d5dc4" - name = "github.com/BurntSushi/toml" - packages = ["."] - pruneopts = "NUT" - revision = "3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005" - version = "v0.3.1" - -[[projects]] - digest = "1:3fcef06a1a6561955c94af6c7757a6fa37605eb653f0d06ab960e5bb80092195" - name = "github.com/PuerkitoBio/goquery" - packages = ["."] - pruneopts = "NUT" - revision = "ed7d758e9a34ba1f55e8084e0d731448b46921a8" - -[[projects]] - digest = "1:44121ca443aec4512ceaeec5047d0162b86bfcc26f35eadddda93bc265cb2e39" - name = "github.com/RoaringBitmap/roaring" - packages = ["."] - pruneopts = "NUT" - revision = "1a28a7fa985680f9f4e1644c0a857ec359a444b0" - version = "v0.4.7" - -[[projects]] - branch = "master" - digest = "1:d290f4b25abbf574f80f60c8a5603ddada784f13f436b91a9a927bc7ce5a0146" - name = "github.com/Unknwon/cae" - packages = [ - ".", - "zip", - ] - pruneopts = "NUT" - revision = "c6aac99ea2cae2ebaf23f26f76b04fe3fcfc9f8c" - -[[projects]] - branch = "master" - digest = "1:7d23e6e1889b8bb4bbb37a564708fdab4497ce232c3a99d66406c975b642a6ff" - name = "github.com/Unknwon/com" - packages = ["."] - pruneopts = "NUT" - revision = "7677a1d7c1137cd3dd5ba7a076d0c898a1ef4520" - -[[projects]] - branch = "master" - digest = "1:a89bad9aea65873d45195417902ba1e6245114bdf1005d855909a7725b0361d1" - name = "github.com/Unknwon/i18n" - packages = ["."] - pruneopts = "NUT" - revision = "b64d336589669d317928070e70ba0ae558f16633" - -[[projects]] - digest = "1:d311c4c0cfd13f237665b248a55c909d5b40815c06f28992f35cba3266ef27da" - name = "github.com/Unknwon/paginater" - packages = ["."] - pruneopts = "NUT" - revision = "7748a72e01415173a27d79866b984328e7b0c12b" - -[[projects]] - digest = "1:fc86904a62ac4bfff8cfbe94f42231ce3d8cea8fe2506d5293eaef468f8eaecf" - name = "github.com/andybalholm/cascadia" - packages = ["."] - pruneopts = "NUT" - revision = "349dd0209470eabd9514242c688c403c0926d266" - -[[projects]] - branch = "master" - digest = "1:707ebe952a8b3d00b343c01536c79c73771d100f63ec6babeaed5c79e2b8a8dd" - name = "github.com/beorn7/perks" - packages = ["quantile"] - pruneopts = "NUT" - revision = "3a771d992973f24aa725d07868b467d1ddfceafb" - -[[projects]] - digest = "1:b17287a86f6cac923a5d886e10618df994eeb54b6724eac2e3b8dde89cfbe3a2" - name = "github.com/blevesearch/bleve" - packages = [ - ".", - "analysis", - "analysis/analyzer/custom", - "analysis/analyzer/standard", - "analysis/datetime/flexible", - "analysis/datetime/optional", - "analysis/lang/en", - "analysis/token/camelcase", - "analysis/token/lowercase", - "analysis/token/porter", - "analysis/token/stop", - "analysis/token/unicodenorm", - "analysis/token/unique", - "analysis/tokenizer/unicode", - "document", - "geo", - "index", - "index/scorch", - "index/scorch/mergeplan", - "index/scorch/segment", - "index/scorch/segment/zap", - "index/store", - "index/store/boltdb", - "index/store/gtreap", - "index/upsidedown", - "mapping", - "numeric", - "registry", - "search", - "search/collector", - "search/facet", - "search/highlight", - "search/highlight/format/html", - "search/highlight/fragmenter/simple", - "search/highlight/highlighter/html", - "search/highlight/highlighter/simple", - "search/query", - "search/scorer", - "search/searcher", - "size", - ] - pruneopts = "NUT" - revision = "05d86ea8f6e30456949f612cf68cf4a27ce8c9c5" - -[[projects]] - branch = "master" - digest = "1:b165e3f145596f4ff864a34e38e0b63c8e57bbaec2d5a234f234f7554b84c42b" - name = "github.com/blevesearch/go-porterstemmer" - packages = ["."] - pruneopts = "NUT" - revision = "23a2c8e5cf1f380f27722c6d2ae8896431dc7d0e" - -[[projects]] - digest = "1:a64956a7766e0d081ebff30d8528db107118485d2ee89cab751e6506f5ab55ea" - name = "github.com/blevesearch/segment" - packages = ["."] - pruneopts = "NUT" - revision = "db70c57796cc8c310613541dfade3dce627d09c7" - -[[projects]] - digest = "1:7c96cf7bf7f52af67f7a8222185813b9b665f5172ec2ac5f7d49ed96e5fcf3e5" - name = "github.com/boombuler/barcode" - packages = [ - ".", - "qr", - "utils", - ] - pruneopts = "NUT" - revision = "fe0f26ff6d26693948ee8189aa064ee8c54141fa" - -[[projects]] - digest = "1:867be5f6a8d3bf4525390559899af512f48675932e2cc3cbaa2304e9c75fc1ba" - name = "github.com/bradfitz/gomemcache" - packages = ["memcache"] - pruneopts = "NUT" - revision = "fb1f79c6b65acda83063cbc69f6bba1522558bfc" - -[[projects]] - digest = "1:ce4ec45b1c748a187386bfb3adc6b78f07a3c6cecc689f7bf68dd0d3630c6d58" - name = "github.com/chaseadamsio/goorgeous" - packages = ["."] - pruneopts = "NUT" - revision = "098da33fde5f9220736531b3cb26a2dec86a8367" - -[[projects]] - branch = "master" - digest = "1:eb205556fe75307c6d2b58d4159e7c2da23e2666481d352c66d4055bebf45a3c" - name = "github.com/couchbase/gomemcached" - packages = [ - ".", - "client", - ] - pruneopts = "NUT" - revision = "5125a94a666c83cb9b7a60907833cd320b84c20f" - -[[projects]] - branch = "master" - digest = "1:ea03e12e246f7708a7b7ab3ad04e96d21ce73f48bb56258bc2bffeed474212e6" - name = "github.com/couchbase/goutils" - packages = [ - "logging", - "scramsha", - ] - pruneopts = "NUT" - revision = "e865a1461c8ac0032bd37e2d4dab3289faea3873" - -[[projects]] - branch = "master" - digest = "1:6a658ac7d23204dc743c7155557c45273747d78e05ae0579742bd6b744bce215" - name = "github.com/couchbase/vellum" - packages = [ - ".", - "levenshtein2", - "regexp", - "utf8", - ] - pruneopts = "NUT" - revision = "e91b68ff3efe3cc11723aa25dd315cbc9276cd65" - -[[projects]] - branch = "master" - digest = "1:df592f4b82b993fcac270862376c34210776b8b0334a0f59f4d9d80467713ffa" - name = "github.com/couchbaselabs/go-couchbase" - packages = ["."] - pruneopts = "NUT" - revision = "d904413d884d1fb849e2ad8834619f661761ef57" - -[[projects]] - digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39" - name = "github.com/davecgh/go-spew" - packages = ["spew"] - pruneopts = "NUT" - revision = "346938d642f2ec3594ed81d874461961cd0faa76" - version = "v1.1.0" - -[[projects]] - digest = "1:08c314ceab5d0a82739bb0846a5d764bed6f1294610e79b651a4c08671830ecb" - name = "github.com/denisenkom/go-mssqldb" - packages = ["."] - pruneopts = "NUT" - revision = "e32ca5036449b7ea12c62ed761ea1ad7fc88a4e2" - -[[projects]] - digest = "1:01ced7908dbaae42990af9521328922b8948bdcb174c23bba6db572381515716" - name = "github.com/dgrijalva/jwt-go" - packages = ["."] - pruneopts = "NUT" - revision = "9ed569b5d1ac936e6494082958d63a6aa4fff99a" - -[[projects]] - branch = "master" - digest = "1:7e2a28602fd65774c79a780a9c32a7a82d180e5a93bb5a36a6beb8619e24a35b" - name = "github.com/edsrzf/mmap-go" - packages = ["."] - pruneopts = "NUT" - revision = "0bce6a6887123b67a60366d2c9fe2dfb74289d2e" - -[[projects]] - digest = "1:9b7f3250d2bd2c70fef82ff79a1c43cfacedd114288af3b86da0c31c67756a2f" - name = "github.com/elazarl/go-bindata-assetfs" - packages = ["."] - pruneopts = "NUT" - revision = "57eb5e1fc594ad4b0b1dbea7b286d299e0cb43c2" - -[[projects]] - digest = "1:b498b36dbb2b306d1c5205ee5236c9e60352be8f9eea9bf08186723a9f75b4f3" - name = "github.com/emirpasic/gods" - packages = [ - "containers", - "lists", - "lists/arraylist", - "trees", - "trees/binaryheap", - "utils", - ] - pruneopts = "NUT" - revision = "1615341f118ae12f353cc8a983f35b584342c9b3" - version = "v1.12.0" - -[[projects]] - digest = "1:ae8eea1a24ae43a46c2e96631b6303fcc4210ca0ac9d643e4da965029d1b511d" - name = "github.com/etcd-io/bbolt" - packages = ["."] - pruneopts = "NUT" - revision = "63597a96ec0ad9e6d43c3fc81e809909e0237461" - version = "v1.3.2" - -[[projects]] - digest = "1:8603f74d35c93b37c615a02ba297be2cf2efc9ff6f1ff2b458a903990b568e48" - name = "github.com/ethantkoenig/rupture" - packages = ["."] - pruneopts = "NUT" - revision = "0a76f03a811abcca2e6357329b673e9bb8ef9643" - -[[projects]] - branch = "master" - digest = "1:b29ac3fe6b4601f89b589337c584ab7204a5c72932465e5f4a16772b5560b4a7" - name = "github.com/facebookgo/clock" - packages = ["."] - pruneopts = "NUT" - revision = "600d898af40aa09a7a93ecb9265d87b0504b6f03" - -[[projects]] - digest = "1:ee3e74e7e3789fc2de1479146477b5cc31f9344dfe2772c01a967a13552c7e60" - name = "github.com/facebookgo/grace" - packages = [ - "gracehttp", - "gracenet", - ] - pruneopts = "NUT" - revision = "5729e484473f52048578af1b80d0008c7024089b" - -[[projects]] - branch = "master" - digest = "1:ff3883a000118ba7efd4c41cc4656592e97d3a0860225d5f087a194066685ce4" - name = "github.com/facebookgo/httpdown" - packages = ["."] - pruneopts = "NUT" - revision = "a3b1354551a26449fbe05f5d855937f6e7acbd71" - -[[projects]] - branch = "master" - digest = "1:35a271df55b343e440407daac25d877269e3bb2f60d2031bcc339bcbe6c0f9b9" - name = "github.com/facebookgo/stats" - packages = ["."] - pruneopts = "NUT" - revision = "1b76add642e42c6ffba7211ad7b3939ce654526e" - -[[projects]] - branch = "master" - digest = "1:ccee1c7954f7296e324a0832b7a4a0a38ea7e51145375fd837283652366c3653" - name = "github.com/glycerine/go-unsnap-stream" - packages = ["."] - pruneopts = "NUT" - revision = "9f0cb55181dd3a0a4c168d3dbc72d4aca4853126" - -[[projects]] - branch = "master" - digest = "1:1961e20504ac246a7eacff00a56ce75cd60be05ea38e04381663593ba5879f58" - name = "github.com/go-macaron/bindata" - packages = ["."] - pruneopts = "NUT" - revision = "85786f57eee3e5544a9cc24fa2afe425b97a8652" - -[[projects]] - digest = "1:628de1525ac764bbe390376679e1ee0ea538429c207926eadf66bdeccda1bf89" - name = "github.com/go-macaron/binding" - packages = ["."] - pruneopts = "NUT" - revision = "9440f336b443056c90d7d448a0a55ad8c7599880" - -[[projects]] - branch = "master" - digest = "1:2440f13a7c7b8a7620bf71504c41a5efb6e04a01249d4eba8b9ce00d2575e793" - name = "github.com/go-macaron/cache" - packages = [ - ".", - "memcache", - "redis", - ] - pruneopts = "NUT" - revision = "56173531277692bc2925924d51fda1cd0a6b8178" - -[[projects]] - digest = "1:221be3922b1be8fe9405a73fd030efe0585baaa41fe9828768ac245c6ea53a83" - name = "github.com/go-macaron/captcha" - packages = ["."] - pruneopts = "NUT" - revision = "8aa5919789ab301e865595eb4b1114d6b9847deb" - -[[projects]] - branch = "master" - digest = "1:7ae1d1b3a156d71413b3a35ef6cf2b1fd6f91e6db0b6f1e8a5f69b47a46795d9" - name = "github.com/go-macaron/csrf" - packages = ["."] - pruneopts = "NUT" - revision = "503617c6b37257a55dff6293ec28556506c3a9a8" - -[[projects]] - branch = "master" - digest = "1:d09d3c94e1bd444464c221be961ba4005e119308f1bcd57aa5f49046fb6affd2" - name = "github.com/go-macaron/i18n" - packages = ["."] - pruneopts = "NUT" - revision = "ef57533c3b0fc2d8581deda14937e52f11a203ab" - -[[projects]] - branch = "master" - digest = "1:fb8711b648d1ff03104fc1d9593a13cb1d5120be7ba2b01641c14ccae286a9e3" - name = "github.com/go-macaron/inject" - packages = ["."] - pruneopts = "NUT" - revision = "d8a0b8677191f4380287cfebd08e462217bac7ad" - -[[projects]] - branch = "master" - digest = "1:a26b7b56aece087165b8db87afb05db8495252449553ca20d15f5a24202f36bc" - name = "github.com/go-macaron/session" - packages = [ - ".", - "couchbase", - "memcache", - "mysql", - "nodb", - "postgres", - "redis", - ] - pruneopts = "NUT" - revision = "0a0a789bf1934e55fde19629869caa015a40c525" - -[[projects]] - digest = "1:758d2371fcdee6d02565901b348729053c636055e67ef6e17aa466c7ff6cc57c" - name = "github.com/go-macaron/toolbox" - packages = ["."] - pruneopts = "NUT" - revision = "a77f45a7ce909c0ff14b28279fa1a2b674acb70f" - -[[projects]] - digest = "1:dce58f88343bd78f4d32dd9601aab4fa5d9994fd2cafa185c51bbd858851cdf9" - name = "github.com/go-sql-driver/mysql" - packages = ["."] - pruneopts = "NUT" - revision = "c45f530f8e7fe40f4687eaa50d0c8c5f1b66f9e0" - -[[projects]] - digest = "1:06d21295033f211588d0ad7ff391cc1b27e72b60cb6d4b7db0d70cffae4cf228" - name = "github.com/go-xorm/builder" - packages = ["."] - pruneopts = "NUT" - revision = "03eb88feccce3e477c318ce7f6f1b386544ab20b" - version = "v0.3.3" - -[[projects]] - digest = "1:c910feae32bcc3cbf068c7263424d9f198da931c0cad909179621835e6f87cb8" - name = "github.com/go-xorm/core" - packages = ["."] - pruneopts = "NUT" - revision = "c10e21e7e1cec20e09398f2dfae385e58c8df555" - version = "v0.6.0" - -[[projects]] - digest = "1:f3015325cb2a17a6ff838358574921a343a0295059b7eb5bec07187131befc0b" - name = "github.com/go-xorm/xorm" - packages = ["."] - pruneopts = "NUT" - revision = "a6300f2a45e05a8f75f00a1d6188049fe7851915" - -[[projects]] - branch = "master" - digest = "1:5fdcd55bad5c103674364f4fdb1ad2541186d063300ab24a8f2bb1b31ae07bac" - name = "github.com/gogits/chardet" - packages = ["."] - pruneopts = "NUT" - revision = "2404f777256163ea3eadb273dada5dcb037993c0" - -[[projects]] - digest = "1:ea030ad2f50b1ced1944914dd80c72e9ebd839fb564c7b8859e7a5d626c61c51" - name = "github.com/gogits/cron" - packages = ["."] - pruneopts = "NUT" - revision = "7f3990acf1833faa5ebd0e86f0a4c72a4b5eba3c" - -[[projects]] - digest = "1:97df918963298c287643883209a2c3f642e6593379f97ab400c2a2e219ab647d" - name = "github.com/golang/protobuf" - packages = ["proto"] - pruneopts = "NUT" - revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" - version = "v1.2.0" - -[[projects]] - digest = "1:60e25fc5f5cfd7783f985ca99b4383e848981dddf0be584db7d809be20848e25" - name = "github.com/golang/snappy" - packages = ["."] - pruneopts = "NUT" - revision = "5f1c01d9f64b941dd9582c638279d046eda6ca31" - -[[projects]] - digest = "1:c01767916c59f084bb7c41a7d5877c0f3099b1595cfa066e84ec6ad6b084dd89" - name = "github.com/gorilla/context" - packages = ["."] - pruneopts = "NUT" - revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" - version = "v1.1.1" - -[[projects]] - digest = "1:9ad9280c98033812aec525d43d4e8137021642dc942bf271b4710f9ac93d0d0b" - name = "github.com/gorilla/mux" - packages = ["."] - pruneopts = "NUT" - revision = "757bef944d0f21880861c2dd9c871ca543023cba" - -[[projects]] - digest = "1:0faa8131e5822f3420f82426667a29c5c425c3cb7e0fcf0c5d1c718d6e6ba19b" - name = "github.com/gorilla/securecookie" - packages = ["."] - pruneopts = "NUT" - revision = "e59506cc896acb7f7bf732d4fdf5e25f7ccd8983" - version = "v1.1.1" - -[[projects]] - digest = "1:ee5531f1e32c0082a6da68a605bc60284711d99b15d38dfba335a1ec52a58c20" - name = "github.com/gorilla/sessions" - packages = ["."] - pruneopts = "NUT" - revision = "ca9ada44574153444b00d3fd9c8559e4cc95f896" - version = "v1.1" - -[[projects]] - digest = "1:18231f2a4af6633fbcd94baab40320d16e826a7f732094ba3420ab547206949b" - name = "github.com/issue9/identicon" - packages = ["."] - pruneopts = "NUT" - revision = "d36b54562f4cf70c83653e13dc95c220c79ef521" - -[[projects]] - digest = "1:d2d4f736f81c5312e2b885798f8a33f9819c6217664404d5b9a4088fcd606df4" - name = "github.com/jaytaylor/html2text" - packages = ["."] - pruneopts = "NUT" - revision = "8fb95d837f7d6db1913fecfd7bcc5333e6499596" - -[[projects]] - branch = "master" - digest = "1:62fe3a7ea2050ecbd753a71889026f83d73329337ada66325cbafd5dea5f713d" - name = "github.com/jbenet/go-context" - packages = ["io"] - pruneopts = "NUT" - revision = "d14ea06fba99483203c19d92cfcd13ebe73135f4" - -[[projects]] - digest = "1:6342cf70eaae592f7b8e2552037f2a9d4d16fa321c6e36f09c3bc450add2de19" - name = "github.com/kballard/go-shellquote" - packages = ["."] - pruneopts = "NUT" - revision = "cd60e84ee657ff3dc51de0b4f55dd299a3e136f2" - -[[projects]] - digest = "1:29e44e9481a689be0093a0033299b95741d394a97b28e0273c21afe697873a22" - name = "github.com/kevinburke/ssh_config" - packages = ["."] - pruneopts = "NUT" - revision = "81db2a75821ed34e682567d48be488a1c3121088" - version = "0.5" - -[[projects]] - digest = "1:b32126992771fddadf6a778fe7ab29150665ed78f31ce4eb550a9db3bc0e650c" - name = "github.com/keybase/go-crypto" - packages = [ - "brainpool", - "cast5", - "curve25519", - "ed25519", - "ed25519/internal/edwards25519", - "openpgp", - "openpgp/armor", - "openpgp/ecdh", - "openpgp/elgamal", - "openpgp/errors", - "openpgp/packet", - "openpgp/s2k", - "rsa", - ] - pruneopts = "NUT" - revision = "00ac4db533f63ef97576cbc7b07939ff7daf7329" - -[[projects]] - digest = "1:c5e37ea5ada80299e6a8e7ebc1a47999c2c8a53eac3a455168adcdcdc78dc93a" - name = "github.com/klauspost/compress" - packages = [ - "flate", - "gzip", - ] - pruneopts = "NUT" - revision = "8df558b6cb6f9b445f9586446cfe7223e7d8bd6b" - version = "v1.1" - -[[projects]] - digest = "1:6a2949d9a141c72cfaa5b55c65794d9b1179878fccdcae735ab62be27bf9cf34" - name = "github.com/klauspost/cpuid" - packages = ["."] - pruneopts = "NUT" - revision = "09cded8978dc9e80714c4d85b0322337b0a1e5e0" - version = "v1.0" - -[[projects]] - digest = "1:b95da1293525625ef6f07be79d537b9bf2ecd7901efcf9a92193edafbd55b9ef" - name = "github.com/klauspost/crc32" - packages = ["."] - pruneopts = "NUT" - revision = "cb6bfca970f6908083f26f39a79009d608efd5cd" - version = "v1.1" - -[[projects]] - digest = "1:38fc7fe0f78eaecdf1ab39a60ba49df85405597103f38d07f2ac560e7e4c8443" - name = "github.com/lafriks/xormstore" - packages = [ - ".", - "util", - ] - pruneopts = "NUT" - revision = "9cab149ea91875cf056211bd6ef82379fce9cb67" - version = "v1.0.0" - -[[projects]] - digest = "1:f1105223bc7ff6a3f3074cf6cccc6c8362ff23db1e7d8505dda01fc4b79b8005" - name = "github.com/lib/pq" - packages = [ - ".", - "oid", - ] - pruneopts = "NUT" - revision = "456514e2defec52e0cd37f90ccf17ec8b28295e2" - -[[projects]] - branch = "master" - digest = "1:6e81c70f78cdc298ea6f19fa9bdba95aacd13a0e0ddb7e118046113997d4dafb" - name = "github.com/lunny/dingtalk_webhook" - packages = ["."] - pruneopts = "NUT" - revision = "e3534c89ef969912856dfa39e56b09e58c5f5daf" - -[[projects]] - branch = "master" - digest = "1:3ea59a5ada4bbac04da58e6177ca63da8c377a3143b48fca584408bf415fdafb" - name = "github.com/lunny/levelqueue" - packages = ["."] - pruneopts = "NUT" - revision = "02b525a4418e684a7786215296984e364746806f" - -[[projects]] - digest = "1:1e6a29ed1f189354030e3371f63ec58aacbc2bf232fd104c6e0d41174ac5af48" - name = "github.com/lunny/log" - packages = ["."] - pruneopts = "NUT" - revision = "7887c61bf0de75586961948b286be6f7d05d9f58" - version = "v0.1" - -[[projects]] - branch = "master" - digest = "1:683d835728cb95d176d423b522420eb5e4ec859b276bca18466476b82b3ebc4c" - name = "github.com/lunny/nodb" - packages = [ - ".", - "config", - "store", - "store/driver", - "store/goleveldb", - ] - pruneopts = "NUT" - revision = "fc1ef06ad4af0da31cdb87e3fa5ec084c67e6597" - -[[projects]] - digest = "1:aa7dcd6a0db70d514821f8739d0a22e7df33b499d8d399cf15b2858d44f8319e" - name = "github.com/markbates/goth" - packages = [ - ".", - "gothic", - "providers/bitbucket", - "providers/discord", - "providers/dropbox", - "providers/facebook", - "providers/github", - "providers/gitlab", - "providers/gplus", - "providers/openidConnect", - "providers/twitter", - ] - pruneopts = "NUT" - revision = "157987f620ff2fc5e1f6a1427a3685219fbf6ff4" - version = "v1.49.0" - -[[projects]] - digest = "1:c9724c929d27a14475a45b17a267dbc60671c0bc2c5c05ed21f011f7b5bc9fb5" - name = "github.com/mattn/go-sqlite3" - packages = ["."] - pruneopts = "NUT" - revision = "c7c4067b79cc51e6dfdcef5c702e74b1e0fa7c75" - -[[projects]] - digest = "1:5985ef4caf91ece5d54817c11ea25f182697534f8ae6521eadcd628c142ac4b6" - name = "github.com/matttproud/golang_protobuf_extensions" - packages = ["pbutil"] - pruneopts = "NUT" - revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" - version = "v1.0.1" - -[[projects]] - branch = "master" - digest = "1:1ed0f3c066eb9d1c2ff7a864a6fa595c70b9b49049cc46af6a6f7ff0e4655321" - name = "github.com/mcuadros/go-version" - packages = ["."] - pruneopts = "NUT" - revision = "88e56e02bea1c203c99222c365fa52a69996ccac" - -[[projects]] - digest = "1:f2111ff3f139dacf8b2177e32f296ad20df85d6ec0ee0e2e348f0fcb21186c14" - name = "github.com/microcosm-cc/bluemonday" - packages = ["."] - pruneopts = "NUT" - revision = "f77f16ffc87a6a58814e64ae72d55f9c41374e6d" - -[[projects]] - digest = "1:a4df73029d2c42fabcb6b41e327d2f87e685284ec03edf76921c267d9cfc9c23" - name = "github.com/mitchellh/go-homedir" - packages = ["."] - pruneopts = "NUT" - revision = "ae18d6b8b3205b561c79e8e5f69bff09736185f4" - version = "v1.0.0" - -[[projects]] - digest = "1:c7dc71a7e144df03332152d730f9c5ae22cf1cfd55454cb001ba8ffcb78aa7f0" - name = "github.com/mrjones/oauth" - packages = ["."] - pruneopts = "NUT" - revision = "3f67d9c274355678b2f9844b08d643e2f9213340" - -[[projects]] - branch = "master" - digest = "1:874d20d479aa479b2ed0200ac565e809d8ff849f672a04e7a21536069eba1cdd" - name = "github.com/mschoch/smat" - packages = ["."] - pruneopts = "NUT" - revision = "90eadee771aeab36e8bf796039b8c261bebebe4f" - -[[projects]] - digest = "1:15bc31ae39f989dda613930c1de860aced7b922502f8d9d861998fc195b7937c" - name = "github.com/msteinert/pam" - packages = ["."] - pruneopts = "NUT" - revision = "02ccfbfaf0cc627aa3aec8ef7ed5cfeec5b43f63" - -[[projects]] - digest = "1:63953ffb90bbc880c612d576fcfd973a5904277d25ec9e2d8d5719bf67969662" - name = "github.com/mvdan/xurls" - packages = ["."] - pruneopts = "NUT" - revision = "e52e821cbfe8fe163ff6f8628ab5869b11fc05af" - version = "v2.0.0" - -[[projects]] - digest = "1:2be1d891535ce3d6d2a3db9087f07415e909744e9eff1a30f8f0b2519df60ae6" - name = "github.com/nfnt/resize" - packages = ["."] - pruneopts = "NUT" - revision = "891127d8d1b52734debe1b3c3d7e747502b6c366" - -[[projects]] - digest = "1:cf254277d898b713195cc6b4a3fac8bf738b9f1121625df27843b52b267eec6c" - name = "github.com/pelletier/go-buffruneio" - packages = ["."] - pruneopts = "NUT" - revision = "c37440a7cf42ac63b919c752ca73a85067e05992" - version = "v0.2.0" - -[[projects]] - digest = "1:44c66ad69563dbe3f8e76d7d6cad21a03626e53f1875b5ab163ded419e01ca7a" - name = "github.com/philhofer/fwd" - packages = ["."] - pruneopts = "NUT" - revision = "bb6d471dc95d4fe11e432687f8b70ff496cf3136" - version = "v1.0.0" - -[[projects]] - digest = "1:14715f705ff5dfe0ffd6571d7d201dd8e921030f8070321a79380d8ca4ec1a24" - name = "github.com/pkg/errors" - packages = ["."] - pruneopts = "NUT" - revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4" - version = "v0.8.1" - -[[projects]] - digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" - name = "github.com/pmezard/go-difflib" - packages = ["difflib"] - pruneopts = "NUT" - revision = "792786c7400a136282c1664665ae0a8db921c6c2" - version = "v1.0.0" - -[[projects]] - digest = "1:aabb118251a9ee8ddab44c405f2391852a82dcf33358cda25ea5748561411ffc" - name = "github.com/pquerna/otp" - packages = [ - ".", - "hotp", - "totp", - ] - pruneopts = "NUT" - revision = "54653902c20e47f3417541d35435cb6d6162e28a" - -[[projects]] - digest = "1:aa2da1df3327c3a338bb42f978407c07de74cd0a5bef35e9411881dffd444214" - name = "github.com/prometheus/client_golang" - packages = [ - "prometheus", - "prometheus/internal", - "prometheus/promhttp", - ] - pruneopts = "NUT" - revision = "1cafe34db7fdec6022e17e00e1c1ea501022f3e4" - version = "v0.9.0" - -[[projects]] - branch = "master" - digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" - name = "github.com/prometheus/client_model" - packages = ["go"] - pruneopts = "NUT" - revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f" - -[[projects]] - branch = "master" - digest = "1:06375f3b602de9c99fa99b8484f0e949fd5273e6e9c6592b5a0dd4cd9085f3ea" - name = "github.com/prometheus/common" - packages = [ - "expfmt", - "internal/bitbucket.org/ww/goautoneg", - "model", - ] - pruneopts = "NUT" - revision = "7e9e6cabbd393fc208072eedef99188d0ce788b6" - -[[projects]] - branch = "master" - digest = "1:102dea0c03a915acfc634b7c67f2662012b5483b56d9025e33f5188e112759b6" - name = "github.com/prometheus/procfs" - packages = [ - ".", - "internal/util", - "nfs", - "xfs", - ] - pruneopts = "NUT" - revision = "185b4288413d2a0dd0806f78c90dde719829e5ae" - -[[projects]] - branch = "master" - digest = "1:5be01c22bc1040e2f6ce4755d51a0ac9cef823a9f2004fb1f9896a414ef519e6" - name = "github.com/russross/blackfriday" - packages = ["."] - pruneopts = "NUT" - revision = "11635eb403ff09dbc3a6b5a007ab5ab09151c229" - -[[projects]] - digest = "1:54f275b550b8a8a20bc91e2067ed740600b69dae9dcf9cdfe905bac1b9cfd1d0" - name = "github.com/satori/go.uuid" - packages = ["."] - pruneopts = "NUT" - revision = "b061729afc07e77a8aa4fad0a2fd840958f1942a" - -[[projects]] - digest = "1:3e0777ad56c86a93cf22459acca84d5c3c8a86b163362074dcb7b33c01aba82b" - name = "github.com/sergi/go-diff" - packages = ["diffmatchpatch"] - pruneopts = "NUT" - revision = "552b4e9bbdca9e5adafd95ee98c822fdd11b330b" - -[[projects]] - digest = "1:400359f0b394fb168f4aee9621d42cc005810c6e462009d5fc76055d5e96dcf3" - name = "github.com/shurcooL/sanitized_anchor_name" - packages = ["."] - pruneopts = "NUT" - revision = "1dba4b3954bc059efc3991ec364f9f9a35f597d2" - -[[projects]] - branch = "master" - digest = "1:dbda803f21e60c38de7d9f884390f2ebbe234ce0c3d139b65bbb36b03a99d266" - name = "github.com/siddontang/go-snappy" - packages = ["snappy"] - pruneopts = "NUT" - revision = "d8f7bb82a96d89c1254e5a6c967134e1433c9ee2" - -[[projects]] - digest = "1:89fd77d603a74a6540d60067debad9397865bf040955d907362c95d364baeba6" - name = "github.com/src-d/gcfg" - packages = [ - ".", - "scanner", - "token", - "types", - ] - pruneopts = "NUT" - revision = "1ac3a1ac202429a54835fe8408a92880156b489d" - version = "v1.4.0" - -[[projects]] - branch = "master" - digest = "1:69177343ca227319b4580441a67d9d889e9ac7fcbfb89fbaa36d3283e6ab0139" - name = "github.com/steveyen/gtreap" - packages = ["."] - pruneopts = "NUT" - revision = "0abe01ef9be25c4aedc174758ec2d917314d6d70" - -[[projects]] - digest = "1:0d3d375df794ab11a192668f4eacdb116ccd99aa574fe357185a2d463e07f2fb" - name = "github.com/stretchr/testify" - packages = [ - "assert", - "require", - ] - pruneopts = "NUT" - revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" - version = "v1.2.1" - -[[projects]] - branch = "master" - digest = "1:685fdfea42d825ebd39ee0994354b46c374cf2c2b2d97a41a8dee1807c6a9b62" - name = "github.com/syndtr/goleveldb" - packages = [ - "leveldb", - "leveldb/cache", - "leveldb/comparer", - "leveldb/errors", - "leveldb/filter", - "leveldb/iterator", - "leveldb/journal", - "leveldb/memdb", - "leveldb/opt", - "leveldb/storage", - "leveldb/table", - "leveldb/util", - ] - pruneopts = "NUT" - revision = "2f17a3356c6616cbfc4ae4c38147dc062a68fb0e" - -[[projects]] - branch = "master" - digest = "1:3cb6dfe7cdece5716b1c3c3c0b5faf7fce2e83e2758e2baad2e9986d101980b8" - name = "github.com/tinylib/msgp" - packages = ["msgp"] - pruneopts = "NUT" - revision = "c8cf64dff2009d53fa8f8a16df54d1cdfc64c4a7" - -[[projects]] - branch = "master" - digest = "1:aa8ce6454cff67af88a195977ba6489df6c55802e1199cbe24af9febec8c1586" - name = "github.com/tstranex/u2f" - packages = ["."] - pruneopts = "NUT" - revision = "d21a03e0b1d9fc1df59ff54e7a513655c1748b0c" - -[[projects]] - digest = "1:d9f3ecc1fb41eaf8af777f844a2c0eb9b7ff743224981e5af4ade023210cf6e5" - name = "github.com/urfave/cli" - packages = ["."] - pruneopts = "NUT" - revision = "d86a009f5e13f83df65d0d6cee9a2e3f1445f0da" - -[[projects]] - branch = "master" - digest = "1:1d786f876a94d808e0ee5052e1f65ab284dc7483a7517d76d25baa8099429ed5" - name = "github.com/willf/bitset" - packages = ["."] - pruneopts = "NUT" - revision = "8ce1146b8621c95164efd9c8b1124cfa9b8afb4e" - -[[projects]] - digest = "1:3148cb3478c26a92b4c1a18abb9428234b281e278af6267840721a24b6cbc6a3" - name = "github.com/xanzy/ssh-agent" - packages = ["."] - pruneopts = "NUT" - revision = "640f0ab560aeb89d523bb6ac322b1244d5c3796c" - version = "v0.2.0" - -[[projects]] - digest = "1:27d050258a4b19ca3b7a1bf26f4a04c5c66bbf0670b346ee509ebb0ad82257a6" - name = "github.com/yohcop/openid-go" - packages = ["."] - pruneopts = "NUT" - revision = "2c050d2dae5345c417db301f11fda6fbf5ad0f0a" - -[[projects]] - digest = "1:590035a7bbea1c037c2e6d51f81ee09857480c3c21f1f77397d9802f10507c06" - name = "golang.org/x/crypto" - packages = [ - "acme", - "acme/autocert", - "bcrypt", - "blowfish", - "cast5", - "curve25519", - "ed25519", - "ed25519/internal/edwards25519", - "internal/chacha20", - "md4", - "openpgp", - "openpgp/armor", - "openpgp/elgamal", - "openpgp/errors", - "openpgp/packet", - "openpgp/s2k", - "pbkdf2", - "poly1305", - "ssh", - "ssh/agent", - "ssh/knownhosts", - ] - pruneopts = "NUT" - revision = "12dd70caea0268ac0d6c2707d0611ef601e7c64e" - -[[projects]] - branch = "master" - digest = "1:d0a0bdd2b64d981aa4e6a1ade90431d042cd7fa31b584e33d45e62cbfec43380" - name = "golang.org/x/net" - packages = [ - "context", - "context/ctxhttp", - "html", - "html/atom", - "html/charset", - ] - pruneopts = "NUT" - revision = "9b4f9f5ad5197c79fd623a3638e70d8b26cef344" - -[[projects]] - branch = "master" - digest = "1:274a6321a5a9f185eeb3fab5d7d8397e0e9f57737490d749f562c7e205ffbc2e" - name = "golang.org/x/oauth2" - packages = [ - ".", - "internal", - ] - pruneopts = "NUT" - revision = "c453e0c757598fd055e170a3a359263c91e13153" - -[[projects]] - digest = "1:9f303486d623f840492bfeb48eb906a94e9d3fe638a761639b72ce64bf7bfcc3" - name = "golang.org/x/sync" - packages = ["syncmap"] - pruneopts = "NUT" - revision = "5a06fca2c336a4b2b2fcb45702e8c47621b2aa2c" - -[[projects]] - branch = "master" - digest = "1:030ca7763285f6cdec5684d7417faa2810d10a508b0220b1487cc876b5c00c35" - name = "golang.org/x/sys" - packages = [ - "unix", - "windows", - "windows/svc", - ] - pruneopts = "NUT" - revision = "2772b66316d2c587efeb188dcd5ebc6987656e84" - -[[projects]] - digest = "1:d2463fd72ee2636c3d9bbdb98fa4996a118f210ae3e5eaf62d281855bc0b4a83" - name = "golang.org/x/text" - packages = [ - "encoding", - "encoding/charmap", - "encoding/htmlindex", - "encoding/internal", - "encoding/internal/identifier", - "encoding/japanese", - "encoding/korean", - "encoding/simplifiedchinese", - "encoding/traditionalchinese", - "encoding/unicode", - "internal/gen", - "internal/tag", - "internal/triegen", - "internal/ucd", - "internal/utf8internal", - "language", - "runes", - "transform", - "unicode/cldr", - "unicode/norm", - ] - pruneopts = "NUT" - revision = "2bf8f2a19ec09c670e931282edfe6567f6be21c9" - -[[projects]] - branch = "v3" - digest = "1:1244a9b3856f70d5ffb74bbfd780fc9d47f93f2049fa265c6fb602878f507bf8" - name = "gopkg.in/alexcesaro/quotedprintable.v3" - packages = ["."] - pruneopts = "NUT" - revision = "2caba252f4dc53eaf6b553000885530023f54623" - -[[projects]] - digest = "1:9c577b4736db46066c2a41aef5736316fc5e0c8d1b97e8917f4b6157b530ee53" - name = "gopkg.in/asn1-ber.v1" - packages = ["."] - pruneopts = "NUT" - revision = "4e86f4367175e39f69d9358a5f17b4dda270378d" - version = "v1.1" - -[[projects]] - digest = "1:24bfc2e8bf971485cb5ba0f0e5b08a1b806cca5828134df76b32d1ea50f2ab49" - name = "gopkg.in/bufio.v1" - packages = ["."] - pruneopts = "NUT" - revision = "567b2bfa514e796916c4747494d6ff5132a1dfce" - version = "v1" - -[[projects]] - digest = "1:9146e4250cb4359ac2f7a1ac3766dbcc52b3d8414ab9ac1af195ce6fba6c234f" - name = "gopkg.in/editorconfig/editorconfig-core-go.v1" - packages = ["."] - pruneopts = "NUT" - revision = "a872f05c2e34b37b567401384d202aff11ba06d4" - version = "v1.2.0" - -[[projects]] - branch = "v2" - digest = "1:8db3ee13f824cd299f10af1dead41de8bce6b53a704998976e58c5b9274ab4b6" - name = "gopkg.in/gomail.v2" - packages = ["."] - pruneopts = "NUT" - revision = "81ebce5c23dfd25c6c67194b37d3dd3f338c98b1" - -[[projects]] - digest = "1:cbecb8d0e314f34d1bc65a86cb433e33ad8e32c2cb6ae313a4f2e52806ddd984" - name = "gopkg.in/ini.v1" - packages = ["."] - pruneopts = "NUT" - revision = "7e7da451323b6766da368f8a1e8ec9a88a16b4a0" - version = "v1.31.1" - -[[projects]] - digest = "1:8a502dedecf5b6d56e36f0d0e6196392baf616634af2c23108b6e8bb89ec57fc" - name = "gopkg.in/ldap.v3" - packages = ["."] - pruneopts = "NUT" - revision = "214f299a0ecb2a6c6f6d2b0f13977032b207dc58" - version = "v3.0.1" - -[[projects]] - digest = "1:de2e7294c9bd0b7d07ada8e98ad02cbbaabacff90eedebe7454ebdbab50d0d19" - name = "gopkg.in/macaron.v1" - packages = ["."] - pruneopts = "NUT" - revision = "dfcb80ca86e8534962c62812efd93209c7e600e7" - version = "v1.3.2" - -[[projects]] - digest = "1:00126f697efdcab42f07c89ac8bf0095fb2328aef6464e070055154088cea859" - name = "gopkg.in/redis.v2" - packages = ["."] - pruneopts = "NUT" - revision = "e6179049628164864e6e84e973cfb56335748dea" - version = "v2.3.2" - -[[projects]] - digest = "1:1cf1388ec8c73b7ecc711d9f279ab631ea0a6964d1ccc32809a6be90c33fa2a0" - name = "gopkg.in/src-d/go-billy.v4" - packages = [ - ".", - "helper/chroot", - "helper/polyfill", - "osfs", - "util", - ] - pruneopts = "NUT" - revision = "982626487c60a5252e7d0b695ca23fb0fa2fd670" - version = "v4.3.0" - -[[projects]] - digest = "1:8a0efb153cc5b7e0e129d716834217be483e2b326e72f3dcca8b03cd3207e9e4" - name = "gopkg.in/src-d/go-git.v4" - packages = [ - ".", - "config", - "internal/revision", - "plumbing", - "plumbing/cache", - "plumbing/filemode", - "plumbing/format/config", - "plumbing/format/diff", - "plumbing/format/gitignore", - "plumbing/format/idxfile", - "plumbing/format/index", - "plumbing/format/objfile", - "plumbing/format/packfile", - "plumbing/format/pktline", - "plumbing/object", - "plumbing/protocol/packp", - "plumbing/protocol/packp/capability", - "plumbing/protocol/packp/sideband", - "plumbing/revlist", - "plumbing/storer", - "plumbing/transport", - "plumbing/transport/client", - "plumbing/transport/file", - "plumbing/transport/git", - "plumbing/transport/http", - "plumbing/transport/internal/common", - "plumbing/transport/server", - "plumbing/transport/ssh", - "storage", - "storage/filesystem", - "storage/filesystem/dotgit", - "storage/memory", - "utils/binary", - "utils/diff", - "utils/ioutil", - "utils/merkletrie", - "utils/merkletrie/filesystem", - "utils/merkletrie/index", - "utils/merkletrie/internal/frame", - "utils/merkletrie/noder", - ] - pruneopts = "NUT" - revision = "f62cd8e3495579a8323455fa0c4e6c44bb0d5e09" - version = "v4.8.0" - -[[projects]] - digest = "1:9c541fc507676a69ea8aaed1af53278a5241d26ce0f192c993fec2ac5b78f795" - name = "gopkg.in/testfixtures.v2" - packages = ["."] - pruneopts = "NUT" - revision = "fa3fb89109b0b31957a5430cef3e93e535de362b" - version = "v2.5.0" - -[[projects]] - digest = "1:b233ad4ec87ac916e7bf5e678e98a2cb9e8b52f6de6ad3e11834fc7a71b8e3bf" - name = "gopkg.in/warnings.v0" - packages = ["."] - pruneopts = "NUT" - revision = "ec4a0fea49c7b46c2aeb0b51aac55779c607e52b" - version = "v0.1.2" - -[[projects]] - digest = "1:ad6f94355d292690137613735965bd3688844880fdab90eccf66321910344942" - name = "gopkg.in/yaml.v2" - packages = ["."] - pruneopts = "NUT" - revision = "a5b47d31c556af34a302ce5d659e6fea44d90de0" - -[[projects]] - digest = "1:5972c0a5308529a35d87dd2dbba827625df90e6c89b0f496644fc43ea761bcf2" - name = "strk.kbt.io/projects/go/libravatar" - packages = ["."] - pruneopts = "NUT" - revision = "5eed7bff870ae19ef51c5773dbc8f3e9fcbd0982" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "code.gitea.io/sdk/gitea", - "github.com/PuerkitoBio/goquery", - "github.com/Unknwon/cae/zip", - "github.com/Unknwon/com", - "github.com/Unknwon/i18n", - "github.com/Unknwon/paginater", - "github.com/blevesearch/bleve", - "github.com/blevesearch/bleve/analysis/analyzer/custom", - "github.com/blevesearch/bleve/analysis/token/camelcase", - "github.com/blevesearch/bleve/analysis/token/lowercase", - "github.com/blevesearch/bleve/analysis/token/unicodenorm", - "github.com/blevesearch/bleve/analysis/token/unique", - "github.com/blevesearch/bleve/analysis/tokenizer/unicode", - "github.com/blevesearch/bleve/index/upsidedown", - "github.com/blevesearch/bleve/mapping", - "github.com/blevesearch/bleve/search/query", - "github.com/chaseadamsio/goorgeous", - "github.com/denisenkom/go-mssqldb", - "github.com/dgrijalva/jwt-go", - "github.com/ethantkoenig/rupture", - "github.com/facebookgo/grace/gracehttp", - "github.com/go-macaron/bindata", - "github.com/go-macaron/binding", - "github.com/go-macaron/cache", - "github.com/go-macaron/cache/memcache", - "github.com/go-macaron/cache/redis", - "github.com/go-macaron/captcha", - "github.com/go-macaron/csrf", - "github.com/go-macaron/i18n", - "github.com/go-macaron/inject", - "github.com/go-macaron/session", - "github.com/go-macaron/session/couchbase", - "github.com/go-macaron/session/memcache", - "github.com/go-macaron/session/mysql", - "github.com/go-macaron/session/nodb", - "github.com/go-macaron/session/postgres", - "github.com/go-macaron/session/redis", - "github.com/go-macaron/toolbox", - "github.com/go-sql-driver/mysql", - "github.com/go-xorm/builder", - "github.com/go-xorm/core", - "github.com/go-xorm/xorm", - "github.com/gogits/chardet", - "github.com/gogits/cron", - "github.com/gorilla/context", - "github.com/issue9/identicon", - "github.com/jaytaylor/html2text", - "github.com/kballard/go-shellquote", - "github.com/keybase/go-crypto/openpgp", - "github.com/keybase/go-crypto/openpgp/armor", - "github.com/keybase/go-crypto/openpgp/packet", - "github.com/klauspost/compress/gzip", - "github.com/lafriks/xormstore", - "github.com/lib/pq", - "github.com/lunny/dingtalk_webhook", - "github.com/lunny/levelqueue", - "github.com/markbates/goth", - "github.com/markbates/goth/gothic", - "github.com/markbates/goth/providers/bitbucket", - "github.com/markbates/goth/providers/discord", - "github.com/markbates/goth/providers/dropbox", - "github.com/markbates/goth/providers/facebook", - "github.com/markbates/goth/providers/github", - "github.com/markbates/goth/providers/gitlab", - "github.com/markbates/goth/providers/gplus", - "github.com/markbates/goth/providers/openidConnect", - "github.com/markbates/goth/providers/twitter", - "github.com/mattn/go-sqlite3", - "github.com/mcuadros/go-version", - "github.com/microcosm-cc/bluemonday", - "github.com/msteinert/pam", - "github.com/mvdan/xurls", - "github.com/nfnt/resize", - "github.com/pquerna/otp", - "github.com/pquerna/otp/totp", - "github.com/prometheus/client_golang/prometheus", - "github.com/prometheus/client_golang/prometheus/promhttp", - "github.com/russross/blackfriday", - "github.com/satori/go.uuid", - "github.com/sergi/go-diff/diffmatchpatch", - "github.com/stretchr/testify/assert", - "github.com/stretchr/testify/require", - "github.com/tstranex/u2f", - "github.com/urfave/cli", - "github.com/yohcop/openid-go", - "golang.org/x/crypto/acme/autocert", - "golang.org/x/crypto/bcrypt", - "golang.org/x/crypto/pbkdf2", - "golang.org/x/crypto/ssh", - "golang.org/x/net/html", - "golang.org/x/net/html/atom", - "golang.org/x/net/html/charset", - "golang.org/x/sync/syncmap", - "golang.org/x/sys/windows/svc", - "golang.org/x/text/transform", - "gopkg.in/editorconfig/editorconfig-core-go.v1", - "gopkg.in/gomail.v2", - "gopkg.in/ini.v1", - "gopkg.in/ldap.v3", - "gopkg.in/macaron.v1", - "gopkg.in/src-d/go-git.v4", - "gopkg.in/src-d/go-git.v4/config", - "gopkg.in/src-d/go-git.v4/plumbing", - "gopkg.in/testfixtures.v2", - "strk.kbt.io/projects/go/libravatar", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml deleted file mode 100644 index f5dcb46869..0000000000 --- a/Gopkg.toml +++ /dev/null @@ -1,119 +0,0 @@ - -ignored = ["google.golang.org/appengine*"] - -[prune] - go-tests = true - unused-packages = true - non-go = true - -[[constraint]] - branch = "master" - name = "code.gitea.io/git" - -[[constraint]] - branch = "master" - name = "code.gitea.io/sdk" - -[[constraint]] - revision = "05d86ea8f6e30456949f612cf68cf4a27ce8c9c5" - name = "github.com/blevesearch/bleve" - -[[constraint]] - revision = "12dd70caea0268ac0d6c2707d0611ef601e7c64e" - name = "golang.org/x/crypto" - -[[constraint]] - branch = "master" - name = "golang.org/x/sys" - -[[constraint]] - revision = "2bf8f2a19ec09c670e931282edfe6567f6be21c9" - name = "golang.org/x/text" - -[[constraint]] - branch = "master" - name = "golang.org/x/net" - -[[override]] - name = "github.com/go-xorm/xorm" - revision = "a6300f2a45e05a8f75f00a1d6188049fe7851915" - -[[override]] - name = "github.com/go-xorm/builder" - version = "0.3.3" - -[[override]] - name = "github.com/go-sql-driver/mysql" - revision = "c45f530f8e7fe40f4687eaa50d0c8c5f1b66f9e0" - -[[override]] - name = "github.com/mattn/go-sqlite3" - revision = "c7c4067b79cc51e6dfdcef5c702e74b1e0fa7c75" - -[[override]] - name = "github.com/gorilla/mux" - revision = "757bef944d0f21880861c2dd9c871ca543023cba" - -[[constraint]] - name = "github.com/gorilla/context" - version = "1.1.1" - -[[constraint]] - name = "github.com/lafriks/xormstore" - version = "1.0.0" - -[[constraint]] - branch = "master" - name = "github.com/lunny/dingtalk_webhook" - -[[constraint]] - name = "github.com/markbates/goth" - version = "1.47.2" - -[[constraint]] - branch = "master" - name = "github.com/mcuadros/go-version" - -[[constraint]] - branch = "master" - name = "github.com/russross/blackfriday" - -[[constraint]] - branch = "master" - name = "github.com/tstranex/u2f" - -[[constraint]] - name = "gopkg.in/editorconfig/editorconfig-core-go.v1" - version = "1.2.0" - -[[constraint]] - branch = "v2" - name = "gopkg.in/gomail.v2" - -[[constraint]] - name = "gopkg.in/ini.v1" - version = "1.31.1" - -[[constraint]] - name = "gopkg.in/ldap.v3" - version = "3.0.1" - -[[constraint]] - name = "gopkg.in/macaron.v1" - version = "1.2.4" - -[[constraint]] - name = "gopkg.in/testfixtures.v2" - version = "2.0.0" - -[[override]] - branch = "master" - name = "golang.org/x/oauth2" - -[[constraint]] - name = "github.com/prometheus/client_golang" - version = "0.9.0" - -[[constraint]] - name = "github.com/mvdan/xurls" - version = "2.0.0" diff --git a/Makefile b/Makefile index 6affeee38d..4959a75e2d 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ DIST := dist IMPORT := code.gitea.io/gitea +export GO111MODULE=off GO ?= go SED_INPLACE := sed -i @@ -169,7 +170,7 @@ fmt-check: .PHONY: test test: - $(GO) test -tags='sqlite sqlite_unlock_notify' $(PACKAGES) + GO111MODULE=on $(GO) test -mod=vendor -tags='sqlite sqlite_unlock_notify' $(PACKAGES) .PHONY: coverage coverage: @@ -184,10 +185,7 @@ unit-test-coverage: .PHONY: vendor vendor: - @hash dep > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ - $(GO) get -u github.com/golang/dep/cmd/dep; \ - fi - dep ensure -vendor-only + GO111MODULE=on $(GO) mod tidy && GO111MODULE=on $(GO) mod vendor .PHONY: test-vendor test-vendor: vendor @@ -197,7 +195,6 @@ test-vendor: vendor echo "$${diff}"; \ exit 1; \ fi; -#TODO add dep status -missing when implemented .PHONY: test-sqlite test-sqlite: integrations.sqlite.test @@ -284,13 +281,13 @@ integration-test-coverage: integrations.cover.test generate-ini GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql.ini ./integrations.cover.test -test.coverprofile=integration.coverage.out integrations.test: $(SOURCES) - $(GO) test -c code.gitea.io/gitea/integrations -o integrations.test + GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -o integrations.test integrations.sqlite.test: $(SOURCES) - $(GO) test -c code.gitea.io/gitea/integrations -o integrations.sqlite.test -tags 'sqlite sqlite_unlock_notify' + GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -o integrations.sqlite.test -tags 'sqlite sqlite_unlock_notify' integrations.cover.test: $(SOURCES) - $(GO) test -c code.gitea.io/gitea/integrations -coverpkg $(shell echo $(PACKAGES) | tr ' ' ',') -o integrations.cover.test + GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -coverpkg $(shell echo $(PACKAGES) | tr ' ' ',') -o integrations.cover.test .PHONY: migrations.test migrations.test: $(SOURCES) @@ -311,7 +308,7 @@ install: $(wildcard *.go) build: $(EXECUTABLE) $(EXECUTABLE): $(SOURCES) - $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@ + GO111MODULE=on $(GO) build -mod=vendor $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@ .PHONY: release release: release-dirs release-windows release-linux release-darwin release-copy release-compress release-check diff --git a/go.mod b/go.mod new file mode 100644 index 0000000000..9e22ef1858 --- /dev/null +++ b/go.mod @@ -0,0 +1,139 @@ +module code.gitea.io/gitea + +go 1.12 + +require ( + code.gitea.io/sdk v0.0.0-20190321154058-a669487e86e0 + github.com/BurntSushi/toml v0.3.1 // indirect + github.com/PuerkitoBio/goquery v0.0.0-20170324135448-ed7d758e9a34 + github.com/RoaringBitmap/roaring v0.4.7 // indirect + github.com/Unknwon/cae v0.0.0-20160715032808-c6aac99ea2ca + github.com/Unknwon/com v0.0.0-20170819223952-7677a1d7c113 + github.com/Unknwon/i18n v0.0.0-20171114194641-b64d33658966 + github.com/Unknwon/paginater v0.0.0-20151104151617-7748a72e0141 + github.com/andybalholm/cascadia v0.0.0-20161224141413-349dd0209470 // indirect + github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/blevesearch/bleve v0.0.0-20190214220507-05d86ea8f6e3 + github.com/blevesearch/blevex v0.0.0-20180227211930-4b158bb555a3 // indirect + github.com/blevesearch/go-porterstemmer v0.0.0-20141230013033-23a2c8e5cf1f // indirect + github.com/blevesearch/segment v0.0.0-20160105220820-db70c57796cc // indirect + github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26 // indirect + github.com/bradfitz/gomemcache v0.0.0-20160117192205-fb1f79c6b65a // indirect + github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f + github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c // indirect + github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a // indirect + github.com/couchbase/vellum v0.0.0-20190111184608-e91b68ff3efe // indirect + github.com/couchbaselabs/go-couchbase v0.0.0-20190117181324-d904413d884d // indirect + github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d // indirect + github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect + github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 // indirect + github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f + github.com/dgrijalva/jwt-go v0.0.0-20161101193935-9ed569b5d1ac + github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 // indirect + github.com/elazarl/go-bindata-assetfs v0.0.0-20151224045452-57eb5e1fc594 // indirect + github.com/emirpasic/gods v1.12.0 // indirect + github.com/etcd-io/bbolt v1.3.2 // indirect + github.com/ethantkoenig/rupture v0.0.0-20180203182544-0a76f03a811a + github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect + github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 // indirect + github.com/facebookgo/freeport v0.0.0-20150612182905-d4adf43b75b9 // indirect + github.com/facebookgo/grace v0.0.0-20160926231715-5729e484473f + github.com/facebookgo/httpdown v0.0.0-20160323221027-a3b1354551a2 // indirect + github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect + github.com/facebookgo/stats v0.0.0-20151006221625-1b76add642e4 // indirect + github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 // indirect + github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd // indirect + github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e // indirect + github.com/go-macaron/bindata v0.0.0-20161222093048-85786f57eee3 + github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443 + github.com/go-macaron/cache v0.0.0-20151013081102-561735312776 + github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab + github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372 + github.com/go-macaron/i18n v0.0.0-20160612092837-ef57533c3b0f + github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 + github.com/go-macaron/session v0.0.0-20190131233854-0a0a789bf193 + github.com/go-macaron/toolbox v0.0.0-20180818072302-a77f45a7ce90 + github.com/go-sql-driver/mysql v1.4.0 + github.com/go-xorm/builder v0.3.3 + github.com/go-xorm/core v0.6.0 + github.com/go-xorm/xorm v0.0.0-20190116032649-a6300f2a45e0 + github.com/gogits/chardet v0.0.0-20150115103509-2404f7772561 + github.com/gogits/cron v0.0.0-20160810035002-7f3990acf183 + github.com/gogo/protobuf v1.2.1 // indirect + github.com/gorilla/context v1.1.1 + github.com/issue9/assert v1.3.2 // indirect + github.com/issue9/identicon v0.0.0-20160320065130-d36b54562f4c + github.com/jaytaylor/html2text v0.0.0-20160923191438-8fb95d837f7d + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/joho/godotenv v1.3.0 // indirect + github.com/kballard/go-shellquote v0.0.0-20170619183022-cd60e84ee657 + github.com/keybase/go-crypto v0.0.0-20170605145657-00ac4db533f6 + github.com/klauspost/compress v0.0.0-20161025140425-8df558b6cb6f + github.com/klauspost/cpuid v0.0.0-20160302075316-09cded8978dc // indirect + github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6 // indirect + github.com/lafriks/xormstore v1.0.0 + github.com/lib/pq v1.0.0 + github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 + github.com/lunny/levelqueue v0.0.0-20190217115915-02b525a4418e + github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de // indirect + github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af // indirect + github.com/markbates/goth v1.49.0 + github.com/mattn/go-oci8 v0.0.0-20190320171441-14ba190cf52d // indirect + github.com/mattn/go-sqlite3 v1.10.0 + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mcuadros/go-version v0.0.0-20171003094716-88e56e02bea1 + github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a + github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae // indirect + github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc + github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 + github.com/philhofer/fwd v1.0.0 // indirect + github.com/pkg/errors v0.8.1 // indirect + github.com/pquerna/otp v0.0.0-20160912161815-54653902c20e + github.com/prometheus/client_golang v0.9.0 + github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect + github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39 // indirect + github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d // indirect + github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 // indirect + github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff + github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect + github.com/satori/go.uuid v1.2.0 + github.com/sergi/go-diff v1.0.0 + github.com/shurcooL/sanitized_anchor_name v0.0.0-20160918041101-1dba4b3954bc // indirect + github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d // indirect + github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff // indirect + github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2 // indirect + github.com/stretchr/testify v1.2.2 + github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481 // indirect + github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200 // indirect + github.com/tstranex/u2f v1.0.0 + github.com/urfave/cli v0.0.0-20161102131801-d86a009f5e13 + github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 // indirect + github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53 + go.etcd.io/bbolt v1.3.2 // indirect + golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 + golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519 + golang.org/x/oauth2 v0.0.0-20181101160152-c453e0c75759 // indirect + golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f + golang.org/x/sys v0.0.0-20181026144532-2772b66316d2 + golang.org/x/text v0.3.0 + gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect + gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 // indirect + gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e // indirect + gopkg.in/editorconfig/editorconfig-core-go.v1 v1.2.0 + gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df + gopkg.in/ini.v1 v1.31.1 + gopkg.in/ldap.v3 v3.0.2 + gopkg.in/macaron.v1 v1.3.2 + gopkg.in/redis.v2 v2.3.2 // indirect + gopkg.in/src-d/go-billy.v4 v4.3.0 // indirect + gopkg.in/src-d/go-git.v4 v4.8.0 + gopkg.in/testfixtures.v2 v2.5.0 + mvdan.cc/xurls/v2 v2.0.0 + strk.kbt.io/projects/go/libravatar v0.0.0-20160628055650-5eed7bff870a +) + +replace ( + github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f => github.com/denisenkom/go-mssqldb v0.0.0-20161128230840-e32ca5036449 + github.com/go-sql-driver/mysql v1.4.0 => github.com/go-sql-driver/mysql v0.0.0-20181218123637-c45f530f8e7f +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000000..aa9cec3a92 --- /dev/null +++ b/go.sum @@ -0,0 +1,364 @@ +cloud.google.com/go v0.30.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +code.gitea.io/sdk v0.0.0-20190321154058-a669487e86e0 h1:pIKKrTUox+0pGcZwFl19Glw9gKfoeNkA02EqeiSmLjs= +code.gitea.io/sdk v0.0.0-20190321154058-a669487e86e0/go.mod h1:5bZt0dRznpn2JysytQnV0yCru3FwDv9O5G91jo+lDAk= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/PuerkitoBio/goquery v0.0.0-20170324135448-ed7d758e9a34 h1:UsHpWO0Elp6NaWVARdZHjiYwkhrspHVEGsyIKPb9OI8= +github.com/PuerkitoBio/goquery v0.0.0-20170324135448-ed7d758e9a34/go.mod h1:T9ezsOHcCrDCgA8aF1Cqr3sSYbO/xgdy8/R/XiIMAhA= +github.com/RoaringBitmap/roaring v0.4.7 h1:eGUudvFzvF7Kxh7JjYvXfI1f7l22/2duFby7r5+d4oc= +github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w= +github.com/Unknwon/cae v0.0.0-20160715032808-c6aac99ea2ca h1:xU8R31tsvj6TesCBog973+UgI3TXjh/LqN5clki6hcc= +github.com/Unknwon/cae v0.0.0-20160715032808-c6aac99ea2ca/go.mod h1:IRSre9/SEhVuy972TVuJLyaPTS73+8Owhe0Y0l9NXHc= +github.com/Unknwon/com v0.0.0-20170819223952-7677a1d7c113 h1:YwXm6KwmrA5R5yJRhcnpqRUHmBXSKciHuWtK9zP5qKQ= +github.com/Unknwon/com v0.0.0-20170819223952-7677a1d7c113/go.mod h1:KYCjqMOeHpNuTOiFQU6WEcTG7poCJrUs0YgyHNtn1no= +github.com/Unknwon/i18n v0.0.0-20171114194641-b64d33658966 h1:Mp8GNJ/tdTZIEdLdZfykEJaL3mTyEYrSzYNcdoQKpJk= +github.com/Unknwon/i18n v0.0.0-20171114194641-b64d33658966/go.mod h1:SFtfq0zFPsENI7DpE87QM2hcYu5QQ0fRdCgP+P1Hrqo= +github.com/Unknwon/paginater v0.0.0-20151104151617-7748a72e0141 h1:SSvHGK7iMpeypcHjI8UzNMz7zW/K8/dcgqk/82lCYP0= +github.com/Unknwon/paginater v0.0.0-20151104151617-7748a72e0141/go.mod h1:fw0McLecf/G5NFwddCRmDckU6yovtk1YsgWIoepMbYo= +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/andybalholm/cascadia v0.0.0-20161224141413-349dd0209470 h1:4jHLmof+Hba81591gfH5xYA8QXzuvgksxwPNrmjR2BA= +github.com/andybalholm/cascadia v0.0.0-20161224141413-349dd0209470/go.mod h1:3I+3V7B6gTBYfdpYgIG2ymALS9H+5VDKUl3lHH7ToM4= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/blevesearch/bleve v0.0.0-20190214220507-05d86ea8f6e3 h1:vinCy/rcjbtxWnMiw11CbMKcuyNi+y4L4MbZUpk7m4M= +github.com/blevesearch/bleve v0.0.0-20190214220507-05d86ea8f6e3/go.mod h1:Y2lmIkzV6mcNfAnAdOd+ZxHkHchhBfU/xroGIp61wfw= +github.com/blevesearch/blevex v0.0.0-20180227211930-4b158bb555a3 h1:U6vnxZrTfItfiUiYx0lf/LgHjRSfaKK5QHSom3lEbnA= +github.com/blevesearch/blevex v0.0.0-20180227211930-4b158bb555a3/go.mod h1:WH+MU2F4T0VmSdaPX+Wu5GYoZBrYWdOZWSjzvYcDmqQ= +github.com/blevesearch/go-porterstemmer v0.0.0-20141230013033-23a2c8e5cf1f h1:J9ZVHbB2X6JNxbKw/f3Y4E9Xq+Ro+zPiivzgmi3RTvg= +github.com/blevesearch/go-porterstemmer v0.0.0-20141230013033-23a2c8e5cf1f/go.mod h1:haWQqFT3RdOGz7PJuM3or/pWNJS1pKkoZJWCkWu0DVA= +github.com/blevesearch/segment v0.0.0-20160105220820-db70c57796cc h1:7OfDAkuAGx71ruzOIFqCkHqGIsVZU0C7PMw5u1bIrwU= +github.com/blevesearch/segment v0.0.0-20160105220820-db70c57796cc/go.mod h1:IInt5XRvpiGE09KOk9mmCMLjHhydIhNPKPPFLFBB7L8= +github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26 h1:NGpwhs9FOwddM6TptNrq2ycby4s24TcppSe5uG4DA/Q= +github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/bradfitz/gomemcache v0.0.0-20160117192205-fb1f79c6b65a h1:k5TuEkqEYCRs8+66WdOkswWOj+L/YbP5ruainvn94wg= +github.com/bradfitz/gomemcache v0.0.0-20160117192205-fb1f79c6b65a/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60= +github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f h1:REH9VH5ubNR0skLaOxK7TRJeRbE2dDfvaouQo8FsRcA= +github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f/go.mod h1:6QaC0vFoKWYDth94dHFNgRT2YkT5FHdQp/Yx15aAAi0= +github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c h1:K4FIibkr4//ziZKOKmt4RL0YImuTjLLBtwElf+F2lSQ= +github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= +github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a h1:Y5XsLCEhtEI8qbD9RP3Qlv5FXdTDHxZM9UPUnMRgBp8= +github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= +github.com/couchbase/vellum v0.0.0-20190111184608-e91b68ff3efe h1:2o6Y7KMjJNsuMTF8f2H2eTKRhqH7+bQbjr+D+LnhE5M= +github.com/couchbase/vellum v0.0.0-20190111184608-e91b68ff3efe/go.mod h1:prYTC8EgTu3gwbqJihkud9zRXISvyulAplQ6exdCo1g= +github.com/couchbaselabs/go-couchbase v0.0.0-20190117181324-d904413d884d h1:lsBRLJe/ET6DjCaRblGwls80dOcOzhFVNJrO6uaMrMQ= +github.com/couchbaselabs/go-couchbase v0.0.0-20190117181324-d904413d884d/go.mod h1:mby/05p8HE5yHEAKiIH/555NoblMs7PtW6NrYshDruc= +github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d h1:SwD98825d6bdB+pEuTxWOXiSjBrHdOl/UVp75eI7JT8= +github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= +github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso= +github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= +github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 h1:MZRmHqDBd0vxNwenEbKSQqRVT24d3C05ft8kduSwlqM= +github.com/cznic/strutil v0.0.0-20181122101858-275e90344537/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= +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-20161128230840-e32ca5036449 h1:JpA+YMG4JLW8nzLmU05mTiuB0O17xHGxpWolEZ0zDuA= +github.com/denisenkom/go-mssqldb v0.0.0-20161128230840-e32ca5036449/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc= +github.com/dgrijalva/jwt-go v0.0.0-20161101193935-9ed569b5d1ac h1:xrQJVwQCGqDvOO7/0+RyIq5J2M3Q4ZF7Ug/BMQtML1E= +github.com/dgrijalva/jwt-go v0.0.0-20161101193935-9ed569b5d1ac/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 h1:aaQcKT9WumO6JEJcRyTqFVq4XUZiUcKR2/GI31TOcz8= +github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elazarl/go-bindata-assetfs v0.0.0-20151224045452-57eb5e1fc594 h1:McZ/pt/pP/XAbLMDQGzm/iQUwW6OXmKVbFtmH9klWmc= +github.com/elazarl/go-bindata-assetfs v0.0.0-20151224045452-57eb5e1fc594/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= +github.com/emirpasic/gods v1.9.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/etcd-io/bbolt v1.3.2 h1:RLRQ0TKLX7DlBRXAJHvbmXL17Q3KNnTBtZ9B6Qo+/Y0= +github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethantkoenig/rupture v0.0.0-20180203182544-0a76f03a811a h1:M1bRpaZAn4GSsqu3hdK2R8H0AH9O6vqCTCbm2oAFGfE= +github.com/ethantkoenig/rupture v0.0.0-20180203182544-0a76f03a811a/go.mod h1:MkKY/CB98aVE4VxO63X5vTQKUgcn+3XP15LMASe3lYs= +github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw= +github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/freeport v0.0.0-20150612182905-d4adf43b75b9 h1:wWke/RUCl7VRjQhwPlR/v0glZXNYzBHdNUzf/Am2Nmg= +github.com/facebookgo/freeport v0.0.0-20150612182905-d4adf43b75b9/go.mod h1:uPmAp6Sws4L7+Q/OokbWDAK1ibXYhB3PXFP1kol5hPg= +github.com/facebookgo/grace v0.0.0-20160926231715-5729e484473f h1:0mlfEUWnUDVZnqWEVHGerL5bKYDKMEmT/Qk/W/3nGuo= +github.com/facebookgo/grace v0.0.0-20160926231715-5729e484473f/go.mod h1:KigFdumBXUPSwzLDbeuzyt0elrL7+CP7TKuhrhT4bcU= +github.com/facebookgo/httpdown v0.0.0-20160323221027-a3b1354551a2 h1:3Zvf9wRhl1cOhckN1oRGWPOkIhOketmEcrQ4TeFAoR4= +github.com/facebookgo/httpdown v0.0.0-20160323221027-a3b1354551a2/go.mod h1:TUV/fX3XrTtBQb5+ttSUJzcFgLNpILONFTKmBuk5RSw= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/stats v0.0.0-20151006221625-1b76add642e4 h1:0YtRCqIZs2+Tz49QuH6cJVw/IFqzo39gEqZ0iYLxD2M= +github.com/facebookgo/stats v0.0.0-20151006221625-1b76add642e4/go.mod h1:vsJz7uE339KUCpBXx3JAJzSRH7Uk4iGGyJzR529qDIA= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gliderlabs/ssh v0.1.1 h1:j3L6gSLQalDETeEg/Jg0mGY0/y/N6zI2xX1978P0Uqw= +github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd h1:r04MMPyLHj/QwZuMJ5+7tJcBr1AQjpiAK/rZWRrQT7o= +github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= +github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e h1:SiEs4J3BKVIeaWrH3tKaz3QLZhJ68iJ/A4xrzIoE5+Y= +github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= +github.com/go-macaron/bindata v0.0.0-20161222093048-85786f57eee3 h1:n0H90987ZwasTc9r/RnuaU1G5ePfzLG6Bkc1cY3KqnY= +github.com/go-macaron/bindata v0.0.0-20161222093048-85786f57eee3/go.mod h1:NkmXhFuAlCOqgV5EWhU1DKLrgztCEIVXGmr2DZv/+sk= +github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443 h1:i801KPR7j76uRMLLlGVyb0hiYbgX1FM5+ur81TJWzIw= +github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443/go.mod h1:u+H6rwW+HQwUL+w5uaEJSpIlVZDye1o9MB4Su0JfRfM= +github.com/go-macaron/cache v0.0.0-20151013081102-561735312776 h1:UYIHS1r0WotqB5cIa0PAiV0m6GzD9rDBcn4alp5JgCw= +github.com/go-macaron/cache v0.0.0-20151013081102-561735312776/go.mod h1:hHAsZm/oBZVcY+S7qdQL6Vbg5VrXF6RuKGuqsszt3Ok= +github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab h1:4VFhsA3GE5Wwq1Ymr8KWCmrOWi1wRLEgdj48LPfQjxI= +github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab/go.mod h1:j9TJ+0nwUOWBvNnm0bheHIPFf3cC62EQo7n7O6PbjZA= +github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372 h1:acrx8CnDmlKl+BPoOOLEK9Ko+SrWFB5pxRuGkKj4iqo= +github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372/go.mod h1:oZGMxI7MBnicI0jJqJvH4qQzyrWKhtiKxLSJKHC+ydc= +github.com/go-macaron/i18n v0.0.0-20160612092837-ef57533c3b0f h1:wDKrZFc9pYJlqFOf7EzGbFMrSFFtyHt3plr2uTdo8Rg= +github.com/go-macaron/i18n v0.0.0-20160612092837-ef57533c3b0f/go.mod h1:MePM/dStkAh+PNzAdNSNl4SGDM2EZvZGken+KpJhM7s= +github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 h1:NjHlg70DuOkcAMqgt0+XA+NHwtu66MkTVVgR4fFWbcI= +github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191/go.mod h1:VFI2o2q9kYsC4o7VP1HrEVosiZZTd+MVT3YZx4gqvJw= +github.com/go-macaron/session v0.0.0-20190131233854-0a0a789bf193 h1:z/nqwd+ql/r6Q3QGnwNd6B89UjPytM0be5pDQV9TuWw= +github.com/go-macaron/session v0.0.0-20190131233854-0a0a789bf193/go.mod h1:ScEJm9Gk+ez5JJTml5WlBIqavAfuE5nF8e4Gvyz/X+A= +github.com/go-macaron/toolbox v0.0.0-20180818072302-a77f45a7ce90 h1:3wYKrRg9IjUMfaf3H0Hh7M5Li9ge79Y7aw2yujHa2jQ= +github.com/go-macaron/toolbox v0.0.0-20180818072302-a77f45a7ce90/go.mod h1:Ut/NmkIMGVYlEdJBzEZgWVWG5ZpYS9BLmUgXfAgi+qM= +github.com/go-sql-driver/mysql v0.0.0-20181218123637-c45f530f8e7f h1:fbIzwEaXt5b2bl9mm+PIufKTSGKk6ZuwSSTQ7iZj7Lo= +github.com/go-sql-driver/mysql v0.0.0-20181218123637-c45f530f8e7f/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-xorm/builder v0.3.2/go.mod h1:v8mE3MFBgtL+RGFNfUnAMUqqfk/Y4W5KuwCFQIEpQLk= +github.com/go-xorm/builder v0.3.3 h1:v8grgrwOGv/iHXIEhIvOwHZIPLrpxRKSX8yWSMLFn/4= +github.com/go-xorm/builder v0.3.3/go.mod h1:v8mE3MFBgtL+RGFNfUnAMUqqfk/Y4W5KuwCFQIEpQLk= +github.com/go-xorm/core v0.6.0 h1:tp6hX+ku4OD9khFZS8VGBDRY3kfVCtelPfmkgCyHxL0= +github.com/go-xorm/core v0.6.0/go.mod h1:d8FJ9Br8OGyQl12MCclmYBuBqqxsyeedpXciV5Myih8= +github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y= +github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM= +github.com/go-xorm/xorm v0.0.0-20190116032649-a6300f2a45e0 h1:GBnJjWjp2SGXBZsyZfYksyp7QocvQwf9vZQ0NRN2FXM= +github.com/go-xorm/xorm v0.0.0-20190116032649-a6300f2a45e0/go.mod h1:EHS1htMQFptzMaIHKyzqpHGw6C9Rtug75nsq6DA9unI= +github.com/gogits/chardet v0.0.0-20150115103509-2404f7772561 h1:deE7ritpK04PgtpyVOS2TYcQEld9qLCD5b5EbVNOuLA= +github.com/gogits/chardet v0.0.0-20150115103509-2404f7772561/go.mod h1:YgYOrVn3Nj9Tq0EvjmFbphRytDj7JNRoWSStJZWDJTQ= +github.com/gogits/cron v0.0.0-20160810035002-7f3990acf183 h1:EBTlva3AOSb80G3JSwY6ZMdILEZJ1JKuewrbqrNjWuE= +github.com/gogits/cron v0.0.0-20160810035002-7f3990acf183/go.mod h1:pX+V62FFmklia2fhP3P4YSY6iJdPO5jIDKFQ5fEd5QE= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/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/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY= +github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY= +github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.1.1 h1:YMDmfaK68mUixINzY/XjscuJ47uXFWSSHzFbBQM0PrE= +github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +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 v0.0.0-20160320065130-d36b54562f4c h1:A/PDn117UYld5mlxe58EpMguqpkeTMw5/FCo0ZPS/Ko= +github.com/issue9/identicon v0.0.0-20160320065130-d36b54562f4c/go.mod h1:5mTb/PQNkqmq2x3IxlQZE0aSnTksJg7fg/oWmJ5SKXQ= +github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc= +github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= +github.com/jackc/pgx v3.2.0+incompatible h1:0Vihzu20St42/UDsvZGdNE6jak7oi/UOeMzwMPHkgFY= +github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= +github.com/jaytaylor/html2text v0.0.0-20160923191438-8fb95d837f7d h1:ig/iUfDDg06RVW8OMby+GrmW6K2nPO3AFHlEIdvJSd4= +github.com/jaytaylor/html2text v0.0.0-20160923191438-8fb95d837f7d/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/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kballard/go-shellquote v0.0.0-20170619183022-cd60e84ee657 h1:vE7J1m7cCpiRVEIr1B5ccDxRpbPsWT5JU3if2Di5nE4= +github.com/kballard/go-shellquote v0.0.0-20170619183022-cd60e84ee657/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e h1:RgQk53JHp/Cjunrr1WlsXSZpqXn+uREuHvUVcK82CV8= +github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/keybase/go-crypto v0.0.0-20170605145657-00ac4db533f6 h1:9mszGwKDxHEY2cy+9XxCQKWIfkGPSAEFrcN8ghzyAKg= +github.com/keybase/go-crypto v0.0.0-20170605145657-00ac4db533f6/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v0.0.0-20161025140425-8df558b6cb6f h1:tCnZKEmDovgV4jmsclh6CuKk9AMzTzyVWfejgkgccVg= +github.com/klauspost/compress v0.0.0-20161025140425-8df558b6cb6f/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v0.0.0-20160302075316-09cded8978dc h1:WW8B7p7QBnFlqRVv/k6ro/S8Z7tCnYjJHcQNScx9YVs= +github.com/klauspost/cpuid v0.0.0-20160302075316-09cded8978dc/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6 h1:KAZ1BW2TCmT6PRihDPpocIy1QTtsAsrx6TneU/4+CMg= +github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lafriks/xormstore v1.0.0 h1:P/IJzNSIpjXl/Up3o2Td5ZU/x4v6DEKLMaPQJGtmJCk= +github.com/lafriks/xormstore v1.0.0/go.mod h1:dD8vHNRfEp3Uy+JvX9cMi2SXcRKJ0x4pYKsZuy843Ic= +github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 h1:uNwtsDp7ci48vBTTxDuwcoTXz4lwtDTe7TjCQ0noaWY= +github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96/go.mod h1:mmIfjCSQlGYXmJ95jFN84AkQFnVABtKuJL8IrzwvUKQ= +github.com/lunny/levelqueue v0.0.0-20190217115915-02b525a4418e h1:GSprKUrG9wNgwQgROvjPGXmcZrg4OLslOuZGB0uJjx8= +github.com/lunny/levelqueue v0.0.0-20190217115915-02b525a4418e/go.mod h1:rQZVENnBOiVakCs97XvclbwJRTAv77CRFWcYVNDkVf8= +github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de h1:nyxwRdWHAVxpFcDThedEgQ07DbcRc5xgNObtbTp76fk= +github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ= +github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af h1:UaWHNBdukWrSG3DRvHFR/hyfg681fceqQDYVTBncKfQ= +github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VObJ7peltM+2n3PWOz7yTrfUuGbVFkzN0= +github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA= +github.com/markbates/goth v1.49.0 h1:qQ4Ti4WaqAxNAggOC+4s5M85sMVfMJwQn/Xkp73wfgI= +github.com/markbates/goth v1.49.0/go.mod h1:zZmAw0Es0Dpm7TT/4AdN14QrkiWLMrrU9Xei1o+/mdA= +github.com/mattn/go-oci8 v0.0.0-20190320171441-14ba190cf52d h1:m+dSK37rFf2fqppZhg15yI2IwC9BtucBiRwSDm9VL8g= +github.com/mattn/go-oci8 v0.0.0-20190320171441-14ba190cf52d/go.mod h1:/M9VLO+lUPmxvoOK2PfWRZ8mTtB4q1Hy9lEGijv9Nr8= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= +github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mcuadros/go-version v0.0.0-20171003094716-88e56e02bea1 h1:4yXas1DDHpauOfuyfmAMm+EB+SiqPKEoTdc88XEJHsc= +github.com/mcuadros/go-version v0.0.0-20171003094716-88e56e02bea1/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo= +github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a h1:d18LCO3ctH2kugUqt0pEyKKP8L+IYrocaPqGFilhTKk= +github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= +github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c h1:3wkDRdxK92dF+c1ke2dtj7ZzemFWBHB9plnJOtlwdFA= +github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc h1:z1PgdCCmYYVL0BoJTUgmAq1p7ca8fzYIPsNyfsN3xAU= +github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc/go.mod h1:np1wUFZ6tyoke22qDJZY40URn9Ae51gX7ljIWXN5TJs= +github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY= +github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA= +github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= +github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/otp v0.0.0-20160912161815-54653902c20e h1:ApqncJ84HYN8x8x5WV1T1YWDuPRF/0aXZhr91LnRMCQ= +github.com/pquerna/otp v0.0.0-20160912161815-54653902c20e/go.mod h1:Zad1CMQfSQZI5KLpahDiSUX4tMMREnXw98IvL1nhgMk= +github.com/prometheus/client_golang v0.9.0 h1:tXuTFVHC03mW0D+Ua1Q2d1EAVqLTuggX50V0VLICCzY= +github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39 h1:Cto4X6SVMWRPBkJ/3YHn1iDGDGc/Z+sW+AEMKHMVvN4= +github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFdaDqxJVlbOQ1DtGmZWs/Qau0hIlk+WQ= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 h1:YDeskXpkNDhPdWN3REluVa46HQOVuVkjkd2sWnrABNQ= +github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff h1:g9ZlAHmkc/h5So+OjNCkZWh+FjuKEOOOoyRkqlGA8+c= +github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI= +github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +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/sanitized_anchor_name v0.0.0-20160918041101-1dba4b3954bc h1:3wIrJvFb3Pf6B/2mDBnN1G5IfUVev4X5apadQlWOczE= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20160918041101-1dba4b3954bc/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d h1:qQWKKOvHN7Q9c6GdmUteCef2F9ubxMpxY1IKwpIKz68= +github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d/go.mod h1:vq0tzqLRu6TS7Id0wMo2N5QzJoKedVeovOpHjnykSzY= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff h1:86HlEv0yBCry9syNuylzqznKXDK11p6D0DT596yNMys= +github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff/go.mod h1:KSQcGKpxUMHk3nbYzs/tIBAM2iDooCn0BmttHOJEbLs= +github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= +github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= +github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2 h1:JNEGSiWg6D3lcBCMCBqN3ELniXujt+0QNHLhNnO0w3s= +github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2/go.mod h1:mjqs7N0Q6m5HpR7QfXVBZXZWSqTjQLeTujjA/xUp2uw= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/syndtr/goleveldb v0.0.0-20190203031304-2f17a3356c66 h1:AwmkkZT+TucFotNCL+aNJ/0KCMsRtlXN9fs8uoOMSRk= +github.com/syndtr/goleveldb v0.0.0-20190203031304-2f17a3356c66/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481 h1:HOxvxvnntLiPn123Fk+twfUhCQdMDaqmb0cclArW0T0= +github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= +github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200 h1:ZVvr38DYEyOPyelySqvF0I9I++85NnUMsWkroBDS4fs= +github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ= +github.com/tstranex/u2f v1.0.0/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGBSayo= +github.com/urfave/cli v0.0.0-20161102131801-d86a009f5e13 h1:niRuEF0NOlFnqraxzjuvvOdCM6gxmHiaBABjvg3/kDo= +github.com/urfave/cli v0.0.0-20161102131801-d86a009f5e13/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 h1:E8u341JM/N8LCnPXBV6ZFD1RKo/j+qHl1XOqSV+GstA= +github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/xanzy/ssh-agent v0.2.0 h1:Adglfbi5p9Z0BmK2oKU9nTG+zKfniSfnaMYB+ULd+Ro= +github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8= +github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53 h1:HsIQ6yAjfjQ3IxPGrTusxp6Qxn92gNVq2x5CbvQvx3w= +github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53/go.mod h1:f6elajwZV+xceiaqgRL090YzLEDGSbqr3poGL3ZgXYo= +github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= +github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= +go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519 h1:x6rhz8Y9CjbgQkccRGmELH6K+LJj7tOoh3XWeC1yaQM= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181101160152-c453e0c75759 h1:TMrx+Qdx7uJAeUbv15N72h5Hmyb5+VDjEiMufAEAM04= +golang.org/x/oauth2 v0.0.0-20181101160152-c453e0c75759/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026144532-2772b66316d2 h1:W7CqTdBJ1CmxLKe7LptKDnBYV6PHrVLiGnoyBjaG/JQ= +golang.org/x/sys v0.0.0-20181026144532-2772b66316d2/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +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/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +google.golang.org/appengine v1.2.0 h1:S0iUepdCWODXRvtE+gcRDd15L+k+k1AiHlMiMjefH24= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= +gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 h1:nn6Zav2sOQHCFJHEspya8KqxhFwKci30UxHy3HXPTyQ= +gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= +gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e h1:wGA78yza6bu/mWcc4QfBuIEHEtc06xdiU0X8sY36yUU= +gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e/go.mod h1:xsQCaysVCudhrYTfzYWe577fCe7Ceci+6qjO2Rdc0Z4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/editorconfig/editorconfig-core-go.v1 v1.2.0 h1:CO465/foR4+bY1xNYjZEl6l8By1g/iMsImoruxfEt84= +gopkg.in/editorconfig/editorconfig-core-go.v1 v1.2.0/go.mod h1:s2mQFI9McjArkyCwyEwU//+luQENTnD/Lfb/7Sj3/kQ= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= +gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= +gopkg.in/ini.v1 v1.31.1 h1:8EY/6KDwKM9Qg4vu1+01ZpsxClC/XV71R+nZ/TL7D4M= +gopkg.in/ini.v1 v1.31.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ldap.v3 v3.0.2 h1:R6RBtabK6e1GO0eQKtkyOFbAHO73QesLzI2w2DZ6b9w= +gopkg.in/ldap.v3 v3.0.2/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw= +gopkg.in/macaron.v1 v1.3.2 h1:AvWIaPmwBUA87/OWzePkoxeaw6YJWDfBt1pDFPBnLf8= +gopkg.in/macaron.v1 v1.3.2/go.mod h1:PrsiawTWAGZs6wFbT5hlr7SQ2Ns9h7cUVtcUu4lQOVo= +gopkg.in/redis.v2 v2.3.2 h1:GPVIIB/JnL1wvfULefy3qXmPu1nfNu2d0yA09FHgwfs= +gopkg.in/redis.v2 v2.3.2/go.mod h1:4wl9PJ/CqzeHk3LVq1hNLHH8krm3+AXEgut4jVc++LU= +gopkg.in/src-d/go-billy.v4 v4.2.1/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= +gopkg.in/src-d/go-billy.v4 v4.3.0 h1:KtlZ4c1OWbIs4jCv5ZXrTqG8EQocr0g/d4DjNg70aek= +gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= +gopkg.in/src-d/go-git-fixtures.v3 v3.1.1 h1:XWW/s5W18RaJpmo1l0IYGqXKuJITWRFuA45iOf1dKJs= +gopkg.in/src-d/go-git-fixtures.v3 v3.1.1/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= +gopkg.in/src-d/go-git.v4 v4.8.0 h1:dDEbgvfNG9vUDM54uhCYPExiGa8uYgXpQ/MR8YvxcAM= +gopkg.in/src-d/go-git.v4 v4.8.0/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk= +gopkg.in/stretchr/testify.v1 v1.2.2 h1:yhQC6Uy5CqibAIlk1wlusa/MJ3iAN49/BsR/dCCKz3M= +gopkg.in/stretchr/testify.v1 v1.2.2/go.mod h1:QI5V/q6UbPmuhtm10CaFZxED9NreB8PnFYN9JcR6TxU= +gopkg.in/testfixtures.v2 v2.5.0 h1:N08B7l2GzFQenyYbzqthDnKAA+cmb17iAZhhFxr7JHw= +gopkg.in/testfixtures.v2 v2.5.0/go.mod h1:vyAq+MYCgNpR29qitQdLZhdbLFf4mR/2MFJRFoQZZ2M= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +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.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +mvdan.cc/xurls/v2 v2.0.0 h1:r1zSOSNS/kqtpmATyMMMvaZ4/djsesbYz5kr0+qMRWc= +mvdan.cc/xurls/v2 v2.0.0/go.mod h1:2/webFPYOXN9jp/lzuj0zuAVlF+9g4KPFJANH1oJhRU= +strk.kbt.io/projects/go/libravatar v0.0.0-20160628055650-5eed7bff870a h1:8q33ShxKXRwQ7JVd1ZnhIU3hZhwwn0Le+4fTeAackuM= +strk.kbt.io/projects/go/libravatar v0.0.0-20160628055650-5eed7bff870a/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY= diff --git a/modules/markup/html.go b/modules/markup/html.go index 20a158b1c5..f4c5d97480 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -17,9 +17,9 @@ import ( "code.gitea.io/gitea/modules/util" "github.com/Unknwon/com" - "github.com/mvdan/xurls" "golang.org/x/net/html" "golang.org/x/net/html/atom" + "mvdan.cc/xurls/v2" ) // Issue name styles diff --git a/vendor/github.com/BurntSushi/toml/.gitignore b/vendor/github.com/BurntSushi/toml/.gitignore new file mode 100644 index 0000000000..0cd3800377 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/.gitignore @@ -0,0 +1,5 @@ +TAGS +tags +.*.swp +tomlcheck/tomlcheck +toml.test diff --git a/vendor/github.com/BurntSushi/toml/.travis.yml b/vendor/github.com/BurntSushi/toml/.travis.yml new file mode 100644 index 0000000000..8b8afc4f0e --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/.travis.yml @@ -0,0 +1,15 @@ +language: go +go: + - 1.1 + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - tip +install: + - go install ./... + - go get github.com/BurntSushi/toml-test +script: + - export PATH="$PATH:$HOME/gopath/bin" + - make test diff --git a/vendor/github.com/BurntSushi/toml/COMPATIBLE b/vendor/github.com/BurntSushi/toml/COMPATIBLE new file mode 100644 index 0000000000..6efcfd0ce5 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/COMPATIBLE @@ -0,0 +1,3 @@ +Compatible with TOML version +[v0.4.0](https://github.com/toml-lang/toml/blob/v0.4.0/versions/en/toml-v0.4.0.md) + diff --git a/vendor/github.com/BurntSushi/toml/Makefile b/vendor/github.com/BurntSushi/toml/Makefile new file mode 100644 index 0000000000..3600848d33 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/Makefile @@ -0,0 +1,19 @@ +install: + go install ./... + +test: install + go test -v + toml-test toml-test-decoder + toml-test -encoder toml-test-encoder + +fmt: + gofmt -w *.go */*.go + colcheck *.go */*.go + +tags: + find ./ -name '*.go' -print0 | xargs -0 gotags > TAGS + +push: + git push origin master + git push github master + diff --git a/vendor/github.com/BurntSushi/toml/README.md b/vendor/github.com/BurntSushi/toml/README.md new file mode 100644 index 0000000000..7c1b37ecc7 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/README.md @@ -0,0 +1,218 @@ +## TOML parser and encoder for Go with reflection + +TOML stands for Tom's Obvious, Minimal Language. This Go package provides a +reflection interface similar to Go's standard library `json` and `xml` +packages. This package also supports the `encoding.TextUnmarshaler` and +`encoding.TextMarshaler` interfaces so that you can define custom data +representations. (There is an example of this below.) + +Spec: https://github.com/toml-lang/toml + +Compatible with TOML version +[v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md) + +Documentation: https://godoc.org/github.com/BurntSushi/toml + +Installation: + +```bash +go get github.com/BurntSushi/toml +``` + +Try the toml validator: + +```bash +go get github.com/BurntSushi/toml/cmd/tomlv +tomlv some-toml-file.toml +``` + +[![Build Status](https://travis-ci.org/BurntSushi/toml.svg?branch=master)](https://travis-ci.org/BurntSushi/toml) [![GoDoc](https://godoc.org/github.com/BurntSushi/toml?status.svg)](https://godoc.org/github.com/BurntSushi/toml) + +### Testing + +This package passes all tests in +[toml-test](https://github.com/BurntSushi/toml-test) for both the decoder +and the encoder. + +### Examples + +This package works similarly to how the Go standard library handles `XML` +and `JSON`. Namely, data is loaded into Go values via reflection. + +For the simplest example, consider some TOML file as just a list of keys +and values: + +```toml +Age = 25 +Cats = [ "Cauchy", "Plato" ] +Pi = 3.14 +Perfection = [ 6, 28, 496, 8128 ] +DOB = 1987-07-05T05:45:00Z +``` + +Which could be defined in Go as: + +```go +type Config struct { + Age int + Cats []string + Pi float64 + Perfection []int + DOB time.Time // requires `import time` +} +``` + +And then decoded with: + +```go +var conf Config +if _, err := toml.Decode(tomlData, &conf); err != nil { + // handle error +} +``` + +You can also use struct tags if your struct field name doesn't map to a TOML +key value directly: + +```toml +some_key_NAME = "wat" +``` + +```go +type TOML struct { + ObscureKey string `toml:"some_key_NAME"` +} +``` + +### Using the `encoding.TextUnmarshaler` interface + +Here's an example that automatically parses duration strings into +`time.Duration` values: + +```toml +[[song]] +name = "Thunder Road" +duration = "4m49s" + +[[song]] +name = "Stairway to Heaven" +duration = "8m03s" +``` + +Which can be decoded with: + +```go +type song struct { + Name string + Duration duration +} +type songs struct { + Song []song +} +var favorites songs +if _, err := toml.Decode(blob, &favorites); err != nil { + log.Fatal(err) +} + +for _, s := range favorites.Song { + fmt.Printf("%s (%s)\n", s.Name, s.Duration) +} +``` + +And you'll also need a `duration` type that satisfies the +`encoding.TextUnmarshaler` interface: + +```go +type duration struct { + time.Duration +} + +func (d *duration) UnmarshalText(text []byte) error { + var err error + d.Duration, err = time.ParseDuration(string(text)) + return err +} +``` + +### More complex usage + +Here's an example of how to load the example from the official spec page: + +```toml +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it + +# Line breaks are OK when inside arrays +hosts = [ + "alpha", + "omega" +] +``` + +And the corresponding Go types are: + +```go +type tomlConfig struct { + Title string + Owner ownerInfo + DB database `toml:"database"` + Servers map[string]server + Clients clients +} + +type ownerInfo struct { + Name string + Org string `toml:"organization"` + Bio string + DOB time.Time +} + +type database struct { + Server string + Ports []int + ConnMax int `toml:"connection_max"` + Enabled bool +} + +type server struct { + IP string + DC string +} + +type clients struct { + Data [][]interface{} + Hosts []string +} +``` + +Note that a case insensitive match will be tried if an exact match can't be +found. + +A working example of the above can be found in `_examples/example.{go,toml}`. diff --git a/vendor/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING b/vendor/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING deleted file mode 100644 index 01b5743200..0000000000 --- a/vendor/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 TOML 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. diff --git a/vendor/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING b/vendor/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING deleted file mode 100644 index 01b5743200..0000000000 --- a/vendor/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 TOML 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. diff --git a/vendor/github.com/BurntSushi/toml/cmd/tomlv/COPYING b/vendor/github.com/BurntSushi/toml/cmd/tomlv/COPYING deleted file mode 100644 index 01b5743200..0000000000 --- a/vendor/github.com/BurntSushi/toml/cmd/tomlv/COPYING +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 TOML 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. diff --git a/vendor/github.com/BurntSushi/toml/session.vim b/vendor/github.com/BurntSushi/toml/session.vim new file mode 100644 index 0000000000..562164be06 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/session.vim @@ -0,0 +1 @@ +au BufWritePost *.go silent!make tags > /dev/null 2>&1 diff --git a/vendor/github.com/PuerkitoBio/goquery/.gitattributes b/vendor/github.com/PuerkitoBio/goquery/.gitattributes new file mode 100644 index 0000000000..0cc26ec01c --- /dev/null +++ b/vendor/github.com/PuerkitoBio/goquery/.gitattributes @@ -0,0 +1 @@ +testdata/* linguist-vendored diff --git a/vendor/github.com/PuerkitoBio/goquery/.gitignore b/vendor/github.com/PuerkitoBio/goquery/.gitignore new file mode 100644 index 0000000000..970381cd26 --- /dev/null +++ b/vendor/github.com/PuerkitoBio/goquery/.gitignore @@ -0,0 +1,16 @@ +# editor temporary files +*.sublime-* +.DS_Store +*.swp +#*.*# +tags + +# direnv config +.env* + +# test binaries +*.test + +# coverage and profilte outputs +*.out + diff --git a/vendor/github.com/PuerkitoBio/goquery/.travis.yml b/vendor/github.com/PuerkitoBio/goquery/.travis.yml new file mode 100644 index 0000000000..148a1fb532 --- /dev/null +++ b/vendor/github.com/PuerkitoBio/goquery/.travis.yml @@ -0,0 +1,12 @@ +language: go + +go: + - 1.1.x + - 1.2.x + - 1.3.x + - 1.4.x + - 1.5.x + - 1.6.x + - 1.7.x + - 1.8.x + - tip diff --git a/vendor/github.com/PuerkitoBio/goquery/README.md b/vendor/github.com/PuerkitoBio/goquery/README.md new file mode 100644 index 0000000000..7b01a27178 --- /dev/null +++ b/vendor/github.com/PuerkitoBio/goquery/README.md @@ -0,0 +1,126 @@ +# goquery - a little like that j-thing, only in Go +[![build status](https://secure.travis-ci.org/PuerkitoBio/goquery.png)](http://travis-ci.org/PuerkitoBio/goquery) [![GoDoc](https://godoc.org/github.com/PuerkitoBio/goquery?status.png)](http://godoc.org/github.com/PuerkitoBio/goquery) [![Sourcegraph Badge](https://sourcegraph.com/github.com/PuerkitoBio/goquery/-/badge.svg)](https://sourcegraph.com/github.com/PuerkitoBio/goquery?badge) + + +goquery brings a syntax and a set of features similar to [jQuery][] to the [Go language][go]. It is based on Go's [net/html package][html] and the CSS Selector library [cascadia][]. Since the net/html parser returns nodes, and not a full-featured DOM tree, jQuery's stateful manipulation functions (like height(), css(), detach()) have been left off. + +Also, because the net/html parser requires UTF-8 encoding, so does goquery: it is the caller's responsibility to ensure that the source document provides UTF-8 encoded HTML. See the [wiki][] for various options to do this. + +Syntax-wise, it is as close as possible to jQuery, with the same function names when possible, and that warm and fuzzy chainable interface. jQuery being the ultra-popular library that it is, I felt that writing a similar HTML-manipulating library was better to follow its API than to start anew (in the same spirit as Go's `fmt` package), even though some of its methods are less than intuitive (looking at you, [index()][index]...). + +## Installation + +Please note that because of the net/html dependency, goquery requires Go1.1+. + + $ go get github.com/PuerkitoBio/goquery + +(optional) To run unit tests: + + $ cd $GOPATH/src/github.com/PuerkitoBio/goquery + $ go test + +(optional) To run benchmarks (warning: it runs for a few minutes): + + $ cd $GOPATH/src/github.com/PuerkitoBio/goquery + $ go test -bench=".*" + +## Changelog + +**Note that goquery's API is now stable, and will not break.** + +* **2017-02-12 (v1.1.0)** : Add `SetHtml` and `SetText` (thanks to @glebtv). +* **2016-12-29 (v1.0.2)** : Optimize allocations for `Selection.Text` (thanks to @radovskyb). +* **2016-08-28 (v1.0.1)** : Optimize performance for large documents. +* **2016-07-27 (v1.0.0)** : Tag version 1.0.0. +* **2016-06-15** : Invalid selector strings internally compile to a `Matcher` implementation that never matches any node (instead of a panic). So for example, `doc.Find("~")` returns an empty `*Selection` object. +* **2016-02-02** : Add `NodeName` utility function similar to the DOM's `nodeName` property. It returns the tag name of the first element in a selection, and other relevant values of non-element nodes (see godoc for details). Add `OuterHtml` utility function similar to the DOM's `outerHTML` property (named `OuterHtml` in small caps for consistency with the existing `Html` method on the `Selection`). +* **2015-04-20** : Add `AttrOr` helper method to return the attribute's value or a default value if absent. Thanks to [piotrkowalczuk][piotr]. +* **2015-02-04** : Add more manipulation functions - Prepend* - thanks again to [Andrew Stone][thatguystone]. +* **2014-11-28** : Add more manipulation functions - ReplaceWith*, Wrap* and Unwrap - thanks again to [Andrew Stone][thatguystone]. +* **2014-11-07** : Add manipulation functions (thanks to [Andrew Stone][thatguystone]) and `*Matcher` functions, that receive compiled cascadia selectors instead of selector strings, thus avoiding potential panics thrown by goquery via `cascadia.MustCompile` calls. This results in better performance (selectors can be compiled once and reused) and more idiomatic error handling (you can handle cascadia's compilation errors, instead of recovering from panics, which had been bugging me for a long time). Note that the actual type expected is a `Matcher` interface, that `cascadia.Selector` implements. Other matcher implementations could be used. +* **2014-11-06** : Change import paths of net/html to golang.org/x/net/html (see https://groups.google.com/forum/#!topic/golang-nuts/eD8dh3T9yyA). Make sure to update your code to use the new import path too when you call goquery with `html.Node`s. +* **v0.3.2** : Add `NewDocumentFromReader()` (thanks jweir) which allows creating a goquery document from an io.Reader. +* **v0.3.1** : Add `NewDocumentFromResponse()` (thanks assassingj) which allows creating a goquery document from an http response. +* **v0.3.0** : Add `EachWithBreak()` which allows to break out of an `Each()` loop by returning false. This function was added instead of changing the existing `Each()` to avoid breaking compatibility. +* **v0.2.1** : Make go-getable, now that [go.net/html is Go1.0-compatible][gonet] (thanks to @matrixik for pointing this out). +* **v0.2.0** : Add support for negative indices in Slice(). **BREAKING CHANGE** `Document.Root` is removed, `Document` is now a `Selection` itself (a selection of one, the root element, just like `Document.Root` was before). Add jQuery's Closest() method. +* **v0.1.1** : Add benchmarks to use as baseline for refactorings, refactor Next...() and Prev...() methods to use the new html package's linked list features (Next/PrevSibling, FirstChild). Good performance boost (40+% in some cases). +* **v0.1.0** : Initial release. + +## API + +goquery exposes two structs, `Document` and `Selection`, and the `Matcher` interface. Unlike jQuery, which is loaded as part of a DOM document, and thus acts on its containing document, goquery doesn't know which HTML document to act upon. So it needs to be told, and that's what the `Document` type is for. It holds the root document node as the initial Selection value to manipulate. + +jQuery often has many variants for the same function (no argument, a selector string argument, a jQuery object argument, a DOM element argument, ...). Instead of exposing the same features in goquery as a single method with variadic empty interface arguments, statically-typed signatures are used following this naming convention: + +* When the jQuery equivalent can be called with no argument, it has the same name as jQuery for the no argument signature (e.g.: `Prev()`), and the version with a selector string argument is called `XxxFiltered()` (e.g.: `PrevFiltered()`) +* When the jQuery equivalent **requires** one argument, the same name as jQuery is used for the selector string version (e.g.: `Is()`) +* The signatures accepting a jQuery object as argument are defined in goquery as `XxxSelection()` and take a `*Selection` object as argument (e.g.: `FilterSelection()`) +* The signatures accepting a DOM element as argument in jQuery are defined in goquery as `XxxNodes()` and take a variadic argument of type `*html.Node` (e.g.: `FilterNodes()`) +* The signatures accepting a function as argument in jQuery are defined in goquery as `XxxFunction()` and take a function as argument (e.g.: `FilterFunction()`) +* The goquery methods that can be called with a selector string have a corresponding version that take a `Matcher` interface and are defined as `XxxMatcher()` (e.g.: `IsMatcher()`) + +Utility functions that are not in jQuery but are useful in Go are implemented as functions (that take a `*Selection` as parameter), to avoid a potential naming clash on the `*Selection`'s methods (reserved for jQuery-equivalent behaviour). + +The complete [godoc reference documentation can be found here][doc]. + +Please note that Cascadia's selectors do not necessarily match all supported selectors of jQuery (Sizzle). See the [cascadia project][cascadia] for details. Invalid selector strings compile to a `Matcher` that fails to match any node. Behaviour of the various functions that take a selector string as argument follows from that fact, e.g. (where `~` is an invalid selector string): + +* `Find("~")` returns an empty selection because the selector string doesn't match anything. +* `Add("~")` returns a new selection that holds the same nodes as the original selection, because it didn't add any node (selector string didn't match anything). +* `ParentsFiltered("~")` returns an empty selection because the selector string doesn't match anything. +* `ParentsUntil("~")` returns all parents of the selection because the selector string didn't match any element to stop before the top element. + +## Examples + +See some tips and tricks in the [wiki][]. + +Adapted from example_test.go: + +```Go +package main + +import ( + "fmt" + "log" + + "github.com/PuerkitoBio/goquery" +) + +func ExampleScrape() { + doc, err := goquery.NewDocument("http://metalsucks.net") + if err != nil { + log.Fatal(err) + } + + // Find the review items + doc.Find(".sidebar-reviews article .content-block").Each(func(i int, s *goquery.Selection) { + // For each item found, get the band and title + band := s.Find("a").Text() + title := s.Find("i").Text() + fmt.Printf("Review %d: %s - %s\n", i, band, title) + }) +} + +func main() { + ExampleScrape() +} +``` + +## License + +The [BSD 3-Clause license][bsd], the same as the [Go language][golic]. Cascadia's license is [here][caslic]. + +[jquery]: http://jquery.com/ +[go]: http://golang.org/ +[cascadia]: https://github.com/andybalholm/cascadia +[bsd]: http://opensource.org/licenses/BSD-3-Clause +[golic]: http://golang.org/LICENSE +[caslic]: https://github.com/andybalholm/cascadia/blob/master/LICENSE +[doc]: http://godoc.org/github.com/PuerkitoBio/goquery +[index]: http://api.jquery.com/index/ +[gonet]: https://github.com/golang/net/ +[html]: http://godoc.org/golang.org/x/net/html +[wiki]: https://github.com/PuerkitoBio/goquery/wiki/Tips-and-tricks +[thatguystone]: https://github.com/thatguystone +[piotr]: https://github.com/piotrkowalczuk diff --git a/vendor/github.com/RoaringBitmap/roaring/.gitignore b/vendor/github.com/RoaringBitmap/roaring/.gitignore new file mode 100644 index 0000000000..b7943ab209 --- /dev/null +++ b/vendor/github.com/RoaringBitmap/roaring/.gitignore @@ -0,0 +1,6 @@ +*~ +roaring-fuzz.zip +workdir +coverage.out +testdata/all3.classic +testdata/all3.msgp.snappy diff --git a/vendor/github.com/RoaringBitmap/roaring/.gitmodules b/vendor/github.com/RoaringBitmap/roaring/.gitmodules new file mode 100644 index 0000000000..e69de29bb2 diff --git a/vendor/github.com/RoaringBitmap/roaring/.travis.yml b/vendor/github.com/RoaringBitmap/roaring/.travis.yml new file mode 100644 index 0000000000..1fdcf3e057 --- /dev/null +++ b/vendor/github.com/RoaringBitmap/roaring/.travis.yml @@ -0,0 +1,30 @@ +language: go +sudo: false +install: +- go get -t github.com/RoaringBitmap/roaring +- go get -t golang.org/x/tools/cmd/cover +- go get -t github.com/mattn/goveralls +- go get -t github.com/mschoch/smat +notifications: + email: false +go: +- 1.7.x +- 1.8.x +- 1.9.x +- 1.10.x +- tip + +# whitelist +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 +- go test -race -run TestConcurrent* +- GOARCH=arm64 go build +- GOARCH=386 go build +- GOARCH=386 go test +- GOARCH=arm go build +matrix: + allow_failures: + - go: tip diff --git a/vendor/github.com/RoaringBitmap/roaring/Makefile b/vendor/github.com/RoaringBitmap/roaring/Makefile new file mode 100644 index 0000000000..d5259b4c9e --- /dev/null +++ b/vendor/github.com/RoaringBitmap/roaring/Makefile @@ -0,0 +1,121 @@ +.PHONY: help all test format fmtcheck vet lint qa deps clean nuke rle backrle ser fetch-real-roaring-datasets + + + + + + + + +# Display general help about this command +help: + @echo "" + @echo "The following commands are available:" + @echo "" + @echo " make qa : Run all the tests" + @echo " make test : Run the unit tests" + @echo "" + @echo " make format : Format the source code" + @echo " make fmtcheck : Check if the source code has been formatted" + @echo " make vet : Check for suspicious constructs" + @echo " make lint : Check for style errors" + @echo "" + @echo " make deps : Get the dependencies" + @echo " make clean : Remove any build artifact" + @echo " make nuke : Deletes any intermediate file" + @echo "" + @echo " make fuzz-smat : Fuzzy testing with smat" + @echo " make fuzz-stream : Fuzzy testing with stream deserialization" + @echo " make fuzz-buffer : Fuzzy testing with buffer deserialization" + @echo "" + +# Alias for help target +all: help +test: + go test + go test -race -run TestConcurrent* +# Format the source code +format: + @find ./ -type f -name "*.go" -exec gofmt -w {} \; + +# Check if the source code has been formatted +fmtcheck: + @mkdir -p target + @find ./ -type f -name "*.go" -exec gofmt -d {} \; | tee target/format.diff + @test ! -s target/format.diff || { echo "ERROR: the source code has not been formatted - please use 'make format' or 'gofmt'"; exit 1; } + +# Check for syntax errors +vet: + GOPATH=$(GOPATH) go vet ./... + +# Check for style errors +lint: + GOPATH=$(GOPATH) PATH=$(GOPATH)/bin:$(PATH) golint ./... + + + + + +# Alias to run all quality-assurance checks +qa: fmtcheck test vet lint + +# --- INSTALL --- + +# Get the dependencies +deps: + GOPATH=$(GOPATH) go get github.com/smartystreets/goconvey/convey + GOPATH=$(GOPATH) go get github.com/willf/bitset + GOPATH=$(GOPATH) go get github.com/golang/lint/golint + GOPATH=$(GOPATH) go get github.com/mschoch/smat + GOPATH=$(GOPATH) go get github.com/dvyukov/go-fuzz/go-fuzz + GOPATH=$(GOPATH) go get github.com/dvyukov/go-fuzz/go-fuzz-build + GOPATH=$(GOPATH) go get github.com/glycerine/go-unsnap-stream + GOPATH=$(GOPATH) go get github.com/philhofer/fwd + GOPATH=$(GOPATH) go get github.com/jtolds/gls + +fuzz-smat: + go test -tags=gofuzz -run=TestGenerateSmatCorpus + go-fuzz-build -func FuzzSmat github.com/RoaringBitmap/roaring + go-fuzz -bin=./roaring-fuzz.zip -workdir=workdir/ -timeout=200 + + +fuzz-stream: + go-fuzz-build -func FuzzSerializationStream github.com/RoaringBitmap/roaring + go-fuzz -bin=./roaring-fuzz.zip -workdir=workdir/ -timeout=200 + + +fuzz-buffer: + go-fuzz-build -func FuzzSerializationBuffer github.com/RoaringBitmap/roaring + go-fuzz -bin=./roaring-fuzz.zip -workdir=workdir/ -timeout=200 + +# Remove any build artifact +clean: + GOPATH=$(GOPATH) go clean ./... + +# Deletes any intermediate file +nuke: + rm -rf ./target + GOPATH=$(GOPATH) go clean -i ./... + +rle: + cp rle.go rle16.go + perl -pi -e 's/32/16/g' rle16.go + cp rle_test.go rle16_test.go + perl -pi -e 's/32/16/g' rle16_test.go + +backrle: + cp rle16.go rle.go + perl -pi -e 's/16/32/g' rle.go + perl -pi -e 's/2032/2016/g' rle.go + +ser: rle + go generate + +cover: + go test -coverprofile=coverage.out + go tool cover -html=coverage.out + +fetch-real-roaring-datasets: + # pull github.com/RoaringBitmap/real-roaring-datasets -> testdata/real-roaring-datasets + git submodule init + git submodule update diff --git a/vendor/github.com/RoaringBitmap/roaring/README.md b/vendor/github.com/RoaringBitmap/roaring/README.md new file mode 100644 index 0000000000..2c096ce8e6 --- /dev/null +++ b/vendor/github.com/RoaringBitmap/roaring/README.md @@ -0,0 +1,246 @@ +roaring [![Build Status](https://travis-ci.org/RoaringBitmap/roaring.png)](https://travis-ci.org/RoaringBitmap/roaring) [![Coverage Status](https://coveralls.io/repos/github/RoaringBitmap/roaring/badge.svg?branch=master)](https://coveralls.io/github/RoaringBitmap/roaring?branch=master) [![GoDoc](https://godoc.org/github.com/RoaringBitmap/roaring?status.svg)](https://godoc.org/github.com/RoaringBitmap/roaring) [![Go Report Card](https://goreportcard.com/badge/RoaringBitmap/roaring)](https://goreportcard.com/report/github.com/RoaringBitmap/roaring) +============= + +This is a go version of the Roaring bitmap data structure. + + + +Roaring bitmaps are used by several major systems such as [Apache Lucene][lucene] and derivative systems such as [Solr][solr] and +[Elasticsearch][elasticsearch], [Metamarkets' Druid][druid], [LinkedIn Pinot][pinot], [Netflix Atlas][atlas], [Apache Spark][spark], [OpenSearchServer][opensearchserver], [Cloud Torrent][cloudtorrent], [Whoosh][whoosh], [Pilosa][pilosa], [Microsoft Visual Studio Team Services (VSTS)][vsts], and eBay's [Apache Kylin][kylin]. + +[lucene]: https://lucene.apache.org/ +[solr]: https://lucene.apache.org/solr/ +[elasticsearch]: https://www.elastic.co/products/elasticsearch +[druid]: http://druid.io/ +[spark]: https://spark.apache.org/ +[opensearchserver]: http://www.opensearchserver.com +[cloudtorrent]: https://github.com/jpillora/cloud-torrent +[whoosh]: https://bitbucket.org/mchaput/whoosh/wiki/Home +[pilosa]: https://www.pilosa.com/ +[kylin]: http://kylin.apache.org/ +[pinot]: http://github.com/linkedin/pinot/wiki +[vsts]: https://www.visualstudio.com/team-services/ +[atlas]: https://github.com/Netflix/atlas + +Roaring bitmaps are found to work well in many important applications: + +> Use Roaring for bitmap compression whenever possible. Do not use other bitmap compression methods ([Wang et al., SIGMOD 2017](http://db.ucsd.edu/wp-content/uploads/2017/03/sidm338-wangA.pdf)) + + +The ``roaring`` Go library is used by +* [Cloud Torrent](https://github.com/jpillora/cloud-torrent): a self-hosted remote torrent client +* [runv](https://github.com/hyperhq/runv): an Hypervisor-based runtime for the Open Containers Initiative +* [InfluxDB](https://www.influxdata.com) +* [Pilosa](https://www.pilosa.com/) +* [Bleve](http://www.blevesearch.com) + +This library is used in production in several systems, it is part of the [Awesome Go collection](https://awesome-go.com). + + +There are also [Java](https://github.com/RoaringBitmap/RoaringBitmap) and [C/C++](https://github.com/RoaringBitmap/CRoaring) versions. The Java, C, C++ and Go version are binary compatible: e.g, you can save bitmaps +from a Java program and load them back in Go, and vice versa. We have a [format specification](https://github.com/RoaringBitmap/RoaringFormatSpec). + + +This code is licensed under Apache License, Version 2.0 (ASL2.0). + +Copyright 2016-... by the authors. + + +### References + +- Daniel Lemire, Owen Kaser, Nathan Kurz, Luca Deri, Chris O'Hara, François Saint-Jacques, Gregory Ssi-Yan-Kai, Roaring Bitmaps: Implementation of an Optimized Software Library, Software: Practice and Experience 48 (4), 2018 [arXiv:1709.07821](https://arxiv.org/abs/1709.07821) +- Samy Chambi, Daniel Lemire, Owen Kaser, Robert Godin, +Better bitmap performance with Roaring bitmaps, +Software: Practice and Experience 46 (5), 2016. +http://arxiv.org/abs/1402.6407 This paper used data from http://lemire.me/data/realroaring2014.html +- Daniel Lemire, Gregory Ssi-Yan-Kai, Owen Kaser, Consistently faster and smaller compressed bitmaps with Roaring, Software: Practice and Experience 46 (11), 2016. http://arxiv.org/abs/1603.06549 + + +### Dependencies + +Dependencies are fetched automatically by giving the `-t` flag to `go get`. + +they include + - github.com/smartystreets/goconvey/convey + - github.com/willf/bitset + - github.com/mschoch/smat + - github.com/glycerine/go-unsnap-stream + - github.com/philhofer/fwd + - github.com/jtolds/gls + +Note that the smat library requires Go 1.6 or better. + +#### Installation + + - go get -t github.com/RoaringBitmap/roaring + + +### Example + +Here is a simplified but complete example: + +```go +package main + +import ( + "fmt" + "github.com/RoaringBitmap/roaring" + "bytes" +) + + +func main() { + // example inspired by https://github.com/fzandona/goroar + fmt.Println("==roaring==") + rb1 := roaring.BitmapOf(1, 2, 3, 4, 5, 100, 1000) + fmt.Println(rb1.String()) + + rb2 := roaring.BitmapOf(3, 4, 1000) + fmt.Println(rb2.String()) + + rb3 := roaring.New() + fmt.Println(rb3.String()) + + fmt.Println("Cardinality: ", rb1.GetCardinality()) + + fmt.Println("Contains 3? ", rb1.Contains(3)) + + rb1.And(rb2) + + rb3.Add(1) + rb3.Add(5) + + rb3.Or(rb1) + + // computes union of the three bitmaps in parallel using 4 workers + roaring.ParOr(4, rb1, rb2, rb3) + // computes intersection of the three bitmaps in parallel using 4 workers + roaring.ParAnd(4, rb1, rb2, rb3) + + + // prints 1, 3, 4, 5, 1000 + i := rb3.Iterator() + for i.HasNext() { + fmt.Println(i.Next()) + } + fmt.Println() + + // next we include an example of serialization + buf := new(bytes.Buffer) + rb1.WriteTo(buf) // we omit error handling + newrb:= roaring.New() + newrb.ReadFrom(buf) + if rb1.Equals(newrb) { + fmt.Println("I wrote the content to a byte stream and read it back.") + } +} +``` + +If you wish to use serialization and handle errors, you might want to +consider the following sample of code: + +```go + rb := BitmapOf(1, 2, 3, 4, 5, 100, 1000) + buf := new(bytes.Buffer) + size,err:=rb.WriteTo(buf) + if err != nil { + t.Errorf("Failed writing") + } + newrb:= New() + size,err=newrb.ReadFrom(buf) + if err != nil { + t.Errorf("Failed reading") + } + if ! rb.Equals(newrb) { + t.Errorf("Cannot retrieve serialized version") + } +``` + +Given N integers in [0,x), then the serialized size in bytes of +a Roaring bitmap should never exceed this bound: + +`` 8 + 9 * ((long)x+65535)/65536 + 2 * N `` + +That is, given a fixed overhead for the universe size (x), Roaring +bitmaps never use more than 2 bytes per integer. You can call +``BoundSerializedSizeInBytes`` for a more precise estimate. + + +### Documentation + +Current documentation is available at http://godoc.org/github.com/RoaringBitmap/roaring + +### Goroutine safety + +In general, it should not generally be considered safe to access +the same bitmaps using different goroutines--they are left +unsynchronized for performance. Should you want to access +a Bitmap from more than one goroutine, you should +provide synchronization. Typically this is done by using channels to pass +the *Bitmap around (in Go style; so there is only ever one owner), +or by using `sync.Mutex` to serialize operations on Bitmaps. + +### Coverage + +We test our software. For a report on our test coverage, see + +https://coveralls.io/github/RoaringBitmap/roaring?branch=master + +### Benchmark + +Type + + go test -bench Benchmark -run - + +To run benchmarks on [Real Roaring Datasets](https://github.com/RoaringBitmap/real-roaring-datasets) +run the following: + +```sh +go get github.com/RoaringBitmap/real-roaring-datasets +BENCH_REAL_DATA=1 go test -bench BenchmarkRealData -run - +``` + +### Iterative use + +You can use roaring with gore: + +- go get -u github.com/motemen/gore +- Make sure that ``$GOPATH/bin`` is in your ``$PATH``. +- go get github/RoaringBitmap/roaring + +```go +$ gore +gore version 0.2.6 :help for help +gore> :import github.com/RoaringBitmap/roaring +gore> x:=roaring.New() +gore> x.Add(1) +gore> x.String() +"{1}" +``` + + +### Fuzzy testing + +You can help us test further the library with fuzzy testing: + + go get github.com/dvyukov/go-fuzz/go-fuzz + go get github.com/dvyukov/go-fuzz/go-fuzz-build + go test -tags=gofuzz -run=TestGenerateSmatCorpus + go-fuzz-build github.com/RoaringBitmap/roaring + go-fuzz -bin=./roaring-fuzz.zip -workdir=workdir/ -timeout=200 + +Let it run, and if the # of crashers is > 0, check out the reports in +the workdir where you should be able to find the panic goroutine stack +traces. + +### Alternative in Go + +There is a Go version wrapping the C/C++ implementation https://github.com/RoaringBitmap/gocroaring + +For an alternative implementation in Go, see https://github.com/fzandona/goroar +The two versions were written independently. + + +### Mailing list/discussion group + +https://groups.google.com/forum/#!forum/roaring-bitmaps diff --git a/vendor/github.com/Unknwon/cae/.gitignore b/vendor/github.com/Unknwon/cae/.gitignore new file mode 100644 index 0000000000..b6c97b1593 --- /dev/null +++ b/vendor/github.com/Unknwon/cae/.gitignore @@ -0,0 +1,25 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test +.idea + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +cae.iml +*.exe +.DS_Store diff --git a/vendor/github.com/Unknwon/cae/README.md b/vendor/github.com/Unknwon/cae/README.md new file mode 100644 index 0000000000..e72de97205 --- /dev/null +++ b/vendor/github.com/Unknwon/cae/README.md @@ -0,0 +1,37 @@ +Compression and Archive Extensions +================================== + +[![Go Walker](http://gowalker.org/api/v1/badge)](http://gowalker.org/github.com/Unknwon/cae) + +[中文文档](README_ZH.md) + +Package cae implements PHP-like Compression and Archive Extensions. + +But this package has some modifications depends on Go-style. + +Reference: [PHP:Compression and Archive Extensions](http://www.php.net/manual/en/refs.compression.php). + +Code Convention: based on [Go Code Convention](https://github.com/Unknwon/go-code-convention). + +### Implementations + +Package `zip`([Go Walker](http://gowalker.org/github.com/Unknwon/cae/zip)) and `tz`([Go Walker](http://gowalker.org/github.com/Unknwon/cae/tz)) both enable you to transparently read or write ZIP/TAR.GZ compressed archives and the files inside them. + +- Features: + - Add file or directory from everywhere to archive, no one-to-one limitation. + - Extract part of entries, not all at once. + - Stream data directly into `io.Writer` without any file system storage. + +### Test cases and Coverage + +All subpackages use [GoConvey](http://goconvey.co/) to write test cases, and coverage is more than 80 percent. + +### Use cases + +- [Gogs](https://github.com/gogits/gogs): self hosted Git service in the Go Programming Language. +- [GoBlog](https://github.com/fuxiaohei/GoBlog): personal blogging application. +- [GoBuild](https://github.com/shxsun/gobuild/): online Go cross-platform compilation and download service. + +## License + +This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text. \ No newline at end of file diff --git a/vendor/github.com/Unknwon/cae/README_ZH.md b/vendor/github.com/Unknwon/cae/README_ZH.md new file mode 100644 index 0000000000..e2f8747ee4 --- /dev/null +++ b/vendor/github.com/Unknwon/cae/README_ZH.md @@ -0,0 +1,29 @@ +压缩与打包扩展 +============= + +[![Go Walker](http://gowalker.org/api/v1/badge)](http://gowalker.org/github.com/Unknwon/cae) + +包 cae 实现了 PHP 风格的压缩与打包扩展。 + +但本包依据 Go 语言的风格进行了一些修改。 + +引用:[PHP:Compression and Archive Extensions](http://www.php.net/manual/en/refs.compression.php) + +编码规范:基于 [Go 编码规范](https://github.com/Unknwon/go-code-convention) + +### 实现 + +包 `zip`([Go Walker](http://gowalker.org/github.com/Unknwon/cae/zip)) 和 `tz`([Go Walker](http://gowalker.org/github.com/Unknwon/cae/tz)) 都允许你轻易的读取或写入 ZIP/TAR.GZ 压缩档案和其内部文件。 + +- 特性: + - 将任意位置的文件或目录加入档案,没有一对一的操作限制。 + - 只解压部分文件,而非一次性解压全部。 + - 将数据以流的形式直接写入 `io.Writer` 而不需经过文件系统的存储。 + +### 测试用例与覆盖率 + +所有子包均采用 [GoConvey](http://goconvey.co/) 来书写测试用例,覆盖率均超过 80%。 + +## 授权许可 + +本项目采用 Apache v2 开源授权许可证,完整的授权说明已放置在 [LICENSE](LICENSE) 文件中。 \ No newline at end of file diff --git a/vendor/github.com/Unknwon/cae/tz/testdata/test.lnk b/vendor/github.com/Unknwon/cae/tz/testdata/test.lnk deleted file mode 120000 index b317dc9d26..0000000000 --- a/vendor/github.com/Unknwon/cae/tz/testdata/test.lnk +++ /dev/null @@ -1 +0,0 @@ -test.zip \ No newline at end of file diff --git a/vendor/github.com/Unknwon/cae/tz/testdata/testdir.lnk b/vendor/github.com/Unknwon/cae/tz/testdata/testdir.lnk deleted file mode 120000 index 9f6260d6f5..0000000000 --- a/vendor/github.com/Unknwon/cae/tz/testdata/testdir.lnk +++ /dev/null @@ -1 +0,0 @@ -testdir \ No newline at end of file diff --git a/vendor/github.com/Unknwon/cae/zip/testdata/test.lnk b/vendor/github.com/Unknwon/cae/zip/testdata/test.lnk deleted file mode 120000 index b317dc9d26..0000000000 --- a/vendor/github.com/Unknwon/cae/zip/testdata/test.lnk +++ /dev/null @@ -1 +0,0 @@ -test.zip \ No newline at end of file diff --git a/vendor/github.com/Unknwon/cae/zip/testdata/testdir.lnk b/vendor/github.com/Unknwon/cae/zip/testdata/testdir.lnk deleted file mode 120000 index 9f6260d6f5..0000000000 --- a/vendor/github.com/Unknwon/cae/zip/testdata/testdir.lnk +++ /dev/null @@ -1 +0,0 @@ -testdir \ No newline at end of file diff --git a/vendor/github.com/Unknwon/com/.gitignore b/vendor/github.com/Unknwon/com/.gitignore new file mode 100644 index 0000000000..0da157fe9c --- /dev/null +++ b/vendor/github.com/Unknwon/com/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test +.idea + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.iml diff --git a/vendor/github.com/Unknwon/com/.travis.yml b/vendor/github.com/Unknwon/com/.travis.yml new file mode 100644 index 0000000000..882eb2d122 --- /dev/null +++ b/vendor/github.com/Unknwon/com/.travis.yml @@ -0,0 +1,13 @@ +language: go + +go: + - 1.2 + - 1.3 + - 1.4 + - tip + +install: go get -v -t + +notifications: + email: + - u@gogs.io \ No newline at end of file diff --git a/vendor/github.com/Unknwon/com/README.md b/vendor/github.com/Unknwon/com/README.md new file mode 100644 index 0000000000..8d821abd65 --- /dev/null +++ b/vendor/github.com/Unknwon/com/README.md @@ -0,0 +1,20 @@ +Common Functions +================ + +[![Build Status](https://travis-ci.org/Unknwon/com.svg)](https://travis-ci.org/Unknwon/com) [![Go Walker](http://gowalker.org/api/v1/badge)](http://gowalker.org/github.com/Unknwon/com) + +This is an open source project for commonly used functions for the Go programming language. + +This package need >= **go 1.2** + +Code Convention: based on [Go Code Convention](https://github.com/Unknwon/go-code-convention). + +## Contribute + +Your contribute is welcome, but you have to check following steps after you added some functions and commit them: + +1. Make sure you wrote user-friendly comments for **all functions** . +2. Make sure you wrote test cases with any possible condition for **all functions** in file `*_test.go`. +3. Make sure you wrote benchmarks for **all functions** in file `*_test.go`. +4. Make sure you wrote useful examples for **all functions** in file `example_test.go`. +5. Make sure you ran `go test` and got **PASS** . diff --git a/vendor/github.com/Unknwon/i18n/.gitignore b/vendor/github.com/Unknwon/i18n/.gitignore new file mode 100644 index 0000000000..00268614f0 --- /dev/null +++ b/vendor/github.com/Unknwon/i18n/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/Unknwon/i18n/Makefile b/vendor/github.com/Unknwon/i18n/Makefile new file mode 100644 index 0000000000..8ff1ac4399 --- /dev/null +++ b/vendor/github.com/Unknwon/i18n/Makefile @@ -0,0 +1,12 @@ +.PHONY: build test bench vet + +build: vet bench + +test: + go test -v -cover + +bench: + go test -v -cover -test.bench=. -test.benchmem + +vet: + go vet \ No newline at end of file diff --git a/vendor/github.com/Unknwon/i18n/README.md b/vendor/github.com/Unknwon/i18n/README.md new file mode 100644 index 0000000000..7503e41f28 --- /dev/null +++ b/vendor/github.com/Unknwon/i18n/README.md @@ -0,0 +1,136 @@ +i18n [![GoDoc](https://godoc.org/github.com/Unknwon/i18n?status.svg)](https://godoc.org/github.com/Unknwon/i18n) [![Sourcegraph](https://sourcegraph.com/github.com/Unknwon/i18n/-/badge.svg)](https://sourcegraph.com/github.com/Unknwon/i18n?badge) +==== + +Package i18n is for app Internationalization and Localization. + +## Introduction + +This package provides multiple-language options to improve user experience. Sites like [Go Walker](http://gowalker.org) and [gogs.io](http://gogs.io) are using this module to implement Chinese and English user interfaces. + +You can use following command to install this module: + + go get github.com/Unknwon/i18n + +## Usage + +First of all, you have to import this package: + +```go +import "github.com/Unknwon/i18n" +``` + +The format of locale files is very like INI format configuration file, which is basically key-value pairs. But this module has some improvements. Every language corresponding to a locale file, for example, under `conf/locale` folder of [gogsweb](https://github.com/gogits/gogsweb/tree/master/conf/locale), there are two files called `locale_en-US.ini` and `locale_zh-CN.ini`. + +The name and extensions of locale files can be anything, but we strongly recommend you to follow the style of gogsweb. + +## Minimal example + +Here are two simplest locale file examples: + +File `locale_en-US.ini`: + +```ini +hi = hello, %s +bye = goodbye +``` + +File `locale_zh-CN.ini`: + +```ini +hi = 您好,%s +bye = 再见 +``` + +### Do Translation + +There are two ways to do translation depends on which way is the best fit for your application or framework. + +Directly use package function to translate: + +```go +i18n.Tr("en-US", "hi", "Unknwon") +i18n.Tr("en-US", "bye") +``` + +Or create a struct and embed it: + +```go +type MyController struct{ + // ...other fields + i18n.Locale +} + +//... + +func ... { + c := &MyController{ + Locale: i18n.Locale{"en-US"}, + } + _ = c.Tr("hi", "Unknwon") + _ = c.Tr("bye") +} +``` + +Code above will produce correspondingly: + +- English `en-US`:`hello, Unknwon`, `goodbye` +- Chinese `zh-CN`:`您好,Unknwon`, `再见` + +## Section + +For different pages, one key may map to different values. Therefore, i18n module also uses the section feature of INI format configuration to achieve section. + +For example, the key name is `about`, and we want to show `About` in the home page and `About Us` in about page. Then you can do following: + +Content in locale file: + +```ini +about = About + +[about] +about = About Us +``` + +Get `about` in home page: + +```go +i18n.Tr("en-US", "about") +``` + +Get `about` in about page: + +```go +i18n.Tr("en-US", "about.about") +``` + +### Ambiguity + +Because dot `.` is sign of section in both [INI parser](https://github.com/go-ini/ini) and locale files, so when your key name contains `.` will cause ambiguity. At this point, you just need to add one more `.` in front of the key. + +For example, the key name is `about.`, then we can use: + +```go +i18n.Tr("en-US", ".about.") +``` + +to get expect result. + +## Helper tool + +Module i18n provides a command line helper tool beei18n for simplify steps of your development. You can install it as follows: + + go get github.com/Unknwon/i18n/ui18n + +### Sync locale files + +Command `sync` allows you use a exist local file as the template to create or sync other locale files: + + ui18n sync srouce_file.ini other1.ini other2.ini + +This command can operate 1 or more files in one command. + +## More information + +- The first locale you load to the module is considered as **default locale**. +- When matching non-default locale and didn't find the string, i18n will have a second try on default locale. +- If i18n still cannot find string in the default locale, raw string will be returned. For instance, when the string is `hi` and it does not exist in locale file, simply return `hi` as output. diff --git a/vendor/github.com/Unknwon/paginater/.gitignore b/vendor/github.com/Unknwon/paginater/.gitignore new file mode 100644 index 0000000000..e947a9a78b --- /dev/null +++ b/vendor/github.com/Unknwon/paginater/.gitignore @@ -0,0 +1,26 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof +paginater.sublime-project +paginater.sublime-workspace diff --git a/vendor/github.com/Unknwon/paginater/README.md b/vendor/github.com/Unknwon/paginater/README.md new file mode 100644 index 0000000000..8e608ed3ea --- /dev/null +++ b/vendor/github.com/Unknwon/paginater/README.md @@ -0,0 +1,65 @@ +Paginater [![Build Status](https://drone.io/github.com/Unknwon/paginater/status.png)](https://drone.io/github.com/Unknwon/paginater/latest) [![](http://gocover.io/_badge/github.com/Unknwon/paginater)](http://gocover.io/github.com/Unknwon/paginater) +========= + +Package paginater is a helper module for custom pagination calculation. + +## Installation + + go get github.com/Unknwon/paginater + +## Getting Started + +The following code shows an example of how to use paginater: + +```go +package main + +import "github.com/Unknwon/paginater" + +func main() { + // Arguments: + // - Total number of rows + // - Number of rows in one page + // - Current page number + // - Number of page links + p := paginater.New(45, 10, 3, 3) + + // Then use p as a template object named "Page" in "demo.html" + // ... +} +``` + +`demo.html` + +```html +{{if not .Page.IsFirst}}[First](1){{end}} +{{if .Page.HasPrevious}}[Previous]({{.Page.Previous}}){{end}} + +{{range .Page.Pages}} + {{if eq .Num -1}} + ... + {{else}} + {{.Num}}{{if .IsCurrent}}(current){{end}} + {{end}} +{{end}} + +{{if .Page.HasNext}}[Next]({{.Page.Next}}){{end}} +{{if not .Page.IsLast}}[Last]({{.Page.TotalPages}}){{end}} +``` + +Possible output: + +``` +[First](1) [Previous](2) ... 2 3(current) 4 ... [Next](4) [Last](5) +``` + +As you may guess, if the `Page` value is `-1`, you should print `...` in the HTML as common practice. + +## Getting Help + +- [API Documentation](https://gowalker.org/github.com/Unknwon/paginater) +- [File An Issue](https://github.com/Unknwon/paginater/issues/new) + +## License + +This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text. \ No newline at end of file diff --git a/vendor/github.com/andybalholm/cascadia/.travis.yml b/vendor/github.com/andybalholm/cascadia/.travis.yml new file mode 100644 index 0000000000..6f227517d6 --- /dev/null +++ b/vendor/github.com/andybalholm/cascadia/.travis.yml @@ -0,0 +1,14 @@ +language: go + +go: + - 1.3 + - 1.4 + +install: + - go get github.com/andybalholm/cascadia + +script: + - go test -v + +notifications: + email: false diff --git a/vendor/github.com/andybalholm/cascadia/LICENSE b/vendor/github.com/andybalholm/cascadia/LICENSE old mode 100755 new mode 100644 diff --git a/vendor/github.com/andybalholm/cascadia/README.md b/vendor/github.com/andybalholm/cascadia/README.md new file mode 100644 index 0000000000..9021cb92aa --- /dev/null +++ b/vendor/github.com/andybalholm/cascadia/README.md @@ -0,0 +1,7 @@ +# cascadia + +[![](https://travis-ci.org/andybalholm/cascadia.svg)](https://travis-ci.org/andybalholm/cascadia) + +The Cascadia package implements CSS selectors for use with the parse trees produced by the html package. + +To test CSS selectors without writing Go code, check out [cascadia](https://github.com/suntong/cascadia) the command line tool, a thin wrapper around this package. diff --git a/vendor/github.com/beorn7/perks/quantile/exampledata.txt b/vendor/github.com/beorn7/perks/quantile/exampledata.txt new file mode 100644 index 0000000000..1602287d7c --- /dev/null +++ b/vendor/github.com/beorn7/perks/quantile/exampledata.txt @@ -0,0 +1,2388 @@ +8 +5 +26 +12 +5 +235 +13 +6 +28 +30 +3 +3 +3 +3 +5 +2 +33 +7 +2 +4 +7 +12 +14 +5 +8 +3 +10 +4 +5 +3 +6 +6 +209 +20 +3 +10 +14 +3 +4 +6 +8 +5 +11 +7 +3 +2 +3 +3 +212 +5 +222 +4 +10 +10 +5 +6 +3 +8 +3 +10 +254 +220 +2 +3 +5 +24 +5 +4 +222 +7 +3 +3 +223 +8 +15 +12 +14 +14 +3 +2 +2 +3 +13 +3 +11 +4 +4 +6 +5 +7 +13 +5 +3 +5 +2 +5 +3 +5 +2 +7 +15 +17 +14 +3 +6 +6 +3 +17 +5 +4 +7 +6 +4 +4 +8 +6 +8 +3 +9 +3 +6 +3 +4 +5 +3 +3 +660 +4 +6 +10 +3 +6 +3 +2 +5 +13 +2 +4 +4 +10 +4 +8 +4 +3 +7 +9 +9 +3 +10 +37 +3 +13 +4 +12 +3 +6 +10 +8 +5 +21 +2 +3 +8 +3 +2 +3 +3 +4 +12 +2 +4 +8 +8 +4 +3 +2 +20 +1 +6 +32 +2 +11 +6 +18 +3 +8 +11 +3 +212 +3 +4 +2 +6 +7 +12 +11 +3 +2 +16 +10 +6 +4 +6 +3 +2 +7 +3 +2 +2 +2 +2 +5 +6 +4 +3 +10 +3 +4 +6 +5 +3 +4 +4 +5 +6 +4 +3 +4 +4 +5 +7 +5 +5 +3 +2 +7 +2 +4 +12 +4 +5 +6 +2 +4 +4 +8 +4 +15 +13 +7 +16 +5 +3 +23 +5 +5 +7 +3 +2 +9 +8 +7 +5 +8 +11 +4 +10 +76 +4 +47 +4 +3 +2 +7 +4 +2 +3 +37 +10 +4 +2 +20 +5 +4 +4 +10 +10 +4 +3 +7 +23 +240 +7 +13 +5 +5 +3 +3 +2 +5 +4 +2 +8 +7 +19 +2 +23 +8 +7 +2 +5 +3 +8 +3 +8 +13 +5 +5 +5 +2 +3 +23 +4 +9 +8 +4 +3 +3 +5 +220 +2 +3 +4 +6 +14 +3 +53 +6 +2 +5 +18 +6 +3 +219 +6 +5 +2 +5 +3 +6 +5 +15 +4 +3 +17 +3 +2 +4 +7 +2 +3 +3 +4 +4 +3 +2 +664 +6 +3 +23 +5 +5 +16 +5 +8 +2 +4 +2 +24 +12 +3 +2 +3 +5 +8 +3 +5 +4 +3 +14 +3 +5 +8 +2 +3 +7 +9 +4 +2 +3 +6 +8 +4 +3 +4 +6 +5 +3 +3 +6 +3 +19 +4 +4 +6 +3 +6 +3 +5 +22 +5 +4 +4 +3 +8 +11 +4 +9 +7 +6 +13 +4 +4 +4 +6 +17 +9 +3 +3 +3 +4 +3 +221 +5 +11 +3 +4 +2 +12 +6 +3 +5 +7 +5 +7 +4 +9 +7 +14 +37 +19 +217 +16 +3 +5 +2 +2 +7 +19 +7 +6 +7 +4 +24 +5 +11 +4 +7 +7 +9 +13 +3 +4 +3 +6 +28 +4 +4 +5 +5 +2 +5 +6 +4 +4 +6 +10 +5 +4 +3 +2 +3 +3 +6 +5 +5 +4 +3 +2 +3 +7 +4 +6 +18 +16 +8 +16 +4 +5 +8 +6 +9 +13 +1545 +6 +215 +6 +5 +6 +3 +45 +31 +5 +2 +2 +4 +3 +3 +2 +5 +4 +3 +5 +7 +7 +4 +5 +8 +5 +4 +749 +2 +31 +9 +11 +2 +11 +5 +4 +4 +7 +9 +11 +4 +5 +4 +7 +3 +4 +6 +2 +15 +3 +4 +3 +4 +3 +5 +2 +13 +5 +5 +3 +3 +23 +4 +4 +5 +7 +4 +13 +2 +4 +3 +4 +2 +6 +2 +7 +3 +5 +5 +3 +29 +5 +4 +4 +3 +10 +2 +3 +79 +16 +6 +6 +7 +7 +3 +5 +5 +7 +4 +3 +7 +9 +5 +6 +5 +9 +6 +3 +6 +4 +17 +2 +10 +9 +3 +6 +2 +3 +21 +22 +5 +11 +4 +2 +17 +2 +224 +2 +14 +3 +4 +4 +2 +4 +4 +4 +4 +5 +3 +4 +4 +10 +2 +6 +3 +3 +5 +7 +2 +7 +5 +6 +3 +218 +2 +2 +5 +2 +6 +3 +5 +222 +14 +6 +33 +3 +2 +5 +3 +3 +3 +9 +5 +3 +3 +2 +7 +4 +3 +4 +3 +5 +6 +5 +26 +4 +13 +9 +7 +3 +221 +3 +3 +4 +4 +4 +4 +2 +18 +5 +3 +7 +9 +6 +8 +3 +10 +3 +11 +9 +5 +4 +17 +5 +5 +6 +6 +3 +2 +4 +12 +17 +6 +7 +218 +4 +2 +4 +10 +3 +5 +15 +3 +9 +4 +3 +3 +6 +29 +3 +3 +4 +5 +5 +3 +8 +5 +6 +6 +7 +5 +3 +5 +3 +29 +2 +31 +5 +15 +24 +16 +5 +207 +4 +3 +3 +2 +15 +4 +4 +13 +5 +5 +4 +6 +10 +2 +7 +8 +4 +6 +20 +5 +3 +4 +3 +12 +12 +5 +17 +7 +3 +3 +3 +6 +10 +3 +5 +25 +80 +4 +9 +3 +2 +11 +3 +3 +2 +3 +8 +7 +5 +5 +19 +5 +3 +3 +12 +11 +2 +6 +5 +5 +5 +3 +3 +3 +4 +209 +14 +3 +2 +5 +19 +4 +4 +3 +4 +14 +5 +6 +4 +13 +9 +7 +4 +7 +10 +2 +9 +5 +7 +2 +8 +4 +6 +5 +5 +222 +8 +7 +12 +5 +216 +3 +4 +4 +6 +3 +14 +8 +7 +13 +4 +3 +3 +3 +3 +17 +5 +4 +3 +33 +6 +6 +33 +7 +5 +3 +8 +7 +5 +2 +9 +4 +2 +233 +24 +7 +4 +8 +10 +3 +4 +15 +2 +16 +3 +3 +13 +12 +7 +5 +4 +207 +4 +2 +4 +27 +15 +2 +5 +2 +25 +6 +5 +5 +6 +13 +6 +18 +6 +4 +12 +225 +10 +7 +5 +2 +2 +11 +4 +14 +21 +8 +10 +3 +5 +4 +232 +2 +5 +5 +3 +7 +17 +11 +6 +6 +23 +4 +6 +3 +5 +4 +2 +17 +3 +6 +5 +8 +3 +2 +2 +14 +9 +4 +4 +2 +5 +5 +3 +7 +6 +12 +6 +10 +3 +6 +2 +2 +19 +5 +4 +4 +9 +2 +4 +13 +3 +5 +6 +3 +6 +5 +4 +9 +6 +3 +5 +7 +3 +6 +6 +4 +3 +10 +6 +3 +221 +3 +5 +3 +6 +4 +8 +5 +3 +6 +4 +4 +2 +54 +5 +6 +11 +3 +3 +4 +4 +4 +3 +7 +3 +11 +11 +7 +10 +6 +13 +223 +213 +15 +231 +7 +3 +7 +228 +2 +3 +4 +4 +5 +6 +7 +4 +13 +3 +4 +5 +3 +6 +4 +6 +7 +2 +4 +3 +4 +3 +3 +6 +3 +7 +3 +5 +18 +5 +6 +8 +10 +3 +3 +3 +2 +4 +2 +4 +4 +5 +6 +6 +4 +10 +13 +3 +12 +5 +12 +16 +8 +4 +19 +11 +2 +4 +5 +6 +8 +5 +6 +4 +18 +10 +4 +2 +216 +6 +6 +6 +2 +4 +12 +8 +3 +11 +5 +6 +14 +5 +3 +13 +4 +5 +4 +5 +3 +28 +6 +3 +7 +219 +3 +9 +7 +3 +10 +6 +3 +4 +19 +5 +7 +11 +6 +15 +19 +4 +13 +11 +3 +7 +5 +10 +2 +8 +11 +2 +6 +4 +6 +24 +6 +3 +3 +3 +3 +6 +18 +4 +11 +4 +2 +5 +10 +8 +3 +9 +5 +3 +4 +5 +6 +2 +5 +7 +4 +4 +14 +6 +4 +4 +5 +5 +7 +2 +4 +3 +7 +3 +3 +6 +4 +5 +4 +4 +4 +3 +3 +3 +3 +8 +14 +2 +3 +5 +3 +2 +4 +5 +3 +7 +3 +3 +18 +3 +4 +4 +5 +7 +3 +3 +3 +13 +5 +4 +8 +211 +5 +5 +3 +5 +2 +5 +4 +2 +655 +6 +3 +5 +11 +2 +5 +3 +12 +9 +15 +11 +5 +12 +217 +2 +6 +17 +3 +3 +207 +5 +5 +4 +5 +9 +3 +2 +8 +5 +4 +3 +2 +5 +12 +4 +14 +5 +4 +2 +13 +5 +8 +4 +225 +4 +3 +4 +5 +4 +3 +3 +6 +23 +9 +2 +6 +7 +233 +4 +4 +6 +18 +3 +4 +6 +3 +4 +4 +2 +3 +7 +4 +13 +227 +4 +3 +5 +4 +2 +12 +9 +17 +3 +7 +14 +6 +4 +5 +21 +4 +8 +9 +2 +9 +25 +16 +3 +6 +4 +7 +8 +5 +2 +3 +5 +4 +3 +3 +5 +3 +3 +3 +2 +3 +19 +2 +4 +3 +4 +2 +3 +4 +4 +2 +4 +3 +3 +3 +2 +6 +3 +17 +5 +6 +4 +3 +13 +5 +3 +3 +3 +4 +9 +4 +2 +14 +12 +4 +5 +24 +4 +3 +37 +12 +11 +21 +3 +4 +3 +13 +4 +2 +3 +15 +4 +11 +4 +4 +3 +8 +3 +4 +4 +12 +8 +5 +3 +3 +4 +2 +220 +3 +5 +223 +3 +3 +3 +10 +3 +15 +4 +241 +9 +7 +3 +6 +6 +23 +4 +13 +7 +3 +4 +7 +4 +9 +3 +3 +4 +10 +5 +5 +1 +5 +24 +2 +4 +5 +5 +6 +14 +3 +8 +2 +3 +5 +13 +13 +3 +5 +2 +3 +15 +3 +4 +2 +10 +4 +4 +4 +5 +5 +3 +5 +3 +4 +7 +4 +27 +3 +6 +4 +15 +3 +5 +6 +6 +5 +4 +8 +3 +9 +2 +6 +3 +4 +3 +7 +4 +18 +3 +11 +3 +3 +8 +9 +7 +24 +3 +219 +7 +10 +4 +5 +9 +12 +2 +5 +4 +4 +4 +3 +3 +19 +5 +8 +16 +8 +6 +22 +3 +23 +3 +242 +9 +4 +3 +3 +5 +7 +3 +3 +5 +8 +3 +7 +5 +14 +8 +10 +3 +4 +3 +7 +4 +6 +7 +4 +10 +4 +3 +11 +3 +7 +10 +3 +13 +6 +8 +12 +10 +5 +7 +9 +3 +4 +7 +7 +10 +8 +30 +9 +19 +4 +3 +19 +15 +4 +13 +3 +215 +223 +4 +7 +4 +8 +17 +16 +3 +7 +6 +5 +5 +4 +12 +3 +7 +4 +4 +13 +4 +5 +2 +5 +6 +5 +6 +6 +7 +10 +18 +23 +9 +3 +3 +6 +5 +2 +4 +2 +7 +3 +3 +2 +5 +5 +14 +10 +224 +6 +3 +4 +3 +7 +5 +9 +3 +6 +4 +2 +5 +11 +4 +3 +3 +2 +8 +4 +7 +4 +10 +7 +3 +3 +18 +18 +17 +3 +3 +3 +4 +5 +3 +3 +4 +12 +7 +3 +11 +13 +5 +4 +7 +13 +5 +4 +11 +3 +12 +3 +6 +4 +4 +21 +4 +6 +9 +5 +3 +10 +8 +4 +6 +4 +4 +6 +5 +4 +8 +6 +4 +6 +4 +4 +5 +9 +6 +3 +4 +2 +9 +3 +18 +2 +4 +3 +13 +3 +6 +6 +8 +7 +9 +3 +2 +16 +3 +4 +6 +3 +2 +33 +22 +14 +4 +9 +12 +4 +5 +6 +3 +23 +9 +4 +3 +5 +5 +3 +4 +5 +3 +5 +3 +10 +4 +5 +5 +8 +4 +4 +6 +8 +5 +4 +3 +4 +6 +3 +3 +3 +5 +9 +12 +6 +5 +9 +3 +5 +3 +2 +2 +2 +18 +3 +2 +21 +2 +5 +4 +6 +4 +5 +10 +3 +9 +3 +2 +10 +7 +3 +6 +6 +4 +4 +8 +12 +7 +3 +7 +3 +3 +9 +3 +4 +5 +4 +4 +5 +5 +10 +15 +4 +4 +14 +6 +227 +3 +14 +5 +216 +22 +5 +4 +2 +2 +6 +3 +4 +2 +9 +9 +4 +3 +28 +13 +11 +4 +5 +3 +3 +2 +3 +3 +5 +3 +4 +3 +5 +23 +26 +3 +4 +5 +6 +4 +6 +3 +5 +5 +3 +4 +3 +2 +2 +2 +7 +14 +3 +6 +7 +17 +2 +2 +15 +14 +16 +4 +6 +7 +13 +6 +4 +5 +6 +16 +3 +3 +28 +3 +6 +15 +3 +9 +2 +4 +6 +3 +3 +22 +4 +12 +6 +7 +2 +5 +4 +10 +3 +16 +6 +9 +2 +5 +12 +7 +5 +5 +5 +5 +2 +11 +9 +17 +4 +3 +11 +7 +3 +5 +15 +4 +3 +4 +211 +8 +7 +5 +4 +7 +6 +7 +6 +3 +6 +5 +6 +5 +3 +4 +4 +26 +4 +6 +10 +4 +4 +3 +2 +3 +3 +4 +5 +9 +3 +9 +4 +4 +5 +5 +8 +2 +4 +2 +3 +8 +4 +11 +19 +5 +8 +6 +3 +5 +6 +12 +3 +2 +4 +16 +12 +3 +4 +4 +8 +6 +5 +6 +6 +219 +8 +222 +6 +16 +3 +13 +19 +5 +4 +3 +11 +6 +10 +4 +7 +7 +12 +5 +3 +3 +5 +6 +10 +3 +8 +2 +5 +4 +7 +2 +4 +4 +2 +12 +9 +6 +4 +2 +40 +2 +4 +10 +4 +223 +4 +2 +20 +6 +7 +24 +5 +4 +5 +2 +20 +16 +6 +5 +13 +2 +3 +3 +19 +3 +2 +4 +5 +6 +7 +11 +12 +5 +6 +7 +7 +3 +5 +3 +5 +3 +14 +3 +4 +4 +2 +11 +1 +7 +3 +9 +6 +11 +12 +5 +8 +6 +221 +4 +2 +12 +4 +3 +15 +4 +5 +226 +7 +218 +7 +5 +4 +5 +18 +4 +5 +9 +4 +4 +2 +9 +18 +18 +9 +5 +6 +6 +3 +3 +7 +3 +5 +4 +4 +4 +12 +3 +6 +31 +5 +4 +7 +3 +6 +5 +6 +5 +11 +2 +2 +11 +11 +6 +7 +5 +8 +7 +10 +5 +23 +7 +4 +3 +5 +34 +2 +5 +23 +7 +3 +6 +8 +4 +4 +4 +2 +5 +3 +8 +5 +4 +8 +25 +2 +3 +17 +8 +3 +4 +8 +7 +3 +15 +6 +5 +7 +21 +9 +5 +6 +6 +5 +3 +2 +3 +10 +3 +6 +3 +14 +7 +4 +4 +8 +7 +8 +2 +6 +12 +4 +213 +6 +5 +21 +8 +2 +5 +23 +3 +11 +2 +3 +6 +25 +2 +3 +6 +7 +6 +6 +4 +4 +6 +3 +17 +9 +7 +6 +4 +3 +10 +7 +2 +3 +3 +3 +11 +8 +3 +7 +6 +4 +14 +36 +3 +4 +3 +3 +22 +13 +21 +4 +2 +7 +4 +4 +17 +15 +3 +7 +11 +2 +4 +7 +6 +209 +6 +3 +2 +2 +24 +4 +9 +4 +3 +3 +3 +29 +2 +2 +4 +3 +3 +5 +4 +6 +3 +3 +2 +4 diff --git a/vendor/github.com/blevesearch/bleve/.gitignore b/vendor/github.com/blevesearch/bleve/.gitignore new file mode 100644 index 0000000000..ab7a1e21a6 --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/.gitignore @@ -0,0 +1,19 @@ +#* +*.sublime-* +*~ +.#* +.project +.settings +**/.idea/ +**/*.iml +.DS_Store +query_string.y.go.tmp +/analysis/token_filters/cld2/cld2-read-only +/analysis/token_filters/cld2/libcld2_full.a +/cmd/bleve/bleve +vendor/** +!vendor/manifest +/y.output +/search/query/y.output +*.test +tags diff --git a/vendor/github.com/blevesearch/bleve/.travis.yml b/vendor/github.com/blevesearch/bleve/.travis.yml new file mode 100644 index 0000000000..35f7b60f23 --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/.travis.yml @@ -0,0 +1,24 @@ +sudo: false + +language: go + +go: + - "1.9.x" + - "1.10.x" + - "1.11.x" + +script: + - go get golang.org/x/tools/cmd/cover + - go get github.com/mattn/goveralls + - go get github.com/kisielk/errcheck + - go get -u github.com/FiloSottile/gvt + - gvt restore + - go test -race -v $(go list ./... | grep -v vendor/) + - go vet $(go list ./... | grep -v vendor/) + - errcheck -ignorepkg fmt $(go list ./... | grep -v vendor/) + - docs/project-code-coverage.sh + - docs/build_children.sh + +notifications: + email: + - marty.schoch@gmail.com diff --git a/vendor/github.com/blevesearch/bleve/CONTRIBUTING.md b/vendor/github.com/blevesearch/bleve/CONTRIBUTING.md new file mode 100644 index 0000000000..5ebf3d65bc --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/CONTRIBUTING.md @@ -0,0 +1,16 @@ +# Contributing to Bleve + +We look forward to your contributions, but ask that you first review these guidelines. + +### Sign the CLA + +As Bleve is a Couchbase project we require contributors accept the [Couchbase Contributor License Agreement](http://review.couchbase.org/static/individual_agreement.html). To sign this agreement log into the Couchbase [code review tool](http://review.couchbase.org/). The Bleve project does not use this code review tool but it is still used to track acceptance of the contributor license agreements. + +### Submitting a Pull Request + +All types of contributions are welcome, but please keep the following in mind: + +- If you're planning a large change, you should really discuss it in a github issue or on the google group first. This helps avoid duplicate effort and spending time on something that may not be merged. +- Existing tests should continue to pass, new tests for the contribution are nice to have. +- All code should have gone through `go fmt` +- All code should pass `go vet` diff --git a/vendor/github.com/blevesearch/bleve/README.md b/vendor/github.com/blevesearch/bleve/README.md new file mode 100644 index 0000000000..7c1a7c7c46 --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/README.md @@ -0,0 +1,67 @@ +# ![bleve](docs/bleve.png) bleve + +[![Build Status](https://travis-ci.org/blevesearch/bleve.svg?branch=master)](https://travis-ci.org/blevesearch/bleve) [![Coverage Status](https://coveralls.io/repos/github/blevesearch/bleve/badge.svg?branch=master)](https://coveralls.io/github/blevesearch/bleve?branch=master) [![GoDoc](https://godoc.org/github.com/blevesearch/bleve?status.svg)](https://godoc.org/github.com/blevesearch/bleve) +[![Join the chat at https://gitter.im/blevesearch/bleve](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/blevesearch/bleve?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![codebeat](https://codebeat.co/badges/38a7cbc9-9cf5-41c0-a315-0746178230f4)](https://codebeat.co/projects/github-com-blevesearch-bleve) +[![Go Report Card](https://goreportcard.com/badge/blevesearch/bleve)](https://goreportcard.com/report/blevesearch/bleve) +[![Sourcegraph](https://sourcegraph.com/github.com/blevesearch/bleve/-/badge.svg)](https://sourcegraph.com/github.com/blevesearch/bleve?badge) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) + +modern text indexing in go - [blevesearch.com](http://www.blevesearch.com/) + +Try out bleve live by [searching the bleve website](http://www.blevesearch.com/search/?q=bleve). + +## Features + +* Index any go data structure (including JSON) +* Intelligent defaults backed up by powerful configuration +* Supported field types: + * Text, Numeric, Date +* Supported query types: + * Term, Phrase, Match, Match Phrase, Prefix + * Conjunction, Disjunction, Boolean + * Numeric Range, Date Range + * Simple query [syntax](http://www.blevesearch.com/docs/Query-String-Query/) for human entry +* tf-idf Scoring +* Search result match highlighting +* Supports Aggregating Facets: + * Terms Facet + * Numeric Range Facet + * Date Range Facet + +## Discussion + +Discuss usage and development of bleve in the [google group](https://groups.google.com/forum/#!forum/bleve). + +## Indexing + +```go +message := struct{ + Id string + From string + Body string +}{ + Id: "example", + From: "marty.schoch@gmail.com", + Body: "bleve indexing is easy", +} + +mapping := bleve.NewIndexMapping() +index, err := bleve.New("example.bleve", mapping) +if err != nil { + panic(err) +} +index.Index(message.Id, message) +``` + +## Querying + +```go +index, _ := bleve.Open("example.bleve") +query := bleve.NewQueryStringQuery("bleve") +searchRequest := bleve.NewSearchRequest(query) +searchResult, _ := index.Search(searchRequest) +``` + +## License + +Apache License Version 2.0 diff --git a/vendor/github.com/blevesearch/bleve/analysis/test_words.txt b/vendor/github.com/blevesearch/bleve/analysis/test_words.txt new file mode 100644 index 0000000000..b86e254bb9 --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/analysis/test_words.txt @@ -0,0 +1,7 @@ +# full line comment +marty +steve # trailing comment +| different format of comment +dustin +siri | different style trailing comment +multiple words with different whitespace \ No newline at end of file diff --git a/vendor/github.com/blevesearch/bleve/geo/README.md b/vendor/github.com/blevesearch/bleve/geo/README.md new file mode 100644 index 0000000000..43bcd98fed --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/geo/README.md @@ -0,0 +1,9 @@ +# geo support in bleve + +First, all of this geo code is a Go adaptation of the [Lucene 5.3.2 sandbox geo support](https://lucene.apache.org/core/5_3_2/sandbox/org/apache/lucene/util/package-summary.html). + +## Notes + +- All of the APIs will use float64 for lon/lat values. +- When describing a point in function arguments or return values, we always use the order lon, lat. +- High level APIs will use TopLeft and BottomRight to describe bounding boxes. This may not map cleanly to min/max lon/lat when crossing the dateline. The lower level APIs will use min/max lon/lat and require the higher-level code to split boxes accordingly. diff --git a/vendor/github.com/blevesearch/bleve/index/scorch/README.md b/vendor/github.com/blevesearch/bleve/index/scorch/README.md new file mode 100644 index 0000000000..9794aed707 --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/index/scorch/README.md @@ -0,0 +1,367 @@ +# scorch + +## Definitions + +Batch +- A collection of Documents to mutate in the index. + +Document +- Has a unique identifier (arbitrary bytes). +- Is comprised of a list of fields. + +Field +- Has a name (string). +- Has a type (text, number, date, geopoint). +- Has a value (depending on type). +- Can be indexed, stored, or both. +- If indexed, can be analyzed. +-m If indexed, can optionally store term vectors. + +## Scope + +Scorch *MUST* implement the bleve.index API without requiring any changes to this API. + +Scorch *MAY* introduce new interfaces, which can be discovered to allow use of new capabilities not in the current API. + +## Implementation + +The scorch implementation starts with the concept of a segmented index. + +A segment is simply a slice, subset, or portion of the entire index. A segmented index is one which is composed of one or more segments. Although segments are created in a particular order, knowing this ordering is not required to achieve correct semantics when querying. Because there is no ordering, this means that when searching an index, you can (and should) search all the segments concurrently. + +### Internal Wrapper + +In order to accommodate the existing APIs while also improving the implementation, the scorch implementation includes some wrapper functionality that must be described. + +#### \_id field + +In scorch, field 0 is prearranged to be named \_id. All documents have a value for this field, which is the documents external identifier. In this version the field *MUST* be both indexed AND stored. The scorch wrapper adds this field, as it will not be present in the Document from the calling bleve code. + +NOTE: If a document already contains a field \_id, it will be replaced. If this is problematic, the caller must ensure such a scenario does not happen. + +### Proposed Structures + +``` +type Segment interface { + + Dictionary(field string) TermDictionary + +} + +type TermDictionary interface { + + PostingsList(term string, excluding PostingsList) PostingsList + +} + +type PostingsList interface { + + Next() Posting + + And(other PostingsList) PostingsList + Or(other PostingsList) PostingsList + +} + +type Posting interface { + Number() uint64 + + Frequency() uint64 + Norm() float64 + + Locations() Locations +} + +type Locations interface { + Start() uint64 + End() uint64 + Pos() uint64 + ArrayPositions() ... +} + +type DeletedDocs { + +} + +type SegmentSnapshot struct { + segment Segment + deleted PostingsList +} + +type IndexSnapshot struct { + segment []SegmentSnapshot +} +``` +**What about errors?** +**What about memory mgmnt or context?** +**Postings List separate iterator to separate stateful from stateless** +### Mutating the Index + +The bleve.index API has methods for directly making individual mutations (Update/Delete/SetInternal/DeleteInternal), however for this first implementation, we assume that all of these calls can simply be turned into a Batch of size 1. This may be highly inefficient, but it will be correct. This decision is made based on the fact that Couchbase FTS always uses Batches. + +NOTE: As a side-effect of this decision, it should be clear that performance tuning may depend on the batch size, which may in-turn require changes in FTS. + +From this point forward, only Batch mutations will be discussed. + +Sequence of Operations: + +1. For each document in the batch, search through all existing segments. The goal is to build up a per-segment bitset which tells us which documents in that segment are obsoleted by the addition of the new segment we're currently building. NOTE: we're not ready for this change to take effect yet, so rather than this operation mutating anything, they simply return bitsets, which we can apply later. Logically, this is something like: + + ``` + foreach segment { + dict := segment.Dictionary("\_id") + postings := empty postings list + foreach docID { + postings = postings.Or(dict.PostingsList(docID, nil)) + } + } + ``` + + NOTE: it is illustrated above as nested for loops, but some or all of these could be concurrently. The end result is that for each segment, we have (possibly empty) bitset. + +2. Also concurrent with 1, the documents in the batch are analyzed. This analysis proceeds using the existing analyzer pool. + +3. (after 2 completes) Analyzed documents are fed into a function which builds a new Segment representing this information. + +4. We now have everything we need to update the state of the system to include this new snapshot. + + - Acquire a lock + - Create a new IndexSnapshot + - For each SegmentSnapshot in the IndexSnapshot, take the deleted PostingsList and OR it with the new postings list for this Segment. Construct a new SegmentSnapshot for the segment using this new deleted PostingsList. Append this SegmentSnapshot to the IndexSnapshot. + - Create a new SegmentSnapshot wrapping our new segment with nil deleted docs. + - Append the new SegmentSnapshot to the IndexSnapshot + - Release the lock + +An ASCII art example: + ``` + 0 - Empty Index + + No segments + + IndexSnapshot + segments [] + deleted [] + + + 1 - Index Batch [ A B C ] + + segment 0 + numbers [ 1 2 3 ] + \_id [ A B C ] + + IndexSnapshot + segments [ 0 ] + deleted [ nil ] + + + 2 - Index Batch [ B' ] + + segment 0 1 + numbers [ 1 2 3 ] [ 1 ] + \_id [ A B C ] [ B ] + + Compute bitset segment-0-deleted-by-1: + [ 0 1 0 ] + + OR it with previous (nil) (call it 0-1) + [ 0 1 0 ] + + IndexSnapshot + segments [ 0 1 ] + deleted [ 0-1 nil ] + + 3 - Index Batch [ C' ] + + segment 0 1 2 + numbers [ 1 2 3 ] [ 1 ] [ 1 ] + \_id [ A B C ] [ B ] [ C ] + + Compute bitset segment-0-deleted-by-2: + [ 0 0 1 ] + + OR it with previous ([ 0 1 0 ]) (call it 0-12) + [ 0 1 1 ] + + Compute bitset segment-1-deleted-by-2: + [ 0 ] + + OR it with previous (nil) + still just nil + + + IndexSnapshot + segments [ 0 1 2 ] + deleted [ 0-12 nil nil ] + ``` + +**is there opportunity to stop early when doc is found in one segment** +**also, more efficient way to find bits for long lists of ids?** + +### Searching + +In the bleve.index API all searching starts by getting an IndexReader, which represents a snapshot of the index at a point in time. + +As described in the section above, our index implementation maintains a pointer to the current IndexSnapshot. When a caller gets an IndexReader, they get a copy of this pointer, and can use it as long as they like. The IndexSnapshot contains SegmentSnapshots, which only contain pointers to immutable segments. The deleted posting lists associated with a segment change over time, but the particular deleted posting list in YOUR snapshot is immutable. This gives a stable view of the data. + +#### Term Search + +Term search is the only searching primitive exposed in today's bleve.index API. This ultimately could limit our ability to take advantage of the indexing improvements, but it also means it will be easier to get a first version of this working. + +A term search for term T in field F will look something like this: + +``` + searchResultPostings = empty + foreach segment { + dict := segment.Dictionary(F) + segmentResultPostings = dict.PostingsList(T, segmentSnapshotDeleted) + // make segmentLocal numbers into global numbers, and flip bits in searchResultPostings + } +``` + +The searchResultPostings will be a new implementation of the TermFieldReader inteface. + +As a reminder this interface is: + +``` +// TermFieldReader is the interface exposing the enumeration of documents +// containing a given term in a given field. Documents are returned in byte +// lexicographic order over their identifiers. +type TermFieldReader interface { + // Next returns the next document containing the term in this field, or nil + // when it reaches the end of the enumeration. The preAlloced TermFieldDoc + // is optional, and when non-nil, will be used instead of allocating memory. + Next(preAlloced *TermFieldDoc) (*TermFieldDoc, error) + + // Advance resets the enumeration at specified document or its immediate + // follower. + Advance(ID IndexInternalID, preAlloced *TermFieldDoc) (*TermFieldDoc, error) + + // Count returns the number of documents contains the term in this field. + Count() uint64 + Close() error +} +``` + +At first glance this appears problematic, we have no way to return documents in order of their identifiers. But it turns out the wording of this perhaps too strong, or a bit ambiguous. Originally, this referred to the external identifiers, but with the introduction of a distinction between internal/external identifiers, returning them in order of their internal identifiers is also acceptable. **ASIDE**: the reason for this is that most callers just use Next() and literally don't care what the order is, they could be in any order and it would be fine. There is only one search that cares and that is the ConjunctionSearcher, which relies on Next/Advance having very specific semantics. Later in this document we will have a proposal to split into multiple interfaces: + +- The weakest interface, only supports Next() no ordering at all. +- Ordered, supporting Advance() +- And/Or'able capable of internally efficiently doing these ops with like interfaces (if not capable then can always fall back to external walking) + +But, the good news is that we don't even have to do that for our first implementation. As long as the global numbers we use for internal identifiers are consistent within this IndexSnapshot, then Next() will be ordered by ascending document number, and Advance() will still work correctly. + +NOTE: there is another place where we rely on the ordering of these hits, and that is in the "\_id" sort order. Previously this was the natural order, and a NOOP for the collector, now it must be implemented by actually sorting on the "\_id" field. We probably should introduce at least a marker interface to detect this. + +An ASCII art example: + +``` +Let's start with the IndexSnapshot we ended with earlier: + +3 - Index Batch [ C' ] + + segment 0 1 2 + numbers [ 1 2 3 ] [ 1 ] [ 1 ] + \_id [ A B C ] [ B ] [ C ] + + Compute bitset segment-0-deleted-by-2: + [ 0 0 1 ] + + OR it with previous ([ 0 1 0 ]) (call it 0-12) + [ 0 1 1 ] + +Compute bitset segment-1-deleted-by-2: + [ 0 0 0 ] + +OR it with previous (nil) + still just nil + + + IndexSnapshot + segments [ 0 1 2 ] + deleted [ 0-12 nil nil ] + +Now let's search for the term 'cat' in the field 'desc' and let's assume that Document C (both versions) would match it. + +Concurrently: + + - Segment 0 + - Get Term Dictionary For Field 'desc' + - From it get Postings List for term 'cat' EXCLUDING 0-12 + - raw segment matches [ 0 0 1 ] but excluding [ 0 1 1 ] gives [ 0 0 0 ] + - Segment 1 + - Get Term Dictionary For Field 'desc' + - From it get Postings List for term 'cat' excluding nil + - [ 0 ] + - Segment 2 + - Get Term Dictionary For Field 'desc' + - From it get Postings List for term 'cat' excluding nil + - [ 1 ] + +Map local bitsets into global number space (global meaning cross-segment but still unique to this snapshot) + +IndexSnapshot already should have mapping something like: +0 - Offset 0 +1 - Offset 3 (because segment 0 had 3 docs) +2 - Offset 4 (because segment 1 had 1 doc) + +This maps to search result bitset: + +[ 0 0 0 0 1] + +Caller would call Next() and get doc number 5 (assuming 1 based indexing for now) + +Caller could then ask to get term locations, stored fields, external doc ID for document number 5. Internally in the IndexSnapshot, we can now convert that back, and realize doc number 5 comes from segment 2, 5-4=1 so we're looking for doc number 1 in segment 2. That happens to be C... + +``` + +#### Future improvements + +In the future, interfaces to detect these non-serially operating TermFieldReaders could expose their own And() and Or() up to the higher level Conjunction/Disjunction searchers. Doing this alone offers some win, but also means there would be greater burden on the Searcher code rewriting logical expressions for maximum performance. + +Another related topic is that of peak memory usage. With serially operating TermFieldReaders it was necessary to start them all at the same time and operate in unison. However, with these non-serially operating TermFieldReaders we have the option of doing a few at a time, consolidating them, dispoting the intermediaries, and then doing a few more. For very complex queries with many clauses this could reduce peak memory usage. + + +### Memory Tracking + +All segments must be able to produce two statistics, an estimate of their explicit memory usage, and their actual size on disk (if any). For in-memory segments, disk usage could be zero, and the memory usage represents the entire information content. For mmap-based disk segments, the memory could be as low as the size of tracking structure itself (say just a few pointers). + +This would allow the implementation to throttle or block incoming mutations when a threshold memory usage has (or would be) exceeded. + +### Persistence + +Obviously, we want to support (but maybe not require) asynchronous persistence of segments. My expectation is that segments are initially built in memory. At some point they are persisted to disk. This poses some interesting challenges. + +At runtime, the state of an index (it's IndexSnapshot) is not only the contents of the segments, but also the bitmasks of deleted documents. These bitmasks indirectly encode an ordering in which the segments were added. The reason is that the bitmasks encode which items have been obsoleted by other (subsequent or more future) segments. In the runtime implementation we compute bitmask deltas and then merge them at the same time we bring the new segment in. One idea is that we could take a similar approach on disk. When we persist a segment, we persist the bitmask deltas of segments known to exist at that time, and eventually these can get merged up into a base segment deleted bitmask. + +This also relates to the topic rollback, addressed next... + + +### Rollback + +One desirable property in the Couchbase ecosystem is the ability to rollback to some previous (though typically not long ago) state. One idea for keeping this property in this design is to protect some of the most recent segments from merging. Then, if necessary, they could be "undone" to reveal previous states of the system. In these scenarios "undone" has to properly undo the deleted bitmasks on the other segments. Again, the current thinking is that rather than "undo" anything, it could be work that was deferred in the first place, thus making it easier to logically undo. + +Another possibly related approach would be to tie this into our existing snapshot mechanism. Perhaps simulating a slow reader (holding onto index snapshots) for some period of time, can be the mechanism to achieve the desired end goal. + + +### Internal Storage + +The bleve.index API has support for "internal storage". The ability to store information under a separate name space. + +This is not used for high volume storage, so it is tempting to think we could just put a small k/v store alongside the rest of the index. But, the reality is that this storage is used to maintain key information related to the rollback scenario. Because of this, its crucial that ordering and overwriting of key/value pairs correspond with actual segment persistence in the index. Based on this, I believe its important to put the internal key/value pairs inside the segments themselves. But, this also means that they must follow a similar "deleted" bitmask approach to obsolete values in older segments. But, this also seems to substantially increase the complexity of the solution because of the separate name space, it would appear to require its own bitmask. Further keys aren't numeric, which then implies yet another mapping from internal key to number, etc. + +More thought is required here. + +### Merging + +The segmented index approach requires merging to prevent the number of segments from growing too large. + +Recent experience with LSMs has taught us that having the correct merge strategy can make a huge difference in the overall performance of the system. In particular, a simple merge strategy which merges segments too aggressively can lead to high write amplification and unnecessarily rendering cached data useless. + +A few simple principles have been identified. + +- Roughly we merge multiple smaller segments into a single larger one. +- The larger a segment gets the less likely we should be to ever merge it. +- Segments with large numbers of deleted/obsoleted items are good candidates as the merge will result in a space savings. +- Segments with all items deleted/obsoleted can be dropped. + +Merging of a segment should be able to proceed even if that segment is held by an ongoing snapshot, it should only delay the removal of it. diff --git a/vendor/github.com/blevesearch/bleve/index/scorch/segment/zap/README.md b/vendor/github.com/blevesearch/bleve/index/scorch/segment/zap/README.md new file mode 100644 index 0000000000..0facb669fd --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/index/scorch/segment/zap/README.md @@ -0,0 +1,158 @@ +# zap file format + +Advanced ZAP File Format Documentation is [here](zap.md). + +The file is written in the reverse order that we typically access data. This helps us write in one pass since later sections of the file require file offsets of things we've already written. + +Current usage: + +- mmap the entire file +- crc-32 bytes and version are in fixed position at end of the file +- reading remainder of footer could be version specific +- remainder of footer gives us: + - 3 important offsets (docValue , fields index and stored data index) + - 2 important values (number of docs and chunk factor) +- field data is processed once and memoized onto the heap so that we never have to go back to disk for it +- access to stored data by doc number means first navigating to the stored data index, then accessing a fixed position offset into that slice, which gives us the actual address of the data. the first bytes of that section tell us the size of data so that we know where it ends. +- access to all other indexed data follows the following pattern: + - first know the field name -> convert to id + - next navigate to term dictionary for that field + - some operations stop here and do dictionary ops + - next use dictionary to navigate to posting list for a specific term + - walk posting list + - if necessary, walk posting details as we go + - if location info is desired, consult location bitmap to see if it is there + +## stored fields section + +- for each document + - preparation phase: + - produce a slice of metadata bytes and data bytes + - produce these slices in field id order + - field value is appended to the data slice + - metadata slice is varint encoded with the following values for each field value + - field id (uint16) + - field type (byte) + - field value start offset in uncompressed data slice (uint64) + - field value length (uint64) + - field number of array positions (uint64) + - one additional value for each array position (uint64) + - compress the data slice using snappy + - file writing phase: + - remember the start offset for this document + - write out meta data length (varint uint64) + - write out compressed data length (varint uint64) + - write out the metadata bytes + - write out the compressed data bytes + +## stored fields idx + +- for each document + - write start offset (remembered from previous section) of stored data (big endian uint64) + +With this index and a known document number, we have direct access to all the stored field data. + +## posting details (freq/norm) section + +- for each posting list + - produce a slice containing multiple consecutive chunks (each chunk is varint stream) + - produce a slice remembering offsets of where each chunk starts + - preparation phase: + - for each hit in the posting list + - if this hit is in next chunk close out encoding of last chunk and record offset start of next + - encode term frequency (uint64) + - encode norm factor (float32) + - file writing phase: + - remember start position for this posting list details + - write out number of chunks that follow (varint uint64) + - write out length of each chunk (each a varint uint64) + - write out the byte slice containing all the chunk data + +If you know the doc number you're interested in, this format lets you jump to the correct chunk (docNum/chunkFactor) directly and then seek within that chunk until you find it. + +## posting details (location) section + +- for each posting list + - produce a slice containing multiple consecutive chunks (each chunk is varint stream) + - produce a slice remembering offsets of where each chunk starts + - preparation phase: + - for each hit in the posting list + - if this hit is in next chunk close out encoding of last chunk and record offset start of next + - encode field (uint16) + - encode field pos (uint64) + - encode field start (uint64) + - encode field end (uint64) + - encode number of array positions to follow (uint64) + - encode each array position (each uint64) + - file writing phase: + - remember start position for this posting list details + - write out number of chunks that follow (varint uint64) + - write out length of each chunk (each a varint uint64) + - write out the byte slice containing all the chunk data + +If you know the doc number you're interested in, this format lets you jump to the correct chunk (docNum/chunkFactor) directly and then seek within that chunk until you find it. + +## postings list section + +- for each posting list + - preparation phase: + - encode roaring bitmap posting list to bytes (so we know the length) + - file writing phase: + - remember the start position for this posting list + - write freq/norm details offset (remembered from previous, as varint uint64) + - write location details offset (remembered from previous, as varint uint64) + - write length of encoded roaring bitmap + - write the serialized roaring bitmap data + +## dictionary + +- for each field + - preparation phase: + - encode vellum FST with dictionary data pointing to file offset of posting list (remembered from previous) + - file writing phase: + - remember the start position of this persistDictionary + - write length of vellum data (varint uint64) + - write out vellum data + +## fields section + +- for each field + - file writing phase: + - remember start offset for each field + - write dictionary address (remembered from previous) (varint uint64) + - write length of field name (varint uint64) + - write field name bytes + +## fields idx + +- for each field + - file writing phase: + - write big endian uint64 of start offset for each field + +NOTE: currently we don't know or record the length of this fields index. Instead we rely on the fact that we know it immediately precedes a footer of known size. + +## fields DocValue + +- for each field + - preparation phase: + - produce a slice containing multiple consecutive chunks, where each chunk is composed of a meta section followed by compressed columnar field data + - produce a slice remembering the length of each chunk + - file writing phase: + - remember the start position of this first field DocValue offset in the footer + - write out number of chunks that follow (varint uint64) + - write out length of each chunk (each a varint uint64) + - write out the byte slice containing all the chunk data + +NOTE: currently the meta header inside each chunk gives clue to the location offsets and size of the data pertaining to a given docID and any +read operation leverage that meta information to extract the document specific data from the file. + +## footer + +- file writing phase + - write number of docs (big endian uint64) + - write stored field index location (big endian uint64) + - write field index location (big endian uint64) + - write field docValue location (big endian uint64) + - write out chunk factor (big endian uint32) + - write out version (big endian uint32) + - write out file CRC of everything preceding this (big endian uint32) diff --git a/vendor/github.com/blevesearch/bleve/index/scorch/segment/zap/zap.md b/vendor/github.com/blevesearch/bleve/index/scorch/segment/zap/zap.md new file mode 100644 index 0000000000..d74dc548b8 --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/index/scorch/segment/zap/zap.md @@ -0,0 +1,177 @@ +# ZAP File Format + +## Legend + +### Sections + + |========| + | | section + |========| + +### Fixed-size fields + + |--------| |----| |--| |-| + | | uint64 | | uint32 | | uint16 | | uint8 + |--------| |----| |--| |-| + +### Varints + + |~~~~~~~~| + | | varint(up to uint64) + |~~~~~~~~| + +### Arbitrary-length fields + + |--------...---| + | | arbitrary-length field (string, vellum, roaring bitmap) + |--------...---| + +### Chunked data + + [--------] + [ ] + [--------] + +## Overview + +Footer section describes the configuration of particular ZAP file. The format of footer is version-dependent, so it is necessary to check `V` field before the parsing. + + |==================================================| + | Stored Fields | + |==================================================| + |-----> | Stored Fields Index | + | |==================================================| + | | Dictionaries + Postings + DocValues | + | |==================================================| + | |---> | DocValues Index | + | | |==================================================| + | | | Fields | + | | |==================================================| + | | |-> | Fields Index | + | | | |========|========|========|========|====|====|====| + | | | | D# | SF | F | FDV | CF | V | CC | (Footer) + | | | |========|====|===|====|===|====|===|====|====|====| + | | | | | | + |-+-+-----------------| | | + | |--------------------------| | + |-------------------------------------| + + D#. Number of Docs. + SF. Stored Fields Index Offset. + F. Field Index Offset. + FDV. Field DocValue Offset. + CF. Chunk Factor. + V. Version. + CC. CRC32. + +## Stored Fields + +Stored Fields Index is `D#` consecutive 64-bit unsigned integers - offsets, where relevant Stored Fields Data records are located. + + 0 [SF] [SF + D# * 8] + | Stored Fields | Stored Fields Index | + |================================|==================================| + | | | + | |--------------------| ||--------|--------|. . .|--------|| + | |-> | Stored Fields Data | || 0 | 1 | | D# - 1 || + | | |--------------------| ||--------|----|---|. . .|--------|| + | | | | | + |===|============================|==============|===================| + | | + |-------------------------------------------| + +Stored Fields Data is an arbitrary size record, which consists of metadata and [Snappy](https://github.com/golang/snappy)-compressed data. + + Stored Fields Data + |~~~~~~~~|~~~~~~~~|~~~~~~~~...~~~~~~~~|~~~~~~~~...~~~~~~~~| + | MDS | CDS | MD | CD | + |~~~~~~~~|~~~~~~~~|~~~~~~~~...~~~~~~~~|~~~~~~~~...~~~~~~~~| + + MDS. Metadata size. + CDS. Compressed data size. + MD. Metadata. + CD. Snappy-compressed data. + +## Fields + +Fields Index section located between addresses `F` and `len(file) - len(footer)` and consist of `uint64` values (`F1`, `F2`, ...) which are offsets to records in Fields section. We have `F# = (len(file) - len(footer) - F) / sizeof(uint64)` fields. + + + (...) [F] [F + F#] + | Fields | Fields Index. | + |================================|================================| + | | | + | |~~~~~~~~|~~~~~~~~|---...---|||--------|--------|...|--------|| + ||->| Dict | Length | Name ||| 0 | 1 | | F# - 1 || + || |~~~~~~~~|~~~~~~~~|---...---|||--------|----|---|...|--------|| + || | | | + ||===============================|==============|=================| + | | + |----------------------------------------------| + + +## Dictionaries + Postings + +Each of fields has its own dictionary, encoded in [Vellum](https://github.com/couchbase/vellum) format. Dictionary consists of pairs `(term, offset)`, where `offset` indicates the position of postings (list of documents) for this particular term. + + |================================================================|- Dictionaries + + | | Postings + + | | DocValues + | Freq/Norm (chunked) | + | [~~~~~~|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~] | + | |->[ Freq | Norm (float32 under varint) ] | + | | [~~~~~~|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~] | + | | | + | |------------------------------------------------------------| | + | Location Details (chunked) | | + | [~~~~~~|~~~~~|~~~~~~~|~~~~~|~~~~~~|~~~~~~~~|~~~~~] | | + | |->[ Size | Pos | Start | End | Arr# | ArrPos | ... ] | | + | | [~~~~~~|~~~~~|~~~~~~~|~~~~~|~~~~~~|~~~~~~~~|~~~~~] | | + | | | | + | |----------------------| | | + | Postings List | | | + | |~~~~~~~~|~~~~~|~~|~~~~~~~~|-----------...--| | | + | |->| F/N | LD | Length | ROARING BITMAP | | | + | | |~~~~~|~~|~~~~~~~~|~~~~~~~~|-----------...--| | | + | | |----------------------------------------------| | + | |--------------------------------------| | + | Dictionary | | + | |~~~~~~~~|--------------------------|-...-| | + | |->| Length | VELLUM DATA : (TERM -> OFFSET) | | + | | |~~~~~~~~|----------------------------...-| | + | | | + |======|=========================================================|- DocValues Index + | | | + |======|=========================================================|- Fields + | | | + | |~~~~|~~~|~~~~~~~~|---...---| | + | | Dict | Length | Name | | + | |~~~~~~~~|~~~~~~~~|---...---| | + | | + |================================================================| + +## DocValues + +DocValues Index is `F#` pairs of varints, one pair per field. Each pair of varints indicates start and end point of DocValues slice. + + |================================================================| + | |------...--| | + | |->| DocValues |<-| | + | | |------...--| | | + |==|=================|===========================================|- DocValues Index + ||~|~~~~~~~~~|~~~~~~~|~~| |~~~~~~~~~~~~~~|~~~~~~~~~~~~|| + || DV1 START | DV1 STOP | . . . . . | DV(F#) START | DV(F#) END || + ||~~~~~~~~~~~|~~~~~~~~~~| |~~~~~~~~~~~~~~|~~~~~~~~~~~~|| + |================================================================| + +DocValues is chunked Snappy-compressed values for each document and field. + + [~~~~~~~~~~~~~~~|~~~~~~|~~~~~~~~~|-...-|~~~~~~|~~~~~~~~~|--------------------...-] + [ Doc# in Chunk | Doc1 | Offset1 | ... | DocN | OffsetN | SNAPPY COMPRESSED DATA ] + [~~~~~~~~~~~~~~~|~~~~~~|~~~~~~~~~|-...-|~~~~~~|~~~~~~~~~|--------------------...-] + +Last 16 bytes are description of chunks. + + |~~~~~~~~~~~~...~|----------------|----------------| + | Chunk Sizes | Chunk Size Arr | Chunk# | + |~~~~~~~~~~~~...~|----------------|----------------| diff --git a/vendor/github.com/blevesearch/bleve/index/upsidedown/benchmark_all.sh b/vendor/github.com/blevesearch/bleve/index/upsidedown/benchmark_all.sh new file mode 100644 index 0000000000..079fef1865 --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/index/upsidedown/benchmark_all.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +BENCHMARKS=`grep "func Benchmark" *_test.go | sed 's/.*func //' | sed s/\(.*{//` + +for BENCHMARK in $BENCHMARKS +do + go test -v -run=xxx -bench=^$BENCHMARK$ -benchtime=10s -tags 'forestdb leveldb' | grep -v ok | grep -v PASS +done diff --git a/vendor/github.com/blevesearch/bleve/index/upsidedown/upsidedown.proto b/vendor/github.com/blevesearch/bleve/index/upsidedown/upsidedown.proto new file mode 100644 index 0000000000..cf0492a2db --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/index/upsidedown/upsidedown.proto @@ -0,0 +1,14 @@ +message BackIndexTermsEntry { + required uint32 field = 1; + repeated string terms = 2; +} + +message BackIndexStoreEntry { + required uint32 field = 1; + repeated uint64 arrayPositions = 2; +} + +message BackIndexRowValue { + repeated BackIndexTermsEntry termsEntries = 1; + repeated BackIndexStoreEntry storedEntries = 2; +} diff --git a/vendor/github.com/blevesearch/bleve/search/facet/benchmark_data.txt b/vendor/github.com/blevesearch/bleve/search/facet/benchmark_data.txt new file mode 100644 index 0000000000..b012f78ce5 --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/search/facet/benchmark_data.txt @@ -0,0 +1,2909 @@ +Boiling liquid expanding vapor explosion +From Wikipedia, the free encyclopedia +See also: Boiler explosion and Steam explosion + +Flames subsequent to a flammable liquid BLEVE from a tanker. BLEVEs do not necessarily involve fire. + +This article's tone or style may not reflect the encyclopedic tone used on Wikipedia. See Wikipedia's guide to writing better articles for suggestions. (July 2013) +A boiling liquid expanding vapor explosion (BLEVE, /ˈblɛviː/ blev-ee) is an explosion caused by the rupture of a vessel containing a pressurized liquid above its boiling point.[1] +Contents [hide] +1 Mechanism +1.1 Water example +1.2 BLEVEs without chemical reactions +2 Fires +3 Incidents +4 Safety measures +5 See also +6 References +7 External links +Mechanism[edit] + +This section needs additional citations for verification. Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed. (July 2013) +There are three characteristics of liquids which are relevant to the discussion of a BLEVE: +If a liquid in a sealed container is boiled, the pressure inside the container increases. As the liquid changes to a gas it expands - this expansion in a vented container would cause the gas and liquid to take up more space. In a sealed container the gas and liquid are not able to take up more space and so the pressure rises. Pressurized vessels containing liquids can reach an equilibrium where the liquid stops boiling and the pressure stops rising. This occurs when no more heat is being added to the system (either because it has reached ambient temperature or has had a heat source removed). +The boiling temperature of a liquid is dependent on pressure - high pressures will yield high boiling temperatures, and low pressures will yield low boiling temperatures. A common simple experiment is to place a cup of water in a vacuum chamber, and then reduce the pressure in the chamber until the water boils. By reducing the pressure the water will boil even at room temperature. This works both ways - if the pressure is increased beyond normal atmospheric pressures, the boiling of hot water could be suppressed far beyond normal temperatures. The cooling system of a modern internal combustion engine is a real-world example. +When a liquid boils it turns into a gas. The resulting gas takes up far more space than the liquid did. +Typically, a BLEVE starts with a container of liquid which is held above its normal, atmospheric-pressure boiling temperature. Many substances normally stored as liquids, such as CO2, oxygen, and other similar industrial gases have boiling temperatures, at atmospheric pressure, far below room temperature. In the case of water, a BLEVE could occur if a pressurized chamber of water is heated far beyond the standard 100 °C (212 °F). That container, because the boiling water pressurizes it, is capable of holding liquid water at very high temperatures. +If the pressurized vessel, containing liquid at high temperature (which may be room temperature, depending on the substance) ruptures, the pressure which prevents the liquid from boiling is lost. If the rupture is catastrophic, where the vessel is immediately incapable of holding any pressure at all, then there suddenly exists a large mass of liquid which is at very high temperature and very low pressure. This causes the entire volume of liquid to instantaneously boil, which in turn causes an extremely rapid expansion. Depending on temperatures, pressures and the substance involved, that expansion may be so rapid that it can be classified as an explosion, fully capable of inflicting severe damage on its surroundings. +Water example[edit] +Imagine, for example, a tank of pressurized liquid water held at 204.4 °C (400 °F). This vessel would normally be pressurized to 1.7 MPa (250 psi) above atmospheric ("gauge") pressure. Were the tank containing the water to split open, there would momentarily exist a volume of liquid water which is +at atmospheric pressure, and +204.4 °C (400 °F). +At atmospheric pressure the boiling point of water is 100 °C (212 °F) - liquid water at atmospheric pressure cannot exist at temperatures higher than 100 °C (212 °F). It is obvious, then, that 204.4 °C (400 °F) liquid water at atmospheric pressure must immediately flash to gas causing an explosion. +BLEVEs without chemical reactions[edit] +It is important to note that a BLEVE need not be a chemical explosion - nor does there need to be a fire - however if a flammable substance is subject to a BLEVE it may also be subject to intense heating, either from an external source of heat which may have caused the vessel to rupture in the first place or from an internal source of localized heating such as skin friction. This heating can cause a flammable substance to ignite, adding a secondary explosion caused by the primary BLEVE. While blast effects of any BLEVE can be devastating, a flammable substance such as propane can add significantly to the danger. +Bleve explosion.svg +While the term BLEVE is most often used to describe the results of a container of flammable liquid rupturing due to fire, a BLEVE can occur even with a non-flammable substance such as water,[2] liquid nitrogen,[3] liquid helium or other refrigerants or cryogens, and therefore is not usually considered a type of chemical explosion. +Fires[edit] +BLEVEs can be caused by an external fire near the storage vessel causing heating of the contents and pressure build-up. While tanks are often designed to withstand great pressure, constant heating can cause the metal to weaken and eventually fail. If the tank is being heated in an area where there is no liquid, it may rupture faster without the liquid to absorb the heat. Gas containers are usually equipped with relief valves that vent off excess pressure, but the tank can still fail if the pressure is not released quickly enough.[1] Relief valves are sized to release pressure fast enough to prevent the pressure from increasing beyond the strength of the vessel, but not so fast as to be the cause of an explosion. An appropriately sized relief valve will allow the liquid inside to boil slowly, maintaining a constant pressure in the vessel until all the liquid has boiled and the vessel empties. +If the substance involved is flammable, it is likely that the resulting cloud of the substance will ignite after the BLEVE has occurred, forming a fireball and possibly a fuel-air explosion, also termed a vapor cloud explosion (VCE). If the materials are toxic, a large area will be contaminated.[4] +Incidents[edit] +The term "BLEVE" was coined by three researchers at Factory Mutual, in the analysis of an accident there in 1957 involving a chemical reactor vessel.[5] +In August 1959 the Kansas City Fire Department suffered its largest ever loss of life in the line of duty, when a 25,000 gallon (95,000 litre) gas tank exploded during a fire on Southwest Boulevard killing five firefighters. This was the first time BLEVE was used to describe a burning fuel tank.[citation needed] +Later incidents included the Cheapside Street Whisky Bond Fire in Glasgow, Scotland in 1960; Feyzin, France in 1966; Crescent City, Illinois in 1970; Kingman, Arizona in 1973; a liquid nitrogen tank rupture[6] at Air Products and Chemicals and Mobay Chemical Company at New Martinsville, West Virginia on January 31, 1978 [1];Texas City, Texas in 1978; Murdock, Illinois in 1983; San Juan Ixhuatepec, Mexico City in 1984; and Toronto, Ontario in 2008. +Safety measures[edit] +[icon] This section requires expansion. (July 2013) +Some fire mitigation measures are listed under liquefied petroleum gas. +See also[edit] +Boiler explosion +Expansion ratio +Explosive boiling or phase explosion +Rapid phase transition +Viareggio train derailment +2008 Toronto explosions +Gas carriers +Los Alfaques Disaster +Lac-Mégantic derailment +References[edit] +^ Jump up to: a b Kletz, Trevor (March 1990). Critical Aspects of Safety and Loss Prevention. London: Butterworth–Heinemann. pp. 43–45. ISBN 0-408-04429-2. +Jump up ^ "Temperature Pressure Relief Valves on Water Heaters: test, inspect, replace, repair guide". Inspect-ny.com. Retrieved 2011-07-12. +Jump up ^ Liquid nitrogen BLEVE demo +Jump up ^ "Chemical Process Safety" (PDF). Retrieved 2011-07-12. +Jump up ^ David F. Peterson, BLEVE: Facts, Risk Factors, and Fallacies, Fire Engineering magazine (2002). +Jump up ^ "STATE EX REL. VAPOR CORP. v. NARICK". Supreme Court of Appeals of West Virginia. 1984-07-12. Retrieved 2014-03-16. +External links[edit] + Look up boiling liquid expanding vapor explosion in Wiktionary, the free dictionary. + Wikimedia Commons has media related to BLEVE. +BLEVE Demo on YouTube — video of a controlled BLEVE demo +huge explosions on YouTube — video of propane and isobutane BLEVEs from a train derailment at Murdock, Illinois (3 September 1983) +Propane BLEVE on YouTube — video of BLEVE from the Toronto propane depot fire +Moscow Ring Road Accident on YouTube - Dozens of LPG tank BLEVEs after a road accident in Moscow +Kingman, AZ BLEVE — An account of the 5 July 1973 explosion in Kingman, with photographs +Propane Tank Explosions — Description of circumstances required to cause a propane tank BLEVE. +Analysis of BLEVE Events at DOE Sites - Details physics and mathematics of BLEVEs. +HID - SAFETY REPORT ASSESSMENT GUIDE: Whisky Maturation Warehouses - The liquor is aged in wooden barrels that can suffer BLEVE. +Categories: ExplosivesFirefightingFireTypes of fireGas technologiesIndustrial fires and explosions +Navigation menu +Create accountLog inArticleTalkReadEditView history + +Main page +Contents +Featured content +Current events +Random article +Donate to Wikipedia +Wikimedia Shop +Interaction +Help +About Wikipedia +Community portal +Recent changes +Contact page +Tools +What links here +Related changes +Upload file +Special pages +Permanent link +Page information +Wikidata item +Cite this page +Print/export +Create a book +Download as PDF +Printable version +Languages +Català +Deutsch +Español +Français +Italiano +עברית +Nederlands +日本語 +Norsk bokmål +Polski +Português +Русский +Suomi +Edit links +This page was last modified on 18 November 2014 at 01:35. +Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Terms of Use and Privacy Policy. Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc., a non-profit organization. +Privacy policyAbout WikipediaDisclaimersContact WikipediaDevelopersMobile viewWikimedia Foundation Powered by MediaWiki + + +Thermobaric weapon +From Wikipedia, the free encyclopedia + +Blast from a US Navy fuel air explosive used against a decommissioned ship, USS McNulty, 1972. +A thermobaric weapon is a type of explosive that utilizes oxygen from the surrounding air to generate an intense, high-temperature explosion, and in practice the blast wave such a weapon produces is typically significantly longer in duration than a conventional condensed explosive. The fuel-air bomb is one of the most well-known types of thermobaric weapons. +Most conventional explosives consist of a fuel-oxidizer premix (gunpowder, for example, contains 25% fuel and 75% oxidizer), whereas thermobaric weapons are almost 100% fuel, so thermobaric weapons are significantly more energetic than conventional condensed explosives of equal weight. Their reliance on atmospheric oxygen makes them unsuitable for use underwater, at high altitude, and in adverse weather. They do, however, cause considerably more destruction when used inside confined environments such as tunnels, caves, and bunkers - partly due to the sustained blast wave, and partly by consuming the available oxygen inside those confined spaces. +There are many different types of thermobaric weapons rounds that can be fitted to hand-held launchers.[1] +Contents [hide] +1 Terminology +2 Mechanism +2.1 Fuel-air explosive +2.1.1 Effect +3 Development history +3.1 Soviet and Russian developments +3.2 US developments +4 History +4.1 Military use +4.2 Non-military use +5 See also +6 References +7 External links +Terminology[edit] +The term thermobaric is derived from the Greek words for "heat" and "pressure": thermobarikos (θερμοβαρικός), from thermos (θερμός), hot + baros (βάρος), weight, pressure + suffix -ikos (-ικός), suffix -ic. +Other terms used for this family of weapons are high-impulse thermobaric weapons (HITs), heat and pressure weapons, vacuum bombs, or fuel-air explosives (FAE or FAX). +Mechanism[edit] +In contrast to condensed explosive, where oxidation in a confined region produces a blast front from essentially a point source, a flame front accelerates to a large volume producing pressure fronts both within the mixture of fuel and oxidant and then in the surrounding air.[2] +Thermobaric explosives apply the principles underlying accidental unconfined vapor cloud explosions, which include those from dispersions of flammable dusts and droplets.[3] Previously, such explosions were most often encountered in flour mills and their storage containers, and later in coal mines; but, now, most commonly in discharged oil tankers and refineries, including an incident at Buncefield in the UK in 2005 where the blast wave woke people 150 kilometres (93 mi) from its centre.[4] +A typical weapon consists of a container packed with a fuel substance, in the center of which is a small conventional-explosive "scatter charge". Fuels are chosen on the basis of the exothermicity of their oxidation, ranging from powdered metals, such as aluminium or magnesium, to organic materials, possibly with a self-contained partial oxidant. The most recent development involves the use of nanofuels.[5][6] +A thermobaric bomb's effective yield requires the most appropriate combination of a number of factors; among these are how well the fuel is dispersed, how rapidly it mixes with the surrounding atmosphere, and the initiation of the igniter and its position relative to the container of fuel. In some designs, strong munitions cases allow the blast pressure to be contained long enough for the fuel to be heated up well above its auto-ignition temperature, so that once the container bursts the super-heated fuel will auto-ignite progressively as it comes into contact with atmospheric oxygen.[7][8][9][10][11][12][13][14][15][16][17] +Conventional upper and lower limits of flammability apply to such weapons. Close in, blast from the dispersal charge, compressing and heating the surrounding atmosphere, will have some influence on the lower limit. The upper limit has been demonstrated strongly to influence the ignition of fogs above pools of oil.[18] This weakness may be eliminated by designs where the fuel is preheated well above its ignition temperature, so that its cooling during its dispersion still results in a minimal ignition delay on mixing. The continual combustion of the outer layer of fuel molecules as they come into contact with the air, generates additional heat which maintains the temperature of the interior of the fireball, and thus sustains the detonation.[19][20][21] +In confinement, a series of reflective shock waves are generated,[22][23] which maintain the fireball and can extend its duration to between 10 and 50 ms as exothermic recombination reactions occur.[24] Further damage can result as the gases cool and pressure drops sharply, leading to a partial vacuum. This effect has given rise to the misnomer "vacuum bomb". Piston-type afterburning is also believed to occur in such structures, as flame-fronts accelerate through it.[25][26] +Fuel-air explosive[edit] +A fuel-air explosive (FAE) device consists of a container of fuel and two separate explosive charges. After the munition is dropped or fired, the first explosive charge bursts open the container at a predetermined height and disperses the fuel in a cloud that mixes with atmospheric oxygen (the size of the cloud varies with the size of the munition). The cloud of fuel flows around objects and into structures. The second charge then detonates the cloud, creating a massive blast wave. The blast wave destroys unreinforced buildings and equipment and kills and injures people. The antipersonnel effect of the blast wave is more severe in foxholes, on people with body armor, and in enclosed spaces such as caves, buildings, and bunkers. +Fuel-air explosives were first developed, and used in Vietnam, by the United States. Soviet scientists, however, quickly developed their own FAE weapons, which were reportedly used against China in the Sino-Soviet border conflict and in Afghanistan. Since then, research and development has continued and currently Russian forces field a wide array of third-generation FAE warheads. +Effect[edit] +A Human Rights Watch report of 1 February 2000[27] quotes a study made by the US Defense Intelligence Agency: +The [blast] kill mechanism against living targets is unique–and unpleasant.... What kills is the pressure wave, and more importantly, the subsequent rarefaction [vacuum], which ruptures the lungs.... If the fuel deflagrates but does not detonate, victims will be severely burned and will probably also inhale the burning fuel. Since the most common FAE fuels, ethylene oxide and propylene oxide, are highly toxic, undetonated FAE should prove as lethal to personnel caught within the cloud as most chemical agents. +According to a U.S. Central Intelligence Agency study,[27] "the effect of an FAE explosion within confined spaces is immense. Those near the ignition point are obliterated. Those at the fringe are likely to suffer many internal, and thus invisible injuries, including burst eardrums and crushed inner ear organs, severe concussions, ruptured lungs and internal organs, and possibly blindness." Another Defense Intelligence Agency document speculates that because the "shock and pressure waves cause minimal damage to brain tissue…it is possible that victims of FAEs are not rendered unconscious by the blast, but instead suffer for several seconds or minutes while they suffocate."[28] +Development history[edit] +Soviet and Russian developments[edit] + +A RPO-A rocket and launcher. +The Soviet armed forces extensively developed FAE weapons,[29] such as the RPO-A, and used them in Chechnya.[30] +The Russian armed forces have developed thermobaric ammunition variants for several of their weapons, such as the TGB-7V thermobaric grenade with a lethality radius of 10 metres (33 ft), which can be launched from a RPG-7. The GM-94 is a 43 mm pump-action grenade launcher which is designed mainly to fire thermobaric grenades for close quarters combat. With the grenade weighing 250 grams (8.8 oz) and holding a 160 grams (5.6 oz) explosive mixture, its lethality radius is 3 metres (9.8 ft); however, due to the deliberate "fragmentation-free" design of the grenade, 4 metres (13 ft) is already considered a safe distance.[31] The RPO-A and upgraded RPO-M are infantry-portable RPGs designed to fire thermobaric rockets. The RPO-M, for instance, has a thermobaric warhead with a TNT equivalence of 5.5 kilograms (12 lb) of TNT and destructive capabilities similar to a 152 mm High explosive fragmentation artillery shell.[32][33] The RShG-1 and the RShG-2 are thermobaric variants of the RPG-27 and RPG-26 respectively. The RShG-1 is the more powerful variant, with its warhead having a 10 metres (33 ft) lethality radius and producing about the same effect as 6 kg (13 lb) of TNT.[34] The RMG is a further derivative of the RPG-26 that uses a tandem-charge warhead, whereby the precursor HEAT warhead blasts an opening for the main thermobaric charge to enter and detonate inside.[35] The RMG's precursor HEAT warhead can penetrate 300 mm of reinforced concrete or over 100 mm of Rolled homogeneous armour, thus allowing the 105 millimetres (4.1 in) diameter thermobaric warhead to detonate inside.[36] +The other examples include the SACLOS or millimeter wave radar-guided thermobaric variants of the 9M123 Khrizantema, the 9M133F-1 thermobaric warhead variant of the 9M133 Kornet, and the 9M131F thermobaric warhead variant of the 9K115-2 Metis-M, all of which are anti-tank missiles. The Kornet has since been upgraded to the Kornet-EM, and its thermobaric variant has a maximum range of 10 kilometres (6.2 mi) and has the TNT equivalent of 7 kilograms (15 lb) of TNT.[37] The 300 mm 9M55S thermobaric cluster warhead rocket was built to be fired from the BM-30 Smerch MLRS. A dedicated carrier of thermobaric weapons is the purpose-built TOS-1, a 24-tube MLRS designed to fire 220 mm caliber thermobaric rockets. A full salvo from the TOS-1 will cover a rectangle 200x400 metres.[38] The Iskander-M theatre ballistic missile can also carry a 700 kilograms (1,500 lb) thermobaric warhead.[39] + +The fireball blast from the Russian Air Force's FOAB, the largest Thermobaric device to be detonated. +Many Russian Air Force munitions also have thermobaric variants. The 80 mm S-8 rocket has the S-8DM and S-8DF thermobaric variants. The S-8's larger 122 mm brother, the S-13 rocket, has the S-13D and S-13DF thermobaric variants. The S-13DF's warhead weighs only 32 kg (71 lb) but its power is equivalent to 40 kg (88 lb) of TNT. The KAB-500-OD variant of the KAB-500KR has a 250 kg (550 lb) thermobaric warhead. The ODAB-500PM and ODAB-500PMV unguided bombs carry a 190 kg (420 lb) fuel-air explosive each. The KAB-1500S GLONASS/GPS guided 1,500 kg (3,300 lb) bomb also has a thermobaric variant. Its fireball will cover over a 150-metre (490 ft) radius and its lethality zone is a 500-metre (1,600 ft) radius.[40] The 9M120 Ataka-V and the 9K114 Shturm ATGMs both have thermobaric variants. +In September 2007 Russia exploded the largest thermobaric weapon ever made. The weapon's yield was reportedly greater than that of the smallest dial-a-yield nuclear weapons at their lowest settings.[41][42] Russia named this particular ordnance the "Father of All Bombs" in response to the United States developed "Massive Ordnance Air Blast" (MOAB) bomb whose backronym is the "Mother of All Bombs", and which previously held the accolade of the most powerful non-nuclear weapon in history.[43] The bomb contains an about 7 tons charge of a liquid fuel such as ethylene oxide, mixed with an energetic nanoparticle such as aluminium, surrounding a high explosive burster[44] that when detonated created an explosion equivalent to 44 metric tons of TNT. +US developments[edit] + +A BLU-72/B bomb on a USAF A-1E taking off from Nakhon Phanom, in September 1968. +Current US FAE munitions include: +BLU-73 FAE I +BLU-95 500-lb (FAE-II) +BLU-96 2,000-lb (FAE-II) +CBU-55 FAE I +CBU-72 FAE I +The XM1060 40-mm grenade is a small-arms thermobaric device, which was delivered to U.S. forces in April 2003.[45] Since the 2003 Invasion of Iraq, the US Marine Corps has introduced a thermobaric 'Novel Explosive' (SMAW-NE) round for the Mk 153 SMAW rocket launcher. One team of Marines reported that they had destroyed a large one-story masonry type building with one round from 100 yards (91 m).[46] +The AGM-114N Hellfire II, first used by U.S. forces in 2003 in Iraq, uses a Metal Augmented Charge (MAC) warhead that contains a thermobaric explosive fill using fluoridated aluminium layered between the charge casing and a PBXN-112 explosive mixture. When the PBXN-112 detonates, the aluminium mixture is dispersed and rapidly burns. The resultant sustained high pressure is extremely effective against people and structures.[47] +History[edit] +Military use[edit] + +US Navy BLU-118B being prepared for shipping for use in Afghanistan, 5 March 2002. +The first experiments with thermobaric weapon were conducted in Germany during World War II and were led by Mario Zippermayr. The German bombs used coal dust as fuel and were extensively tested in 1943 and 1944, but did not reach mass production before the war ended. +The TOS-1 system was test fired in Panjshir valley during Soviet war in Afghanistan in the early 1980s.[48] +Unconfirmed reports suggest that Russian military forces used ground delivered thermobaric weapons in the storming of the Russian parliament during the 1993 Russian constitutional crisis and also during the Battle for Grozny (first and second Chechen wars) to attack dug in Chechen fighters. The use of both TOS-1 heavy MLRS and "RPO-A Shmel" shoulder-fired rocket system in the Chechen wars is reported to have occurred.[48][49] +It is theorized that a multitude of hand-held thermobaric weapons were used by the Russian Armed Forces in their efforts to retake the school during the 2004 Beslan school hostage crisis. The RPO-A and either the TGB-7V thermobaric rocket from the RPG-7 or rockets from either the RShG-1 or the RShG-2 is claimed to have been used by the Spetsnaz during the initial storming of the school.[50][51][52] At least 3 and as many as 9 RPO-A casings were later found at the positions of the Spetsnaz.[53][54] The Russian Government later admitted to the use of the RPO-A during the crisis.[55] +According to UK Ministry of Defence, British military forces have also used thermobaric weapons in their AGM-114N Hellfire missiles (carried by Apache helicopters and UAVs) against the Taliban in the War in Afghanistan.[56] +The US military also used thermobaric weapons in Afghanistan. On 3 March 2002, a single 2,000 lb (910 kg) laser guided thermobaric bomb was used by the United States Army against cave complexes in which Al-Qaeda and Taliban fighters had taken refuge in the Gardez region of Afghanistan.[57][58] The SMAW-NE was used by the US Marines during the First Battle of Fallujah and Second Battle of Fallujah. +Reports by the rebel fighters of the Free Syrian Army claim the Syrian Air Force used such weapons against residential area targets occupied by the rebel fighters, as for instance in the Battle for Aleppo[59] and also in Kafar Batna.[60] A United Nations panel of human rights investigators reported that the Syrian government used thermobaric bombs against the rebellious town of Qusayr in March 2013.[61] +Non-military use[edit] +Thermobaric and fuel-air explosives have been used in guerrilla warfare since the 1983 Beirut barracks bombing in Lebanon, which used a gas-enhanced explosive mechanism, probably propane, butane or acetylene.[62] The explosive used by the bombers in the 1993 World Trade Center bombing incorporated the FAE principle, using three tanks of bottled hydrogen gas to enhance the blast.[63][64] Jemaah Islamiyah bombers used a shock-dispersed solid fuel charge,[65] based on the thermobaric principle,[66] to attack the Sari nightclub in the 2002 Bali bombings.[67] +See also[edit] +Bunker buster +Dust explosion +FOAB +Flame fougasse +MOAB +RPO-A +SMAW +References[edit] +Jump up ^ Algeria Isp (2011-10-18). "Libye – l'Otan utilise une bombe FAE | Politique, Algérie". Algeria ISP. Retrieved 2013-04-23. +Jump up ^ Nettleton, J. Occ. Accidents, 1, 149 (1976). +Jump up ^ Strehlow, 14th. Symp. (Int.) Comb. 1189, Comb. Inst. (1973). +Jump up ^ Health and Safety Environmental Agency, 5th. and final report, 2008. +Jump up ^ See Nanofuel/Oxidizers For Energetic Compositions – John D. Sullivan and Charles N. Kingery (1994) High explosive disseminator for a high explosive air bomb. +Jump up ^ Slavica Terzić, Mirjana Dakić Kolundžija, Milovan Azdejković and Gorgi Minov (2004) Compatibility Of Thermobaric Mixtures Based On Isopropyl Nitrate And Metal Powders. +Jump up ^ Meyer, Rudolf; Josef Köhler and Axel Homburg (2007). Explosives. Weinheim: Wiley-VCH. pp. 312. ISBN 3-527-31656-6. OCLC 165404124. +Jump up ^ Howard C. Hornig (1998) Non-focusing active warhead. +Jump up ^ Chris Ludwig (Talley Defense) Verifying Performance of Thermobaric Materials for Small to Medium Caliber Rocket Warheads. +Jump up ^ Martin M.West (1982) Composite high explosives for high energy blast applications. +Jump up ^ Raafat H. Guirguis (2005) Reactively Induced Fragmenting Explosives. +Jump up ^ Michael Dunning, William Andrews and Kevin Jaansalu (2005) The Fragmentation of Metal Cylinders Using Thermobaric Explosives. +Jump up ^ David L. Frost, Fan Zhang, Stephen B. Murray and Susan McCahan Critical Conditions For Ignition Of Metal Particles In A Condensed Explosive. +Jump up ^ The Army Doctrine and Training Bulletin (2001) The Threat from Blast Weapons. +Jump up ^ INTERNATIONAL DEFENCE REVIEW (2004) ENHANCED BLAST AND THERMOBARICS. +Jump up ^ F. Winterberg Conjectured Metastable Super-Explosives formed under High Pressure for Thermonuclear Ignition. +Jump up ^ Zhang, Fan (Medicine Hat, CA) Murray, Stephen Burke (Medicine Hat, CA) Higgins, Andrew (Montreal, CA) (2005) Super compressed detonation method and device to effect such detonation. +Jump up ^ Nettleton, arch. combust.,1,131, (1981). +Jump up ^ Stephen B. Murray Fundamental and Applied Studies of Fuel-Air Detonation. +Jump up ^ John H. Lee (1992) Chemical initiation of detonation in fuel-air explosive clouds. +Jump up ^ Frank E. Lowther (1989) Nuclear-sized explosions without radiation. +Jump up ^ Nettleton, Comb. and Flame, 24,65 (1975). +Jump up ^ Fire Prev. Sci. and Tech. No. 19,4 (1976) +Jump up ^ May L.Chan (2001) Advanced Thermobaric Explosive Compositions. +Jump up ^ New Thermobaric Materials and Weapon Concepts. +Jump up ^ Robert C. Morris (2003) Small Thermobaric Weapons An Unnoticed Threat.[dead link] +^ Jump up to: a b "Backgrounder on Russian Fuel Air Explosives ("Vacuum Bombs") | Human Rights Watch". Hrw.org. 2000-02-01. Retrieved 2013-04-23. +Jump up ^ Defense Intelligence Agency, "Future Threat to the Soldier System, Volume I; Dismounted Soldier--Middle East Threat", September 1993, p. 73. Obtained by Human Rights Watch under the U.S. Freedom of Information Act. +Jump up ^ "Press | Human Rights Watch". Hrw.org. 2008-12-27. Retrieved 2009-07-30. +Jump up ^ Lester W. Grau and Timothy L. Thomas(2000)"Russian Lessons Learned From the Battles For Grozny" +Jump up ^ "Modern Firearms – GM-94". World.guns.ru. 2011-01-24. Retrieved 2011-07-12. +Jump up ^ "New RPO Shmel-M Infantry Rocket Flamethrower Man-Packable Thermobaric Weapon". defensereview.com. 2006-07-19. Retrieved 2012-08-27. +Jump up ^ "Shmel-M: Infantry Rocket-assisted Flamethrower of Enhanced Range and Lethality". Kbptula.ru. Retrieved 2013-12-28. +Jump up ^ "Modern Firearms – RShG-1". World.guns.ru. 2011-01-24. Retrieved 2011-07-12. +Jump up ^ "Modern Firearms – RMG". World.guns.ru. 2011-01-24. Retrieved 2011-07-12. +Jump up ^ "RMG - A new Multi-Purpose Assault Weapon from Bazalt". defense-update.com. Retrieved 2012-08-27. +Jump up ^ "Kornet-EM: Multi-purpose Long-range Missile System". Kbptula.ru. Retrieved 2013-12-28. +Jump up ^ "TOS-1 Heavy flamethrower system". military-today.com. Retrieved 2012-08-27. +Jump up ^ "SS-26". Missilethreat.com. Retrieved 2013-12-28. +Jump up ^ Air Power Australia (2007-07-04). "How to Destroy the Australian Defence Force". Ausairpower.net. Retrieved 2011-07-12. +Jump up ^ "Russia unveils devastating vacuum bomb". ABC News. 2007. Retrieved 2007-09-12. +Jump up ^ "Video of test explosion". BBC News. 2007. Retrieved 2007-09-12. +Jump up ^ Harding, Luke (2007-09-12). "Russia unveils the father of all bombs". London: The Guardian. Retrieved 2007-09-12. +Jump up ^ Berhie, Saba. "Dropping the Big One | Popular Science". Popsci.com. Retrieved 2011-07-12. +Jump up ^ John Pike (2003-04-22). "XM1060 40mm Thermobaric Grenade". Globalsecurity.org. Retrieved 2011-07-12. +Jump up ^ David Hambling (2005) "Marines Quiet About Brutal New Weapon" +Jump up ^ John Pike (2001-09-11). "AGM-114N Metal Augmented Charge (MAC) Thermobaric Hellfire". Globalsecurity.org. Retrieved 2011-07-12. +^ Jump up to: a b John Pike. "TOS-1 Buratino 220mm Multiple Rocket Launcher". Globalsecurity.org. Retrieved 2013-04-23. +Jump up ^ "Foreign Military Studies Office Publications - A 'Crushing' Victory: Fuel-Air Explosives and Grozny 2000". Fmso.leavenworth.army.mil. Retrieved 2013-04-23. +Jump up ^ "Russian forces faulted in Beslan school tragedy". Christian Science Monitor. 1 September 2006. Retrieved 14 February 2007. +Jump up ^ Russia: Independent Beslan Investigation Sparks Controversy, The Jamestown Foundation, 29 August 2006 +Jump up ^ Beslan still a raw nerve for Russia, BBC News, 1 September 2006 +Jump up ^ ACHING TO KNOW, Los Angeles Times, 27 August 2005 +Jump up ^ Searching for Traces of “Shmel” in Beslan School, Kommersant, 12 September 2005 +Jump up ^ A Reversal Over Beslan Only Fuels Speculation, The Moscow Times, 21 July 2005 +Jump up ^ "MoD's Controversial Thermobaric Weapons Use in Afghanistan". Armedforces-int.com. 2008-06-23. Retrieved 2013-04-23. +Jump up ^ "US Uses Bunker-Busting 'Thermobaric' Bomb for First Time". Commondreams.org. 2002-03-03. Retrieved 2013-04-23. +Jump up ^ John Pike. "BLU-118/B Thermobaric Weapon Demonstration / Hard Target Defeat Program". Globalsecurity.org. Retrieved 2013-04-23. +Jump up ^ "Syria rebels say Assad using 'mass-killing weapons' in Aleppo". October 10, 2012. Retrieved November 11, 2012. +Jump up ^ "Dropping Thermobaric Bombs on Residential Areas in Syria_ Nov. 5. 2012". First Post. November 11, 2012. Retrieved November 11, 2012. +Jump up ^ Cumming-Bruce, Nick (2013-06-04). "U.N. Panel Reports Increasing Brutality by Both Sides in Syria". The New York Times. +Jump up ^ Richard J. Grunawalt. Hospital Ships In The War On Terror: Sanctuaries or Targets? (PDF), Naval War College Review, Winter 2005, pp. 110–11. +Jump up ^ Paul Rogers (2000) "Politics in the Next 50 Years: The Changing Nature of International Conflict" +Jump up ^ J. Gilmore Childers, Henry J. DePippo (February 24, 1998). "Senate Judiciary Committee, Subcommittee on Technology, Terrorism, and Government Information hearing on "Foreign Terrorists in America: Five Years After the World Trade Center"". Fas.org. Retrieved 2011-07-12. +Jump up ^ P. Neuwald, H. Reichenbach, A. L. Kuhl (2003). "Shock-Dispersed-Fuel Charges-Combustion in Chambers and Tunnels". +Jump up ^ David Eshel (2006). "Is the world facing Thermobaric Terrorism?".[dead link] +Jump up ^ Wayne Turnbull (2003). "Bali:Preparations". +External links[edit] +Fuel/Air Explosive (FAE) +Thermobaric Explosive (Global Security) +Aspects of thermobaric weaponry (PDF) – Dr. Anna E Wildegger-Gaissmaier, Australian Defence Force Health +Thermobaric warhead for RPG-7 +XM1060 40 mm Thermobaric Grenade (Global Security) +Defense Update: Fuel-Air Explosive Mine Clearing System +Foreign Military Studies Office – A 'Crushing' Victory: Fuel-Air Explosives and Grozny 2000 +Soon to make a comeback in Afghanistan +Russia claims to have tested the most powerful "Vacuum" weapon +Categories: Explosive weaponsAmmunitionThermobaric weaponsAnti-personnel weapons +Navigation menu +Create accountLog inArticleTalkReadEditView history + +Main page +Contents +Featured content +Current events +Random article +Donate to Wikipedia +Wikimedia Shop +Interaction +Help +About Wikipedia +Community portal +Recent changes +Contact page +Tools +What links here +Related changes +Upload file +Special pages +Permanent link +Page information +Wikidata item +Cite this page +Print/export +Create a book +Download as PDF +Printable version +Languages +العربية +Беларуская +Български +Čeština +Deutsch +Español +فارسی +Français +हिन्दी +Italiano +עברית +Latviešu +Македонски +Nederlands +日本語 +Polski +Русский +Suomi +Svenska +Türkçe +Українська +Tiếng Việt +粵語 +中文 +Edit links +This page was last modified on 28 November 2014 at 10:32. +Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Terms of Use and Privacy Policy. Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc., a non-profit organization. +Privacy policyAbout WikipediaDisclaimersContact WikipediaDevelopersMobile viewWikimedia Foundation Powered by MediaWiki + + +Gunpowder +From Wikipedia, the free encyclopedia +For other uses, see Gunpowder (disambiguation). +In American English, the term gunpowder also refers broadly to any gun propellant.[1] Gunpowder (black powder) as described in this article is not normally used in modern firearms, which instead use smokeless powders. + +Black powder for muzzleloading rifles and pistols in FFFG granulation size. American Quarter (diameter 24 mm) for comparison. +Gunpowder, also known as black powder, is a chemical explosive—the earliest known. It is a mixture of sulfur, charcoal, and potassium nitrate (saltpeter). The sulfur and charcoal act as fuels, and the saltpeter is an oxidizer.[2][3] Because of its burning properties and the amount of heat and gas volume that it generates, gunpowder has been widely used as a propellant in firearms and as a pyrotechnic composition in fireworks. +Gunpowder is assigned the UN number UN0027 and has a hazard class of 1.1D. It has a flash point of approximately 427–464 °C (801–867 °F). The specific flash point may vary based on the specific composition of the gunpowder. Gunpowder's gravity is 1.70–1.82 (mercury method) orŠ 1.92–2.08 (pycnometer), and it has a pH of 6.0–8.0. It is also considered to be an insoluble material.[4] +Gunpowder was, according to prevailing academic consensus, invented in the 9th century in China,[5][6] and the earliest record of a written formula for gunpowder appears in the 11th century Song Dynasty text, Wujing Zongyao.[7] This discovery led to the invention of fireworks and the earliest gunpowder weapons in China. In the centuries following the Chinese discovery, gunpowder weapons began appearing in the Muslim world, Europe, and India. The technology spread from China through the Middle East or Central Asia, and then into Europe.[8] The earliest Western accounts of gunpowder appear in texts written by English philosopher Roger Bacon in the 13th century.[9] +Gunpowder is classified as a low explosive because of its relatively slow decomposition rate and consequently low brisance. Low explosives deflagrate (i.e., burn) at subsonic speeds, whereas high explosives detonate, producing a supersonic wave. Gunpowder's burning rate increases with pressure, so it bursts containers if contained but otherwise just burns in the open. Ignition of the powder packed behind a bullet must generate enough pressure to force it from the muzzle at high speed, but not enough to rupture the gun barrel. Gunpowder thus makes a good propellant, but is less suitable for shattering rock or fortifications. Gunpowder was widely used to fill artillery shells and in mining and civil engineering to blast rock roughly until the second half of the 19th century, when the first high explosives (nitro-explosives) were discovered. Gunpowder is no longer used in modern explosive military warheads, nor is it used as main explosive in mining operations due to its cost relative to that of newer alternatives such as ammonium nitrate/fuel oil (ANFO).[10] Black powder is still used as a delay element in various munitions where its slow-burning properties are valuable. +Formulations used in blasting rock (such as in quarrying) are called blasting powder. +Contents [hide] +1 History +1.1 China +1.2 Middle East +1.3 Mainland Europe +1.4 Britain and Ireland +1.5 India +1.6 Indonesia +2 Manufacturing technology +3 Composition and characteristics +4 Serpentine +5 Corning +6 Modern types +7 Other types of gunpowder +8 Sulfur-free gunpowder +9 Combustion characteristics +9.1 Advantages +9.2 Disadvantages +9.3 Transportation +10 Other uses +11 See also +12 References +13 External links +History[edit] + +Early Chinese rocket + +A Mongol bomb thrown against a charging Japanese samurai during the Mongol invasions of Japan after founding the Yuan Dynasty, 1281. +Main article: History of gunpowder +Gunpowder was invented in China while taoists attempted to create a potion of immortality. Chinese military forces used gunpowder-based weapons (i.e. rockets, guns, cannons) and explosives (i.e. grenades and different types of bombs) against the Mongols when the Mongols attempted to invade and breach city fortifications on China's northern borders. After the Mongols conquered China and founded the Yuan Dynasty, they used the Chinese gunpowder-based weapons technology in their attempted invasion of Japan; they also used gunpowder to fuel rockets. +The mainstream scholarly consensus is that gunpowder was invented in China, spread through the Middle East, and then into Europe,[8] although there is a dispute over how much the Chinese advancements in gunpowder warfare influenced later advancements in the Middle East and Europe.[11][12] The spread of gunpowder across Asia from China is widely attributed to the Mongols. One of the first examples of Europeans encountering gunpowder and firearms is at the Battle of Mohi in 1241. At this battle the Mongols not only used gunpowder in early Chinese firearms but in the earliest grenades as well. +A major problem confronting the study of the early history of gunpowder is ready access to sources close to the events described. Often enough, the first records potentially describing use of gunpowder in warfare were written several centuries after the fact, and may well have been colored by the contemporary experiences of the chronicler.[13] It is also difficult to accurately translate original alchemy texts, especially medieval Chinese texts that try to explain phenomena through metaphor, into modern scientific language with rigidly defined terminology. The translation difficulty has led to errors or loose interpretations bordering on artistic licence.[14][15] Early writings potentially mentioning gunpowder are sometimes marked by a linguistic process where old words acquired new meanings.[16] For instance, the Arabic word naft transitioned from denoting naphtha to denoting gunpowder, and the Chinese word pao evolved from meaning catapult to referring to cannon.[17] According to science and technology historian Bert S. Hall: "It goes without saying, however, that historians bent on special pleading, or simply with axes of their own to grind, can find rich material in these terminological thickets."[18] +China[edit] +Further information: Wujing Zongyao, Four Great Inventions and List of Chinese inventions + +Chinese Ming Dynasty (1368-1644) matchlock firearms +Saltpeter was known to the Chinese by the mid-1st century AD and there is strong evidence of the use of saltpeter and sulfur in various largely medicinal combinations.[19] A Chinese alchemical text dated 492 noted saltpeter burnt with a purple flame, providing a practical and reliable means of distinguishing it from other inorganic salts, thus enabling alchemists to evaluate and compare purification techniques; the earliest Latin accounts of saltpeter purification are dated after 1200.[20] + +Yuan Dynasty bronze hand cannon from 1332 at th (c. 808); it describes mixing six parts sulfur to six parts saltpeter to one part birthwort herb (which would provide carbon).[21] +The first reference to the incendiary properties of such mixtures is the passage of the Zhenyuan miaodao yaolüe, a Taoist text tentatively dated to the mid-9th century AD:[20] "Some have heated together sulfur, realgar and saltpete with honey; smoke and flames result, so that their hands and faces have been burnt, and even the whole house where they were working burned down."[22] The Chinese word for "gunpowder" is Chinese: 火药/火藥; pinyin: huŏ yào /xuou yɑʊ/, which literally means "Fire Medicine";[23] however this name only came into use some centuries after the mixture's discovery.[24] During the 9th century, Taoist monks or alchemists searching for an elixir of immortality had serendipitously stumbled upon gunpowder.[8][25] The Chinese wasted little time in applying gunpowder to the development of weapons, and in the centuries that followed, they produced a variety of gunpowder weapons, including flamethrowers, rockets, bombs, and land mines, before inventing guns as a projectile weapon.[26] Archaeological evidence of a hand cannon has been excavated in Manchuria dated from the late 1200s[27] and the shells of explosive bombs have been discovered in a shipwreck off the shore of Japan dated from 1281, during the Mongol invasions of Japan.[28] +The Chinese "Wu Ching Tsung Yao" (Complete Essentials from the Military Classics), written by Tseng Kung-Liang between 1040–1044, provides encyclopedia references to a variety of mixtures that included petrochemicals—as well as garlic and honey. A slow match for flame throwing mechanisms using the siphon principle and for fireworks and rockets are mentioned. The mixture formulas in this book do not contain enough saltpeter to create an explosive however; being limited to at most 50% saltpeter, they produce an incendiary.[29] The Essentials was however written by a Song Dynasty court bureaucrat, and there's little evidence that it had any immediate impact on warfare; there is no mention of gunpowder use in the chronicles of the wars against the Tanguts in the eleventh century, and China was otherwise mostly at peace during this century. The first chronicled use of "fire spears" (or "fire lances") is at the siege of De'an in 1132.[30] + +Formula for gunpowder in 1044 Wujing zongyao part I vol 12 + + +Instruction for fire bomb in Wujing zongyao + + +Fire bomb + + +Fire grenade + + +Proto-cannon from the Ming Dynasty text Huolongjing + + +Land mine from the Ming Dynasty text Huolongjing + + +Fire arrow rocket launcher from the Wujing zongyao +Middle East[edit] +Main articles: Inventions in the Islamic world and Alchemy and chemistry in Islam + +The Sultani Cannon, a very heavy bronze breech-loading cannon of type used by Ottoman Empire in the conquest of Constantinople, in 1453. +The Muslims acquired knowledge of gunpowder some time between 1240 and 1280, by which time the Syrian Hasan al-Rammah had written, in Arabic, recipes for gunpowder, instructions for the purification of saltpeter, and descriptions of gunpowder incendiaries. Gunpowder arrived in the Middle East, possibly through India, from China. This is implied by al-Rammah's usage of "terms that suggested he derived his knowledge from Chinese sources" and his references to saltpeter as "Chinese snow" Arabic: ثلج الصين‎ thalj al-ṣīn, fireworks as "Chinese flowers" and rockets as "Chinese arrows".[31] However, because al-Rammah attributes his material to "his father and forefathers", al-Hassan argues that gunpowder became prevalent in Syria and Egypt by "the end of the twelfth century or the beginning of the thirteenth".[32] Persians called saltpeter "Chinese salt" [33][34][35][36][37] or "salt from Chinese salt marshes" (namak shūra chīnī Persian: نمک شوره چيني‎).[38][39] + +A picture of a 15th-century Granadian cannon from the book Al-izz wal rifa'a. +Al-Hassan claims that in the Battle of Ain Jalut of 1260, the Mamluks used against the Mongols in "the first cannon in history" gunpowder formula with near-identical ideal composition ratios for explosive gunpowder.[32] Other historians urge caution regarding claims of Islamic firearms use in the 1204-1324 period as late medieval Arabic texts used the same word for gunpowder, naft, that they used for an earlier incendiary, naphtha.[13][17] Khan claims that it was invading Mongols who introduced gunpowder to the Islamic world[40] and cites Mamluk antagonism towards early musketeers in their infantry as an example of how gunpowder weapons were not always met with open acceptance in the Middle East.[41] Similarly, the refusal of their Qizilbash forces to use firearms contributed to the Safavid rout at Chaldiran in 1514.[41] +The earliest surviving documentary evidence for the use of the hand cannon, considered the oldest type of portable firearm and a forerunner of the handgun, are from several Arabic manuscripts dated to the 14th century.[42] Al-Hassan argues that these are based on earlier originals and that they report hand-held cannons being used by the Mamluks at the Battle of Ain Jalut in 1260.[32] +Hasan al-Rammah included 107 gunpowder recipes in his text al-Furusiyyah wa al-Manasib al-Harbiyya (The Book of Military Horsemanship and Ingenious War Devices), 22 of which are for rockets. If one takes the median of 17 of these 22 compositions for rockets (75% nitrates, 9.06% sulfur, and 15.94% carbon), it is nearly identical to the modern reported ideal gunpowder recipe of 75% potassium nitrate, 10% sulfur, and 15% carbon.[32] +The state-controlled manufacture of gunpowder by the Ottoman Empire through early supply chains to obtain nitre, sulfur and high-quality charcoal from oaks in Anatolia contributed significantly to its expansion the 15th and 18th century. It was not until later in the 19th century when the syndicalist production of Turkish gunpowder was greatly reduced, which coincided with the decline of its military might.[43] +Mainland Europe[edit] +Several sources mention Chinese firearms and gunpowder weapons being deployed by the Mongols against European forces at the Battle of Mohi in 1241.[44][45][46] Professor Kenneth Warren Chase credits the Mongols for introducing into Europe gunpowder and its associated weaponry.[47] +C. F. Temler interprets Peter, Bishop of Leon, as reporting the use of cannons in Seville in 1248.[48] +In Europe, one of the first mentions of gunpowder use appears in a passage found in Roger Bacon's Opus Maius and Opus Tertium in what has been interpreted as being firecrackers. The most telling passage reads: "We have an example of these things (that act on the senses) in [the sound and fire of] that children's toy which is made in many [diverse] parts of the world; i.e., a device no bigger than one's thumb. From the violence of that salt called saltpeter [together with sulfur and willow charcoal, combined into a powder] so horrible a sound is made by the bursting of a thing so small, no more than a bit of parchment [containing it], that we find [the ear assaulted by a noise] exceeding the roar of strong thunder, and a flash brighter than the most brilliant lightning."[9] In the early 20th century, British artillery officer Henry William Lovett Hime proposed that another work tentatively attributed to Bacon, Epistola de Secretis Operibus Artis et Naturae, et de Nullitate Magiae contained an encrypted formula for gunpowder. This claim has been disputed by historians of science including Lynn Thorndike, John Maxson Stillman and George Sarton and by Bacon's editor Robert Steele, both in terms of authenticity of the work, and with respect to the decryption method.[9] In any case, the formula claimed to have been decrypted (7:5:5 saltpeter:charcoal:sulfur) is not useful for firearms use or even firecrackers, burning slowly and producing mostly smoke.[49][50] + +Cannon forged in 1667 at the Fortín de La Galera, Nueva Esparta, Venezuela. +The Liber Ignium, or Book of Fires, attributed to Marcus Graecus, is a collection of incendiary recipes, including some gunpowder recipes. Partington dates the gunpowder recipes to approximately 1300.[51] One recipe for "flying fire" (ingis volatilis) involves saltpeter, sulfur, and colophonium, which, when inserted into a reed or hollow wood, "flies away suddenly and burns up everything." Another recipe, for artificial "thunder", specifies a mixture of one pound native sulfur, two pounds linden or willow charcoal, and six pounds of saltpeter.[52] Another specifies a 1:3:9 ratio.[52] +Some of the gunpowder recipes of De Mirabilibus Mundi of Albertus Magnus are identical to the recipes of the Liber Ignium, and according to Partington, "may have been taken from that work, rather than conversely."[53] Partington suggests that some of the book may have been compiled by Albert's students, "but since it is found in thirteenth century manuscripts, it may well be by Albert."[53] Albertus Magnus died in 1280. +A common German folk-tale is of the German priest/monk named Berthold Schwarz who independently invented gunpowder, thus earning it the German name Schwarzpulver or in English Schwarz's powder. Schwarz is also German for black so this folk-tale, while likely containing elements of truth, is considered problematic. +A major advance in manufacturing began in Europe in the late 14th century when the safety and thoroughness of incorporation was improved by wet grinding; liquid, such as distilled spirits or perhaps the urine of wine-drinking bishops[54] was added during the grinding-together of the ingredients and the moist paste dried afterwards. (The principle of wet mixing to prevent the separation of dry ingredients, invented for gunpowder, is used today in the pharmaceutical industry.[55]) It was also discovered that if the paste was rolled into balls before drying the resulting gunpowder absorbed less water from the air during storage and traveled better. The balls were then crushed in a mortar by the gunner immediately before use, with the old problem of uneven particle size and packing causing unpredictable results. +If the right size particles were chosen, however, the result was a great improvement in power. Forming the damp paste into corn-sized clumps by hand or with the use of a sieve instead of larger balls produced a product after drying that loaded much better, as each tiny piece provided its own surrounding air space that allowed much more rapid combustion than a fine powder. This "corned" gunpowder was from 30% to 300% more powerful. An example is cited where 34 pounds of serpentine was needed to shoot a 47 pound ball, but only 18 pounds of corned powder.[54] The optimum size of the grain depended on its use; larger for large cannon, finer for small arms. Larger cast cannons were easily muzzle-loaded with corned powder using a long-handled ladle. Corned powder also retained the advantage of low moisture absorption, as even tiny grains still had much less surface area to attract water than a floury powder. +During this time, European manufacturers also began regularly purifying saltpeter, using wood ashes containing potassium carbonate to precipitate calcium from their dung liquor, and using ox blood, alum, and slices of turnip to clarify the solution.[54] +Gunpowder-making and metal-smelting and casting for shot and cannon fee was closely held by skilled military tradesmen, who formed guilds that collected dues, tested apprentices, and gave pensions. "Fire workers" were also required to craft fireworks for celebrations of victory or peace. During the Renaissance, two European schools of pyrotechnic thought emerged, one in Italy and the other at Nuremberg, Germany. Vannoccio Biringuccio, born in 1480, was a member of the guild Fraternita di Santa Barbara but broke with the tradition of secrecy by setting down everything he knew in a book titled De la pirotechnia, written in vernacular. The first printed book on either gunpowder or metalworking, it was published posthumously in 1540, with 9 editions over 138 years, and also reprinted by MIT Press in 1966.[54] By the mid-17th century fireworks were used for entertainment on an unprecedented scale in Europe, being popular even at resorts and public gardens.[56] +In 1774 Louis XVI ascended to the throne of France at age 20. After he discovered that France was not self-sufficient in gunpowder, a Gunpowder Administration was established; to head it, the lawyer Antoine Lavoisier was appointed. Although from a bourgeois family, after his degree in law Lavoisier became wealthy from a company set up to collect taxes for the Crown; this allowed him to pursue experimental natural science as a hobby.[57] +Without access to cheap Indian saltpeter (controlled by the British), for hundreds of years France had relied on saltpetermen with royal warrants, the droit de fouille or "right to dig", to seize nitrous-containing soil and demolished walls of barnyards, without compensation to the owners.[58] This caused farmers, the wealthy, or entire villages to bribe the petermen and the associated bureaucracy to leave their buildings alone and the saltpeter uncollected. Lavoisier instituted a crash program to increase saltpeter production, revised (and later eliminated) the droit de fouille, researched best refining and powder manufacturing methods, instituted management and record-keeping, and established pricing that encouraged private investment in works. Although saltpeter from new Prussian-style putrefaction works had not been produced yet (the process taking about 18 months), in only a year France had gunpowder to export. A chief beneficiary of this surplus was the American Revolution. By careful testing and adjusting the proportions and grinding time, powder from mills such as at Essonne outside Paris became the best in the world by 1788, and inexpensive.[58] [59] +Britain and Ireland[edit] + +The old Powder or Pouther magazine dating from 1642, built by order of Charles I. Irvine, North Ayrshire, Scotland +Gunpowder production in Britain appears to have started in the mid 14th century AD with the aim of supplying the English Crown.[60] Records show that gunpowder was being made, in England, in 1346, at the Tower of London; a powder house existed at the Tower in 1461; and in 1515 three King's gunpowder makers worked there.[60] Gunpowder was also being made or stored at other Royal castles, such as Portchester. By the early 14th century, according to N.J.G. Pounds's study The Medieval Castle in England and Wales, many English castles had been deserted and others were crumbling. Their military significance faded except on the borders. Gunpowder had made smaller castles useless.[61] +Henry VIII of England was short of gunpowder when he invaded France in 1544 and England needed to import gunpowder via the port of Antwerp in what is now Belgium.[60] +The English Civil War (1642–1645) led to an expansion of the gunpowder industry, with the repeal of the Royal Patent in August 1641.[60] +Two British physicists, Andrew Noble and Frederick Abel, worked to improve the properties of black powder during the late 19th century. This formed the basis for the Noble-Abel gas equation for internal ballistics.[62] +The introduction of smokeless powder in the late 19th century led to a contraction of the gunpowder industry. After the end of World War I, the majority of the United Kingdom gunpowder manufacturers merged into a single company, "Explosives Trades limited"; and number of sites were closed down, including those in Ireland. This company became Nobel Industries Limited; and in 1926 became a founding member of Imperial Chemical Industries. The Home Office removed gunpowder from its list of Permitted Explosives; and shortly afterwards, on 31 December 1931, the former Curtis & Harvey's Glynneath gunpowder factory at Pontneddfechan, in Wales, closed down, and it was demolished by fire in 1932.[63] + +Gunpowder storing barrels at Martello tower in Point Pleasant Park +The last remaining gunpowder mill at the Royal Gunpowder Factory, Waltham Abbey was damaged by a German parachute mine in 1941 and it never reopened.[64] This was followed by the closure of the gunpowder section at the Royal Ordnance Factory, ROF Chorley, the section was closed and demolished at the end of World War II; and ICI Nobel's Roslin gunpowder factory, which closed in 1954.[64][65] +This left the sole United Kingdom gunpowder factory at ICI Nobel's Ardeer site in Scotland; it too closed in October 1976.[64] Since then gunpowder has been imported into the United Kingdom. In the late 1970s/early 1980s gunpowder was bought from eastern Europe, particularly from what was then the German Democratic Republic and former Yugoslavia. +India[edit] + +In the year 1780 the British began to annex the territories of the Sultanate of Mysore, during the Second Anglo-Mysore War. The British battalion was defeated during the Battle of Guntur, by the forces of Hyder Ali, who effectively utilized Mysorean rockets and Rocket artillery against the closely massed British forces. + +Mughal Emperor Shah Jahan, hunting deer using a Matchlock as the sun sets in the horizon. +Gunpowder and gunpowder weapons were transmitted to India through the Mongol invasions of India.[66][67] The Mongols were defeated by Alauddin Khilji of the Delhi Sultanate, and some of the Mongol soldiers remained in northern India after their conversion to Islam.[67] It was written in the Tarikh-i Firishta (1606–1607) that Nasir ud din Mahmud the ruler of the Delhi Sultanate presented the envoy of the Mongol ruler Hulegu Khan with a dazzling pyrotechnics display upon his arrival in Delhi in 1258 AD. Nasir ud din Mahmud tried to express his strength as a ruler and tried to ward off any Mongol attempt similar to the Siege of Baghdad (1258).[68] Firearms known as top-o-tufak also existed in many Muslim kingdoms in India by as early as 1366 AD.[68] From then on the employment of gunpowder warfare in India was prevalent, with events such as the "Siege of Belgaum" in 1473 by Sultan Muhammad Shah Bahmani.[69] +The shipwrecked Ottoman Admiral Seydi Ali Reis is known to have introduced the earliest type of Matchlock weapons, which the Ottomans used against the Portuguese during the Siege of Diu (1531). After that, a diverse variety of firearms; large guns in particular, became visible in Tanjore, Dacca, Bijapur, and Murshidabad.[70] Guns made of bronze were recovered from Calicut (1504)- the former capital of the Zamorins[71] +The Mughal Emperor Akbar mass-produced matchlocks for the Mughal Army. Akbar is personally known to have shot a leading Rajput commander during the Siege of Chittorgarh.[72] The Mughals began to use Bamboo rockets (mainly for signalling) and employ Sappers: special units that undermined heavy stone fortifications to plant gunpowder charges. +The Mughal Emperor Shah Jahan is known to have introduced much more advanced Matchlocks, their designs were a combination of Ottoman and Mughal designs. Shah Jahan also countered the British and other Europeans in his province of Gujarāt, which supplied Europe saltpeter for use in gunpowder warfare during the 17th century.[73] Bengal and Mālwa participated in saltpeter production.[73] The Dutch, French, Portuguese, and English used Chhapra as a center of saltpeter refining.[73] +Ever since the founding of the Sultanate of Mysore by Hyder Ali, French military officers were employed to train the Mysore Army. Hyder Ali and his son Tipu Sultan were the first to introduce modern Cannons and Muskets, their army was also the first in India to have official uniforms. During the Second Anglo-Mysore War Hyder Ali and his son Tipu Sultan unleashed the Mysorean rockets at their British opponents effectively defeating them on various occasions. The Mysorean rockets inspired the development of the Congreve rocket, which the British widely utilized during the Napoleonic Wars and the War of 1812.[74] +Indonesia[edit] +The Javanese Majapahit Empire was arguably able to encompass much of modern day Indonesia due to its unique mastery of bronze smithing and use of a central arsenal fed by a large number of cottage industries within the immediate region. Documentary and archeological evidence indicate that Arab or Indian traders introduced gunpowder, gonnes, muskets, blunderbusses, and cannons to the Javanese, Acehnese, and Batak via long established commercial trade routes around the early to mid 14th century CE.[75] Portuguese and Spanish invaders were unpleasantly surprised and occasionally even outgunned on occasion.[76] The resurgent Singhasari Empire overtook Sriwijaya and later emerged as the Majapahit whose warfare featured the use of fire-arms and cannonade.[77] Circa 1540 CE the Javanese, always alert for new weapons found the newly arrived Portuguese weaponry superior to that of the locally made variants. Javanese bronze breech-loaded swivel-guns, known as meriam, or erroneously as lantaka, was used widely by the Majapahit navy as well as by pirates and rival lords. The demise of the Majapahit empire and the dispersal of disaffected skilled bronze cannon-smiths to Brunei, modern Sumatra, Malaysia and the Philippines lead to widespread use, especially in the Makassar Strait. +Saltpeter harvesting was recorded by Dutch and German travelers as being common in even the smallest villages and was collected from the decomposition process of large dung hills specifically piled for the purpose. The Dutch punishment for possession of non-permitted gunpowder appears to have been amputation.[78] Ownership and manufacture of gunpowder was later prohibited by the colonial Dutch occupiers.[75] According to a colonel McKenzie quoted in Sir Thomas Stamford Raffles, The History of Java (1817), the purest sulfur was supplied from a crater from a mountain near the straits of Bali.[77] +Manufacturing technology[edit] + +Edge-runner mill in a restored mill, at Eleutherian Mills +For the most powerful black powder meal, a wood charcoal is used. The best wood for the purpose is Pacific willow,[79] but others such as alder or buckthorn can be used. In Great Britain between the 15th to 19th centuries charcoal from alder buckthorn was greatly prized for gunpowder manufacture; cottonwood was used by the American Confederate States.[80] The ingredients are reduced in particle size and mixed as intimately as possible. Originally this was with a mortar-and-pestle or a similarly operating stamping-mill, using copper, bronze or other non-sparking materials, until supplanted by the rotating ball mill principle with non-sparking bronze or lead. Historically, a marble or limestone edge runner mill, running on a limestone bed was used in Great Britain; however, by the mid 19th century AD this had changed to either an iron shod stone wheel or a cast iron wheel running on an iron bed.[81] The mix was dampened with alcohol or water during grinding to prevent accidental ignition. This also helps the extremely soluble saltpeter mix into the microscopic nooks and crannies of the very high surface-area charcoal. +Around the late 14th century AD, European powdermakers first began adding liquid during grinding to improve mixing, reduce dust, and with it the risk of explosion.[82] The powder-makers would then shape the resulting paste of dampened gunpowder, known as mill cake, into corns, or grains, to dry. Not only did corned powder keep better because of its reduced surface area, gunners also found that it was more powerful and easier to load into guns. Before long, powder-makers standardized the process by forcing mill cake through sieves instead of corning powder by hand. +The improvement was based on reducing the surface area of a higher density composition. At the beginning of the 19th century, makers increased density further by static pressing. They shoveled damp mill cake into a two-foot square box, placed this beneath a screw press and reduced it to 1/2 its volume. "Presscake" had the hardness of slate. They broke the dried slabs with hammers or rollers, and sorted the granules with sieves into different grades. In the United States, Irenee du Pont, who had learned the trade from Lavoisier, tumbled the dried grains in rotating barrels to round the edges and increase durability during shipping and handling. (Sharp grains rounded off in transport, producing fine "meal dust" that changed the burning properties.) +Another advance was the manufacture of kiln charcoal by distilling wood in heated iron retorts instead of burning it in earthen pits. Controlling the temperature influenced the power and consistency of the finished gunpowder. In 1863, in response to high prices for Indian saltpeter, DuPont chemists developed a process using potash or mined potassium chloride to convert plentiful Chilean sodium nitrate to potassium nitrate.[83] +During the 18th century gunpowder factories became increasingly dependent on mechanical energy.[84] Despite mechanization, production difficulties related to humidity control, especially during the pressing, were still present in the late 19th century. A paper from 1885 laments that "Gunpowder is such a nervous and sensitive spirit, that in almost every process of manufacture it changes under our hands as the weather changes." Pressing times to the desired density could vary by factor of three depending on the atmospheric humidity.[85] +Composition and characteristics[edit] +The term black powder was coined in the late 19th century, primarily in the United States, to distinguish prior gunpowder formulations from the new smokeless powders and semi-smokeless powders, in cases where these are not referred to as cordite. Semi-smokeless powders featured bulk volume properties that approximated black powder, but had significantly reduced amounts of smoke and combustion products. Smokeless powder has different burning properties (pressure vs. time) and can generate higher pressures and work per gram. This can rupture older weapons designed for black powder. Smokeless powders ranged in color from brownish tan to yellow to white. Most of the bulk semi-smokeless powders ceased to be manufactured in the 1920s.[86][87][88] +Black powder is a granular mixture of +a nitrate, typically potassium nitrate (KNO3), which supplies oxygen for the reaction; +charcoal, which provides carbon and other fuel for the reaction, simplified as carbon (C); +sulfur (S), which, while also serving as a fuel, lowers the temperature required to ignite the mixture, thereby increasing the rate of combustion. +Potassium nitrate is the most important ingredient in terms of both bulk and function because the combustion process releases oxygen from the potassium nitrate, promoting the rapid burning of the other ingredients.[89] To reduce the likelihood of accidental ignition by static electricity, the granules of modern black powder are typically coated with graphite, which prevents the build-up of electrostatic charge. +Charcoal does not consist of pure carbon; rather, it consists of partially pyrolyzed cellulose, in which the wood is not completely decomposed. Carbon differs from charcoal. Whereas charcoal's autoignition temperature is relatively low, carbon's is much greater. Thus, a black powder composition containing pure carbon would burn similarly to a match head, at best.[90] +The current standard composition for the black powders that are manufactured by pyrotechnicians was adopted as long ago as 1780. Proportions by weight are 75% potassium nitrate (known as saltpeter or saltpetre), 15% softwood charcoal, and 10% sulfur.[81] These ratios have varied over the centuries and by country, and can be altered somewhat depending on the purpose of the powder. For instance, power grades of black powder, unsuitable for use in firearms but adequate for blasting rock in quarrying operations, is called blasting powder rather than gunpowder with standard proportions of 70% nitrate, 14% charcoal, and 16% sulfur; blasting powder may be made with the cheaper sodium nitrate substituted for potassium nitrate and proportions may be as low as 40% nitrate, 30% charcoal, and 30% sulfur.[91] In 1857, Lamont DuPont solved the main problem of using cheaper sodium nitrate formulations when he patented DuPont "B" Blasting powder. After manufacturing grains from press-cake in the usual way, his process tumbled the powder with graphite dust for 12 hours. This formed a graphite coating on each grain that reduced its ability to absorb moisture.[92] +French war powder in 1879 used the ratio 75% saltpeter, 12.5% charcoal, 12.5% sulfur. English war powder in 1879 used the ratio 75% saltpeter, 15% charcoal, 10% sulfur.[93] The British Congreve rockets used 62.4% saltpeter, 23.2% charcoal and 14.4% sulfur, but the British Mark VII gunpowder was changed to 65% saltpeter, 20% charcoal and 15% sulfur.[94] The explanation for the wide variety in formulation relates to usage. Powder used for rocketry can use a slower burn rate since it accelerates the projectile for a much longer time—whereas powders for weapons such as flintlocks, cap-locks, or matchlocks need a higher burn rate to accelerate the projectile in a much shorter distance. Cannons usually used lower burn rate powders, because most would burst with higher burn rate powders. +Serpentine[edit] +The original dry-compounded powder used in fifteenth-century Europe was known as "Serpentine", either a reference to Satan[95] or to a common artillery piece that used it.[96] The ingredients were ground together with a mortar and pestle, perhaps for 24 hours,[96] resulting in a fine flour. Vibration during transportation could cause the components to separate again, requiring remixing in the field. Also if the quality of the saltpeter was low (for instance if it was contaminated with highly hygroscopic calcium nitrate), or if the powder was simply old (due to the mildly hygroscopic nature of potassium nitrate), in humid weather it would need to be re-dried. The dust from "repairing" powder in the field was a major hazard. +Loading cannons or bombards before the powder-making advances of the Renaissance was a skilled art. Fine powder loaded haphazardly or too tightly would burn incompletely or too slowly. Typically, the breech-loading powder chamber in the rear of the piece was filled only about half full, the serpentine powder neither too compressed nor too loose, a wooden bung pounded in to seal the chamber from the barrel when assembled, and the projectile placed on. A carefully determined empty space was necessary for the charge to burn effectively. When the cannon was fired through the touchhole, turbulence from the initial surface combustion caused the rest of the powder to be rapidly exposed to the flame.[96] +The advent of much more powerful and easy to use corned powder changed this procedure, but serpentine was used with older guns into the seventeenth century.[97] +Corning[edit] +For gunpowder to explode effectively, the combustible ingredients must be reduced to the smallest possible particle sizes, and thoroughly mixed as possible. Once mixed, however, for better results in a gun, makers discovered that the final product should be in the form of individual, dense, grains that spread the fire quickly from grain to grain, much as straw or twigs catch fire more quickly than a pile of sawdust. +Primarily for safety reasons, size reduction and mixing is done while the ingredients are damp, usually with water. After 1800, instead of forming grains by hand or with sieves, the damp mill-cake was pressed in molds to increase its density and extract the liquid, forming press-cake. The pressing took varying amounts of time, depending on conditions such as atmospheric humidity. The hard, dense product was broken again into tiny pieces, which were separated with sieves to produce a uniform product for each purpose: coarse powders for cannons, finer grained powders for muskets, and the finest for small hand guns and priming.[97] Inappropriately fine-grained powder often caused cannons to burst before the projectile could move down the barrel, due to the high initial spike in pressure.[98] Mammoth powder with large grains made for Rodman's 15-inch cannon reduced the pressure to only 20 percent as high as ordinary cannon powder would have produced.[99] +In the mid-nineteenth century, measurements were made determining that the burning rate within a grain of black powder (or a tightly packed mass) is about 0.20 fps, while the rate of ignition propagation from grain to grain is around 30 fps, over two orders of magnitude faster.[97] +Modern types[edit] +Modern corning first compresses the fine black powder meal into blocks with a fixed density (1.7 g/cm³).[100] In the United States, gunpowder grains were designated F (for fine) or C (for coarse). Grain diameter decreased with a larger number of Fs and increased with a larger number of Cs, ranging from about 2 mm for 7F to 15 mm for 7C. Even larger grains were produced for artillery bore diameters greater than about 17 cm (6.7 in). The standard DuPont Mammoth powder developed by Thomas Rodman and Lammot du Pont for use during the American Civil War had grains averaging 0.6 inches diameter, with edges rounded in a glazing barrel.[99] Other versions had grains the size of golf and tennis balls for use in 20-inch (50-cm) Rodman guns.[101] In 1875 DuPont introduced Hexagonal powder for large artillery, which was pressed using shaped plates with a small center core—about 1.5 inches diameter, like a wagon wheel nut, the center hole widened as the grain burned.[102] By 1882 German makers also produced hexagonal grained powders of a similar size for artillery.[102] +By the late 19th century manufacturing focused on standard grades of black powder from Fg used in large bore rifles and shotguns, through FFg (medium and small-bore arms such as muskets and fusils), FFFg (small-bore rifles and pistols), and FFFFg (extreme small bore, short pistols and most commonly for priming flintlocks).[103] A coarser grade for use in military artillery blanks was designated A-1. These grades were sorted on a system of screens with oversize retained on a mesh of 6 wires per inch, A-1 retained on 10 wires per inch, Fg retained on 14, FFg on 24, FFFg on 46, and FFFFg on 60. Fines designated FFFFFg were usually reprocessed to minimize explosive dust hazards.[104] In the United Kingdom, the main service gunpowders were classified RFG (rifle grained fine) with diameter of one or two millimeters and RLG (rifle grained large) for grain diameters between two and six millimeters.[101] Gunpowder grains can alternatively be categorized by mesh size: the BSS sieve mesh size, being the smallest mesh size, which retains no grains. Recognized grain sizes are Gunpowder G 7, G 20, G 40, and G 90. +Owing to the large market of antique and replica black-powder firearms in the US, modern gunpowder substitutes like Pyrodex, Triple Seven and Black Mag3[105] pellets have been developed since the 1970s. These products, which should not be confused with smokeless powders, aim to produce less fouling (solid residue), while maintaining the traditional volumetric measurement system for charges. Claims of less corrosiveness of these products have been controversial however. New cleaning products for black-powder guns have also been developed for this market.[103] +Other types of gunpowder[edit] +Besides black powder, there are other historically important types of gunpowder. "Brown gunpowder" is cited as composed of 79% nitre, 3% sulfur, and 18% charcoal per 100 of dry powder, with about 2% moisture. Prismatic Brown Powder is a large-grained product the Rottweil Company introduced in 1884 in Germany, which was adopted by the British Royal Navy shortly thereafter. The French navy adopted a fine, 3.1 millimeter, not prismatic grained product called Slow Burning Cocoa (SBC) or "cocoa powder". These brown powders reduced burning rate even further by using as little as 2 percent sulfur and using charcoal made from rye straw that had not been completely charred, hence the brown color.[102] +Lesmok powder was a product developed by DuPont in 1911[106] one of several semi-smokeless products in the industry containing a mixture of black and nitrocellulose powder. It was sold to Winchester and others primarily for .22 and .32 small calibers. Its advantage was that it was believed at the time to be less corrosive than smokeless powders then in use. It was not understood in the U.S. until the 1920s that the actual source of corrosion was the potassium chloride residue from potassium chlorate sensitized primers. The bulkier black powder fouling better disperses primer residue. Failure to mitigate primer corrosion by dispersion caused the false impression that nitrocellulose-based powder caused corrosion.[107] Lesmok had some of the bulk of black powder for dispersing primer residue, but somewhat less total bulk than straight black powder, thus requiring less frequent bore cleaning.[108] It was last sold by Winchester in 1947. +Sulfur-free gunpowder[edit] + +Burst barrel of a muzzle loader pistol replica, which was loaded with nitrocellulose powder instead of black powder and couldn't withstand the higher pressures of the modern propellant +The development of smokeless powders, such as cordite, in the late 19th century created the need for a spark-sensitive priming charge, such as gunpowder. However, the sulfur content of traditional gunpowders caused corrosion problems with Cordite Mk I and this led to the introduction of a range of sulfur-free gunpowders, of varying grain sizes.[64] They typically contain 70.5 parts of saltpeter and 29.5 parts of charcoal.[64] Like black powder, they were produced in different grain sizes. In the United Kingdom, the finest grain was known as sulfur-free mealed powder (SMP). Coarser grains were numbered as sulfur-free gunpowder (SFG n): 'SFG 12', 'SFG 20', 'SFG 40' and 'SFG 90', for example; where the number represents the smallest BSS sieve mesh size, which retained no grains. +Sulfur's main role in gunpowder is to decrease the ignition temperature. A sample reaction for sulfur-free gunpowder would be +6 KNO3 + C7H4O → 3 K2CO3 + 4 CO2 + 2 H2O + 3 N2 +Combustion characteristics[edit] +A simple, commonly cited, chemical equation for the combustion of black powder is +2 KNO3 + S + 3 C → K2S + N2 + 3 CO2. +A balanced, but still simplified, equation is[109] +10 KNO3 + 3 S + 8 C → 2 K2CO3 + 3 K2SO4 + 6 CO2 + 5 N2. +Although charcoal's chemical formula varies, it can be best summed up by its empirical formula: C7H4O. +Therefore, an even more accurate equation of the decomposition of regular black powder with the use of sulfur can be described as: +6 KNO3 + C7H4O + 2 S → K2CO3 + K2SO4 + K2S + 4 CO2 + 2 CO + 2 H2O + 3 N2 +Black powder without the use of sulfur: +10 KNO3 + 2 C7H4O → 5 K2CO3 + 4 CO2 + 5 CO + 4 H2O + 5 N2 +The burning of gunpowder does not take place as a single reaction, however, and the byproducts are not easily predicted. One study's results showed that it produced (in order of descending quantities) 55.91% solid products: potassium carbonate, potassium sulfate, potassium sulfide, sulfur, potassium nitrate, potassium thiocyanate, carbon, ammonium carbonate and 42.98% gaseous products: carbon dioxide, nitrogen, carbon monoxide, hydrogen sulfide, hydrogen, methane, 1.11% water. +Black powder made with less-expensive and more plentiful sodium nitrate (in appropriate proportions) works just as well but is more hygroscopic than powders made from Potassium nitrate—popularly known as saltpeter. Because corned black powder grains made with saltpeter are less affected by moisture in the air, they can be stored unsealed without degradation by humidity. Muzzleloaders have been known to fire after hanging on a wall for decades in a loaded state, provided they remained dry. By contrast, black powder made with sodium nitrate must be kept sealed to remain stable. +Gunpowder contains 3 megajoules per kilogram, and contains its own oxidant. For comparison, the energy density of TNT is 4.7 megajoules per kilogram, and the energy density of gasoline is 47.2 megajoules per kilogram. Gunpowder is a low explosive and as such it does not detonate; rather it deflagrates. Since it contains its own oxidizer and additionally burns faster under pressure, its combustion is capable of rupturing containers such as shell, grenade, or improvised "pipe bomb" or "pressure cooker" casings, forming shrapnel. +Advantages[edit] +In quarrying, high explosives are generally preferred for shattering rock. However, because of its low brisance, black powder causes fewer fractures and results in more usable stone compared to other explosives, making black powder useful for blasting monumental stone such as granite and marble. Black powder is well suited for blank rounds, signal flares, burst charges, and rescue-line launches. Black powder is also used in fireworks for lifting shells, in rockets as fuel, and in certain special effects. +Disadvantages[edit] +Black powder has a low energy density compared to modern "smokeless" powders, and thus to achieve high energy loadings, large amounts of black powder are needed with heavy projectiles. Black powder also produces thick smoke as a byproduct, which in military applications may give a soldier's location away to an enemy observer and may also impair aiming for additional shots. +Combustion converts less than half the mass of black powder to gas. The rest ends up as a thick layer of soot inside the barrel. In addition to being a nuisance, the residue from burnt black powder is hygroscopic and with the addition of moisture absorbed from the air, this residue forms a caustic substance. The soot contains potassium oxide or sodium oxide that turns into potassium hydroxide, or sodium hydroxide, which corrodes wrought iron or steel gun barrels. Black powder arms must be well cleaned both inside and out to remove the residue. The matchlock musket or pistol (an early gun ignition system), as well as the flintlock would often be unusable in wet weather, due to powder in the pan being exposed and dampened. Because of this unreliability, soldiers carrying muskets, known as musketeers, were armed with additional weapons such as swords or pikes. The bayonet was developed to allow the musket to be used as a pike, thus eliminating the need for the soldier to carry a secondary weapon. +Transportation[edit] +The United Nations Model Regulations on the Transportation of Dangerous Goods and national transportation authorities, such as United States Department of Transportation, have classified gunpowder (black powder) as a Group A: Primary explosive substance for shipment because it ignites so easily. Complete manufactured devices containing black powder are usually classified as Group D: Secondary detonating substance, or black powder, or article containing secondary detonating substance, such as firework, class D model rocket engine, etc., for shipment because they are harder to ignite than loose powder. As explosives, they all fall into the category of Class 1. +Other uses[edit] +Besides its use as an explosive, gunpowder has been occasionally employed for other purposes; after the Battle of Aspern-Essling (1809), the surgeon of the Napoleonic Army Larrey combated the lack of food for the wounded under his care by preparing a bouillon of horse meat seasoned with gunpowder for lack of salt.[110][111] It was also used for sterilizing on ships when there was no alcohol. +Jack Tars (British sailors) used gunpowder to create tattoos when ink wasn't available, by pricking the skin and rubbing the powder into the wound in a method known as traumatic tattooing.[112] +Christiaan Huygens experimented with gunpowder in 1673 in an early attempt to build an internal combustion engine, but he did not succeed. Modern attempts to recreate his invention were similarly unsuccessful. +Fireworks use gunpowder as lifting and burst charges, although sometimes other more powerful compositions are added to the burst charge to improve performance in small shells or provide a louder report. Most modern firecrackers no longer contain black powder. +Beginning in the 1930s, gunpowder or smokeless powder was used in rivet guns, stun guns for animals, cable splicers and other industrial construction tools.[113] The "stud gun" drove nails or screws into solid concrete, a function not possible with hydraulic tools. See Powder-actuated tool. Shotguns have been used to eliminate persistent material rings in operating rotary kilns (such as those for cement, lime, phosphate, etc.) and clinker in operating furnaces, and commercial tools make the method more reliable.[114] +Near London in 1853, Captain Shrapnel demonstrated a method for crushing gold-bearing ores by firing them from a cannon into an iron chamber, and "much satisfaction was expressed by all present". He hoped it would be useful on the goldfields of California and Australia. Nothing came of the invention, as continuously-operating crushing machines that achieved more reliable comminution were already coming into use.[115] +See also[edit] +Ballistics +Black powder substitute +Faversham explosives industry +Bulk loaded liquid propellants +Gunpowder magazine +Gunpowder Plot +Berthold Schwarz +Gunpowder warfare +History of gunpowder +Technology of the Song Dynasty +References[edit] +Jump up ^ http://www.merriam-webster.com/dictionary/gunpowder +Jump up ^ Jai Prakash Agrawal (2010). High Energy Materials: Propellants, Explosives and Pyrotechnics. Wiley-VCH. p. 69. ISBN 978-3-527-32610-5. +Jump up ^ David Cressy, Saltpeter: The Mother of Gunpowder (Oxford University Press, 2013) +Jump up ^ Owen Compliance Services. "Black Powder". Material Safety Data Sheet. Retrieved 31 August 2014. +Jump up ^ http://www.history.com/shows/ancient-discoveries/articles/who-built-it-first-2 +Jump up ^ http://chemistry.about.com/od/historyofchemistry/a/gunpowder.htm +Jump up ^ Chase 2003:31 : "the earliest surviving formulas for gunpowder can be found in the Wujing zongyao, a military work from around 1040" +^ Jump up to: a b c Buchanan 2006, p. 2 "With its ninth century AD origins in China, the knowledge of gunpowder emerged from the search by alchemists for the secrets of life, to filter through the channels of Middle Eastern culture, and take root in Europe with consequences that form the context of the studies in this volume." +^ Jump up to: a b c Joseph Needham; Gwei-Djen Lu; Ling Wang (1987). Science and civilisation in China, Volume 5, Part 7. Cambridge University Press. pp. 48–50. ISBN 978-0-521-30358-3. +Jump up ^ Hazel Rossotti (2002). Fire: Servant, Scourge, and Enigma. Courier Dover Publications. pp. 132–137. ISBN 978-0-486-42261-9. +Jump up ^ Jack Kelly Gunpowder: Alchemy, Bombards, and Pyrotechnics: The History of the Explosive that Changed the World, Perseus Books Group: 2005, ISBN 0-465-03722-4, ISBN 978-0-465-03722-3: 272 pages +Jump up ^ St. C. Easton: "Roger Bacon and his Search for a Universal Science", Oxford (1962) +^ Jump up to: a b Gábor Ágoston (2005). Guns for the sultan: military power and the weapons industry in the Ottoman Empire. Cambridge University Press. p. 15. ISBN 978-0-521-84313-3. +Jump up ^ Ingham-Brown, George (1989) The Big Bang: A History of Explosives, Sutton Publishers, ISBN 0-7509-1878-0, ISBN 978-0-7509-1878-7, page vi +Jump up ^ Kelly, Jack (2005) Gunpowder: Alchemy, Bombards, and Pyrotechnics: The History of the Explosive that Changed the World, Perseus Books Group, ISBN 0-465-03722-4, ISBN 978-0-465-03722-3, page 22 +Jump up ^ Bert S. Hall, "Introduction, 1999" pp. xvi–xvii to the reprinting of James Riddick Partington (1960). A history of Greek fire and gunpowder. JHU Press. ISBN 978-0-8018-5954-0. +^ Jump up to: a b Peter Purton (2009). A History of the Late Medieval Siege, 1200–1500. Boydell & Brewer. pp. 108–109. ISBN 978-1-84383-449-6. +Jump up ^ Bert S. Hall, "Introduction, 1999" p. xvii to the reprinting of James Riddick Partington (1960). A history of Greek fire and gunpowder. JHU Press. ISBN 978-0-8018-5954-0. +Jump up ^ Buchanan. "Editor's Introduction: Setting the Context", in Buchanan 2006. +^ Jump up to: a b Chase 2003:31–32 +Jump up ^ Lorge, Peter A. (2008). The Asian military revolution, 1300-2000 : from gunpowder to the bomb (1. publ. ed.). Cambridge: Cambridge University Press. p. 32. ISBN 978052160954-8. +Jump up ^ Kelly 2004:4 +Jump up ^ The Big Book of Trivia Fun, Kidsbooks, 2004 +Jump up ^ Peter Allan Lorge (2008), The Asian military revolution: from gunpowder to the bomb, Cambridge University Press, p. 18, ISBN 978-0-521-60954-8 +Jump up ^ Needham 1986, p. 7 "Without doubt it was in the previous century, around +850, that the early alchemical experiments on the constituents of gunpowder, with its self-contained oxygen, reached their climax in the appearance of the mixture itself." +Jump up ^ Chase 2003:1 "The earliest known formula for gunpowder can be found in a Chinese work dating probably from the 800s. The Chinese wasted little time in applying it to warfare, and they produced a variety of gunpowder weapons, including flamethrowers, rockets, bombs, and land mines, before inventing firearms." +Jump up ^ Chase 2003:1 +Jump up ^ Delgado, James (February 2003). "Relics of the Kamikaze". Archaeology (Archaeological Institute of America) 56 (1). +Jump up ^ Chase 2003:31 +Jump up ^ Peter Allan Lorge (2008), The Asian military revolution: from gunpowder to the bomb, Cambridge University Press, pp. 33–34, ISBN 978-0-521-60954-8 +Jump up ^ Kelly 2004:22 'Around year 1240, Arabs acquired knowledge of saltpeter ("Chinese snow") from the East, perhaps through India. They knew of gunpowder soon afterward. They also learned about fireworks ("Chinese flowers") and rockets ("Chinese arrows"). Arab warriors had acquired fire lances before year 1280. Around that same year, a Syrian named Hasan al-Rammah wrote a book that, as he put it, "treats of machines of fire to be used for amusement or for useful purposes." He talked of rockets, fireworks, fire lances, and other incendiaries, using terms that suggested he derived his knowledge from Chinese sources. He gave instructions for the purification of saltpeter and recipes for making different types of gunpowder.' +^ Jump up to: a b c d Hassan, Ahmad Y. "Transfer of Islamic Technology to the West: Part III". History of Science and Technology in Islam. +Jump up ^ Peter Watson (2006). Ideas: A History of Thought and Invention, from Fire to Freud. HarperCollins. p. 304. ISBN 978-0-06-093564-1. The first use of a metal tube in this context was made around 1280 in the wars between the Song and the Mongols, where a new term, chong, was invented to describe the new horror...Like paper, it reached the West via the Muslims, in this case the writings of the Andalusian botanist Ibn al-Baytar, who died in Damascus in 1248. The Arabic term for saltpetre is 'Chinese snow' while the Persian usage is 'Chinese salt'.28 +Jump up ^ Cathal J. Nolan (2006). The age of wars of religion, 1000–1650: an encyclopedia of global warfare and civilization. Volume 1 of Greenwood encyclopedias of modern world wars. Greenwood Publishing Group. p. 365. ISBN 0-313-33733-0. Retrieved 2011-11-28. In either case, there is linguistic evidence of Chinese origins of the technology: in Damascus, Arabs called the saltpeter used in making gunpowder " Chinese snow," while in Iran it was called "Chinese salt." Whatever the migratory route +Jump up ^ Oliver Frederick Gillilan Hogg (1970). Artillery: its origin, heyday, and decline. Archon Books. p. 123. The Chinese were certainly acquainted with saltpetre, the essential ingredient of gunpowder. They called it Chinese Snow and employed it early in the Christian era in the manufacture of fireworks and rockets. +Jump up ^ Oliver Frederick Gillilan Hogg (1963). English artillery, 1326–1716: being the history of artillery in this country prior to the formation of the Royal Regiment of Artillery. Royal Artillery Institution. p. 42. The Chinese were certainly acquainted with saltpetre, the essential ingredient of gunpowder. They called it Chinese Snow and employed it early in the Christian era in the manufacture of fireworks and rockets. +Jump up ^ Oliver Frederick Gillilan Hogg (1993). Clubs to cannon: warfare and weapons before the introduction of gunpowder (reprint ed.). Barnes & Noble Books. p. 216. ISBN 1-56619-364-8. Retrieved 2011-11-28. The Chinese were certainly acquainted with saltpetre, the essential ingredient of gunpowder. They called it Chinese snow and used it early in the Christian era in the manufacture of fireworks and rockets. +Jump up ^ Partington, J. R. (1960). A History of Greek Fire and Gunpowder (illustrated, reprint ed.). JHU Press. p. 335. ISBN 0801859549. Retrieved 2014-11-21. +Jump up ^ Needham, Joseph; Yu, Ping-Yu (1980). Needham, Joseph, ed. Science and Civilisation in China: Volume 5, Chemistry and Chemical Technology, Part 4, Spagyrical Discovery and Invention: Apparatus, Theories and Gifts. Volume 5 (Issue 4 of Science and Civilisation in China). Contributors Joseph Needham, Lu Gwei-Djen, Nathan Sivin (illustrated, reprint ed.). Cambridge University Press. p. 194. ISBN 052108573X. Retrieved 2014-11-21. +Jump up ^ Khan 1996 +^ Jump up to: a b Khan 2004:6 +Jump up ^ Ancient Discoveries, Episode 12: Machines of the East, History Channel, 2007 (Part 4 and Part 5) +Jump up ^ Nelson, Cameron Rubaloff (2010-07). Manufacture and transportation of gunpowder in the Ottoman Empire: 1400-1800 M.A. Thesis. +Jump up ^ William H. McNeill (1992). The Rise of the West: A History of the Human Community. University of Chicago Press. p. 492. ISBN 0-226-56141-0. Retrieved 29 July 2011. +Jump up ^ Michael Kohn (2006), Dateline Mongolia: An American Journalist in Nomad's Land, RDR Books, p. 28, ISBN 1-57143-155-1, retrieved 29 July 2011 +Jump up ^ Robert Cowley (1993). Robert Cowley, ed. Experience of War (reprint ed.). Random House Inc. p. 86. ISBN 0-440-50553-4. Retrieved 29 July 2011. +Jump up ^ Kenneth Warren Chase (2003). Firearms: a global history to 1700 (illustrated ed.). Cambridge University Press. p. 58. ISBN 0-521-82274-2. Retrieved 29 July 2011. +Jump up ^ C. F. Temler, Historische Abhandlungen der Koniglichen Gesellschaft der Wissenschaften zu Kopenhagen ... ubersetzt ... von V. A. Heinze, Kiel, Dresden and Leipzig, 1782, i, 168, as cited in Partington, p. 228, footnote 6. +Jump up ^ Joseph Needham; Gwei-Djen Lu; Ling Wang (1987). Science and civilisation in China, Volume 5, Part 7. Cambridge University Press. p. 358. ISBN 978-0-521-30358-3. +Jump up ^ Bert S. Hall, "Introduction, 1999" p. xxiv to the reprinting of James Riddick Partington (1960). A history of Greek fire and gunpowder. JHU Press. ISBN 978-0-8018-5954-0. +Jump up ^ Partington 1960:60 +^ Jump up to: a b Partington 1960:48–49, 54 +^ Jump up to: a b Partington 1960:82–83 +^ Jump up to: a b c d Kelly 2004, p.61 +Jump up ^ Molerus, Otto. "History of Civilization in the Western Hemisphere from the Point of View of Particulate Technology, Part 2," Advanced Powder Technology 7 (1996): 161-66 +Jump up ^ Microsoft Encarta Online Encyclopedia 2007 Archived 31 October 2009. +Jump up ^ In 1777 Lavoisier named oxygen, which had earlier been isolated by Priestley; the realization that saltpeter contained this substance was fundamental to understanding gunpowder. +^ Jump up to: a b Kelly 2004, p.164 +Jump up ^ Metzner, Paul (1998), Crescendo of the Virtuoso: Spectacle, Skill, and Self-Promotion in Paris during the Age of Revolution, University of California Press +^ Jump up to: a b c d Cocroft 2000, "Success to the Black Art!". Chapter 1 +Jump up ^ Ross, Charles. The Custom of the Castle: From Malory to Macbeth. Berkeley: University of California Press, c1997. [1] pages 131-130 +Jump up ^ The Noble-Abel Equation of State: Thermodynamic Derivations for Ballistics Modelling +Jump up ^ Pritchard, Tom; Evans, Jack; Johnson, Sydney (1985), The Old Gunpowder Factory at Glynneath, Merthyr Tydfil: Merthyr Tydfil & District Naturalists' Society +^ Jump up to: a b c d e Cocroft 2000, "The demise of gunpowder". Chapter 4 +Jump up ^ MacDougall, Ian (2000). 'Oh, ye had to be careful' : personal recollections by Roslin gunpowder mill and bomb factory workers. East Linton, Scotland: Tuckwell Press in association with the European Ethnological Research Centre and the Scottish Working People's History Trust. ISBN 1-86232-126-4. +Jump up ^ Iqtidar Alam Khan (2004). Gunpowder And Firearms: Warfare In Medieval India. Oxford University Press. ISBN 978-0-19-566526-0. +^ Jump up to: a b Iqtidar Alam Khan (25 April 2008). Historical Dictionary of Medieval India. Scarecrow Press. p. 157. ISBN 978-0-8108-5503-8. +^ Jump up to: a b Khan 2004:9–10 +Jump up ^ Khan 2004:10 +Jump up ^ Partington (Johns Hopkins University Press edition, 1999), 225 +Jump up ^ Partington (Johns Hopkins University Press edition, 1999), 226 +Jump up ^ http://www.youtube.com/watch?v=DTfEDaWMj4o +^ Jump up to: a b c "India." Encyclopædia Britannica. Encyclopedia Britannica 2008 Ultimate Reference Suite. Chicago: Encyclopedia Britannica, 2008. +Jump up ^ "rocket and missile system." Encyclopædia Britannica. Encyclopædia Britannica 2008 Ultimate Reference Suite. Chicago: Encyclopædia Britannica, 2008. +^ Jump up to: a b Dipanegara, P. B. R. Carey, Babad Dipanagara: an account of the outbreak of the Java war, 1825-30 : the Surakarta court version of the Babad Dipanagara with translations into English and Indonesian volume 9: Council of the M.B.R.A.S. by Art Printing Works: 1981. +Jump up ^ Atsushi, Ota (2006). Changes of regime and social dynamics in West Java : society, state, and the outer world of Banten, 1750-1830. Leiden: Brill. ISBN 90-04-15091-9. +^ Jump up to: a b Thomas Stamford Raffles, The History of Java, Oxford University Press, 1965 (originally published in 1817), ISBN 0-19-580347-7 +Jump up ^ Raffles, Thomas Stamford (1978). The History of Java ([Repr.]. ed.). Kuala Lumpur: Oxford University Press. ISBN 0-19-580347-7. +Jump up ^ US Department of Agriculture (1917). Department Bulleting No. 316: Willows: Their growth, use, and importance. The Department. p. 31. +Jump up ^ Kelly 2004, p.200 +^ Jump up to: a b Earl 1978, Chapter 2: The Development of Gunpowder +Jump up ^ Kelly 2004:60–63 +Jump up ^ Kelly 2004, p.199 +Jump up ^ Frangsmyr, Tore, J. L. Heilbron, and Robin E. Rider, editors The Quantifying Spirit in the Eighteenth Century. Berkeley: University of California Press, c1990. http://ark.cdlib.org/ark:/13030/ft6d5nb455/ p. 292. +Jump up ^ C.E. Munroe (1885) "Notes on the literature of explosives no. VIII", Proceedings of the US Naval Institute, no. XI, p. 285 +Jump up ^ The History of the 10.4×38 Swiss Cartridge +Jump up ^ Blackpowder to Pyrodex and Beyond by Randy Wakeman at Chuck Hawks +Jump up ^ The History and Art of Shotshells by Jon Farrar, Nebraskaland Magazine +Jump up ^ Buchanan. "Editor's Introduction: Setting the Context", in Buchanan 2006, p. 4. +Jump up ^ Black Powder Recipes, Ulrich Bretscher +Jump up ^ Julian S. Hatcher, Hatcher's Notebook, Military Service Publishing Company, 1947. Chapter XIII Notes on Gunpowder, pages 300-305. +Jump up ^ Kelly 2004, p.218 +Jump up ^ Book title Workshop Receipts Publisher William Clowes and Son limited Author Ernest Spon. Date 1 August 1873. +Jump up ^ GunpowderTranslation. Academic. Retrieved 2014-08-31. +Jump up ^ Cathal J. Nolan (2006), The age of wars of religion, 1000-1650: an encyclopedia of global warfare and civilization, Greenwood Publishing Group, p. 365, ISBN 978-0-313-33733-8 +^ Jump up to: a b c Kelly 2004, p58 +^ Jump up to: a b c John Francis Guilmartin (2003). Gunpowder & galleys: changing technology & Mediterranean warfare at sea in the 16th century. Conway Maritime Press. pp. 109–110 and 298–300. ISBN 0851779514. +Jump up ^ T.J. Rodman (1861), Reports of experiments on the properties of metals for cannon and the qualities of cannon powder, p. 270 +^ Jump up to: a b Kelly 2004, p.195 +Jump up ^ Tenney L. Davis (1943). The Chemistry of Powder and Explosives (PDF). p. 139. +^ Jump up to: a b Brown, G.I. (1998) The Big Bang: A history of Explosives Sutton Publishing pp.22&32 ISBN 0-7509-1878-0 +^ Jump up to: a b c Kelly 2004, p.224 +^ Jump up to: a b Rodney James (2011). The ABCs of Reloading: The Definitive Guide for Novice to Expert (9 ed.). Krause Publications. pp. 53–59. ISBN 978-1-4402-1396-0. +Jump up ^ Sharpe, Philip B. (1953) Complete Guide to Handloading Funk & Wagnalls p.137 +Jump up ^ Wakeman, Randy. "Blackpowder to Pyrodex and Beyond". Retrieved 31 August 2014. +Jump up ^ "LESMOK POWDER". +Jump up ^ Julian S. Hatcher, Hatcher's Notebook, Stackpole Books, 1962. Chapter XIV, Gun Corrosion and Ammunition Developments, pages 346-349. +Jump up ^ Wakeman, Randy. "Blackpowder to Pyrodex and Beyond". +Jump up ^ Flash! Bang! Whiz!, University of Denver +Jump up ^ Parker, Harold T. (1983). Three Napoleonic battles. (Repr., Durham, 1944. ed.). Durham, NC: Duke Univ. Pr. p. 83. ISBN 0-8223-0547-X. +Jump up ^ Larrey is quoted in French at Dr Béraud, Études Hygiéniques de la chair de cheval comme aliment, Musée des Familles (1841-42). +Jump up ^ Rediker, Marcus (1989). Between the devil and the deep blue sea : merchant seamen, pirates, and the Anglo-American maritime world, 1700-1750 (1st pbk. ed. ed.). Cambridge: Cambridge University Press. p. 12. ISBN 9780521379830. +Jump up ^ "Gunpowder Now Used To Drive Rivets And Splice Cables", April 1932, Popular Science +Jump up ^ "MasterBlaster System". Remington Products. +Jump up ^ Mining Journal 22 January 1853, p. 61 +Benton, Captain James G. (1862). A Course of Instruction in Ordnance and Gunnery (2 ed.). West Point, New York: Thomas Publications. ISBN 1-57747-079-6.. +Brown, G. I. (1998). The Big Bang: A History of Explosives. Sutton Publishing. ISBN 0-7509-1878-0.. +Buchanan, Brenda J., ed. (2006). Gunpowder, Explosives and the State: A Technological History. Aldershot: Ashgate. ISBN 0-7546-5259-9.. +Chase, Kenneth (2003). Firearms: A Global History to 1700. Cambridge University Press. ISBN 0-521-82274-2.. +Cocroft, Wayne (2000). Dangerous Energy: The archaeology of gunpowder and military explosives manufacture. Swindon: English Heritage. ISBN 1-85074-718-0.. +Crosby, Alfred W. (2002). Throwing Fire: Projectile Technology Through History. Cambridge University Press. ISBN 0-521-79158-8.. +Earl, Brian (1978). Cornish Explosives. Cornwall: The Trevithick Society. ISBN 0-904040-13-5.. +al-Hassan, Ahmad Y.. "History of Science and Technology in Islam". |chapter= ignored (help). +Johnson, Norman Gardner. "explosive". Encyclopædia Britannica. Chicago: Encyclopædia Britannica Online.. +Kelly, Jack (2004). Gunpowder: Alchemy, Bombards, & Pyrotechnics: The History of the Explosive that Changed the World. Basic Books. ISBN 0-465-03718-6.. +Khan, Iqtidar Alam (1996). "Coming of Gunpowder to the Islamic World and North India: Spotlight on the Role of the Mongols". Journal of Asian History 30: 41–5.. +Khan, Iqtidar Alam (2004). "Gunpowder and Firearms: Warfare in Medieval India". Oxford University Press. doi:10.1086/ahr.111.3.817.. +Needham, Joseph (1986). "Science & Civilisation in China". V:7: The Gunpowder Epic. Cambridge University Press. ISBN 0-521-30358-3.. +Norris, John (2003). Early Gunpowder Artillery: 1300-1600. Marlborough: The Crowood Press. ISBN 9781861266156.. +Partington, J.R. (1960). A History of Greek Fire and Gunpowder. Cambridge, UK: W. Heffer & Sons.. +Partington, James Riddick; Hall, Bert S. (1999). A History of Greek Fire and Gunpowder. Baltimore: Johns Hopkins University Press. doi:10.1353/tech.2000.0031. ISBN 0-8018-5954-9. +Urbanski, Tadeusz (1967). "Chemistry and Technology of Explosives" III. New York: Pergamon Press.. +External links[edit] + Wikimedia Commons has media related to Gunpowder. + Look up gunpowder in Wiktionary, the free dictionary. +Gun and Gunpowder +The Origins of Gunpowder +Cannons and Gunpowder +Oare Gunpowder Works, Kent, UK +Royal Gunpowder Mills +The DuPont Company on the Brandywine A digital exhibit produced by the Hagley Library that covers the founding and early history of the DuPont Company powder yards in Delaware +"Ulrich Bretschler's Gunpowder Chemistry page". +Video Demonstration of the Medieval Siege Society's Guns, Including showing ignition of gunpowder +Black Powder Recipes +"Dr. Sasse's investigations (and others) found via search at US DTIC.MIL These contain scientific studies of BP properties and details of measurement techniques.". +Categories: GunpowderChinese inventionsExplosivesFirearm propellantsPyrotechnic compositionsRocket fuelsSolid fuels +Navigation menu +Create accountLog inArticleTalkReadEditView history + +Main page +Contents +Featured content +Current events +Random article +Donate to Wikipedia +Wikimedia Shop +Interaction +Help +About Wikipedia +Community portal +Recent changes +Contact page +Tools +What links here +Related changes +Upload file +Special pages +Permanent link +Page information +Wikidata item +Cite this page +Print/export +Create a book +Download as PDF +Printable version +Languages +Afrikaans +العربية +Aragonés +Asturianu +Azərbaycanca +Башҡортса +Беларуская +Беларуская (тарашкевіца)‎ +Български +Bosanski +Brezhoneg +Буряад +Català +Чӑвашла +Čeština +Corsu +Cymraeg +Dansk +Deutsch +Eesti +Ελληνικά +Español +Esperanto +Euskara +فارسی +Français +Gaeilge +Galego +贛語 +Хальмг +한국어 +हिन्दी +Hrvatski +Ilokano +Bahasa Indonesia +Íslenska +Italiano +עברית +Kapampangan +Kiswahili +Kurdî +Latina +Latviešu +Lietuvių +Limburgs +Magyar +Македонски +മലയാളം +مصرى +Монгол +Nederlands +नेपाली +नेपाल भाषा +日本語 +Нохчийн +Norsk bokmål +Norsk nynorsk +Occitan +Oʻzbekcha +پنجابی +Polski +Português +Română +Runa Simi +Русский +Саха тыла +Scots +Shqip +Sicilianu +Simple English +Slovenčina +Slovenščina +کوردی +Српски / srpski +Srpskohrvatski / српскохрватски +Suomi +Svenska +Tagalog +தமிழ் +Татарча/tatarça +ไทย +Türkçe +Українська +اردو +Tiếng Việt +Võro +Winaray +ייִדיש +粵語 +Žemaitėška +中文 +Edit links +This page was last modified on 28 November 2014 at 05:37. +Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Terms of Use and Privacy Policy. Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc., a non-profit organization. +Privacy policyAbout WikipediaDisclaimersContact WikipediaDevelopersMobile viewWikimedia Foundation Powered by MediaWiki + + +Smokeless powder +From Wikipedia, the free encyclopedia + +Finnish smokeless powder +Smokeless powder is the name given to a number of propellants used in firearms and artillery that produce negligible smoke when fired, unlike the black powder they replaced. The term is unique to the United States and is generally not used in other English-speaking countries, which initially used proprietary names such as "Ballistite" and "Cordite" but gradually shifted to "propellant" as the generic term. +The basis of the term smokeless is that the combustion products are mainly gaseous, compared to around 55% solid products (mostly potassium carbonate, potassium sulfate, and potassium sulfide) for black powder.[1] Despite its name, smokeless powder is not completely smoke-free;[2] while there may be little noticeable smoke from small-arms ammunition, smoke from artillery fire can be substantial. This article focuses on nitrocellulose formulations, but the term smokeless powder was also used to describe various picrate mixtures with nitrate, chlorate, or dichromate oxidizers during the late 19th century, before the advantages of nitrocellulose became evident.[3] +Since the 14th century[4] gunpowder was not actually a physical "powder," and smokeless powder can only be produced as a pelletized or extruded granular material. Smokeless powder allowed the development of modern semi- and fully automatic firearms and lighter breeches and barrels for artillery. Burnt black powder leaves a thick, heavy fouling that is hygroscopic and causes rusting of the barrel. The fouling left by smokeless powder exhibits none of these properties (though some primer compounds can leave hygroscopic salts that have a similar effect; non-corrosive primer compounds were introduced in the 1920s[5][6]). This makes an autoloading firearm with many moving parts feasible (which would otherwise jam or seize under heavy black powder fouling). +Smokeless powders are classified as, typically, division 1.3 explosives under the UN Recommendations on the transportation of Dangerous goods – Model Regulations, regional regulations (such as ADR) and national regulations (such the United States' ATF). However, they are used as solid propellants; in normal use, they undergo deflagration rather than detonation. +Contents [hide] +1 Background +2 Nitroglycerine and guncotton +3 Propellant improvements +4 Chemical formulations +5 Instability and stabilization +6 Physical variations +7 Smokeless propellant components +8 Manufacturing +9 Flashless propellant +10 See also +11 References +11.1 Notes +11.2 Sources +12 External links +Background[edit] +Military commanders had been complaining since the Napoleonic Wars about the problems of giving orders on a battlefield obscured by the smoke of firing. Verbal commands could not be heard above the noise of the guns, and visual signals could not be seen through the thick smoke from the gunpowder used by the guns. Unless there was a strong wind, after a few shots, soldiers using black powder ammunition would have their view obscured by a huge cloud of smoke. Snipers or other concealed shooters were given away by a cloud of smoke over the firing position. Black powder is also corrosive, making cleaning mandatory after every use. Likewise, black powder's tendency to produce severe fouling caused actions to jam and often made reloading difficult. +Nitroglycerine and guncotton[edit] +Nitroglycerine was synthesized by the Italian chemist Ascanio Sobrero in 1847.[7] It was subsequently developed and manufactured by Alfred Nobel as an industrial explosive, but even then it was unsuitable as a propellant: despite its energetic and smokeless qualities, it detonates instead of deflagrating smoothly, making it more amenable to shattering a gun than propelling a projectile out of it. Nitroglycerine per se is also highly unstable, making it unfit to be carried in battlefield conditions. +A major step forward was the discovery of guncotton, a nitrocellulose-based material, by Swiss chemist Christian Friedrich Schönbein in 1846. He promoted its use as a blasting explosive[8] and sold manufacturing rights to the Austrian Empire. Guncotton was more powerful than gunpowder, but at the same time was once again somewhat more unstable. John Taylor obtained an English patent for guncotton; and John Hall & Sons began manufacture in Faversham. +English interest languished after an explosion destroyed the Faversham factory in 1847. Austrian Baron Wilhelm Lenk von Wolfsberg built two guncotton plants producing artillery propellent, but it too was dangerous under field conditions, and guns that could fire thousands of rounds using gunpowder would reach their service life after only a few hundred shots with the more powerful guncotton. Small arms could not withstand the pressures generated by guncotton at all. +After one of the Austrian factories blew up in 1862, Thomas Prentice & Company began manufacturing guncotton in Stowmarket in 1863; and British War Office chemist Sir Frederick Abel began thorough research at Waltham Abbey Royal Gunpowder Mills leading to a manufacturing process that eliminated the impurities in nitrocellulose making it safer to produce and a stable product safer to handle. Abel patented this process in 1865, when the second Austrian guncotton factory exploded. After the Stowmarket factory exploded in 1871, Waltham Abbey began production of guncotton for torpedo and mine warheads.[9] +Propellant improvements[edit] +In 1863, Prussian artillery captain Johann F. E. Schultze patented a small arms propellent of nitrated hardwood impregnated with saltpetre or barium nitrate. Prentice received an 1866 patent for a sporting powder of nitrated paper manufactured at Stowmarket, but ballistic uniformity suffered as the paper absorbed atmospheric moisture. In 1871, Frederick Volkmann received an Austrian patent for a colloided version of Schultze powder called Collodin, which he manufactured near Vienna for use in sporting firearms. Austrian patents were not published at the time, and the Austrian Empire considered the operation a violation of the government monopoly on explosives manufacture and closed the Volkmann factory in 1875.[9] In 1882, the Explosives Company at Stowmarket patented an improved formulation of nitrated cotton gelatinised by ether-alcohol with nitrates of potassium and barium. These propellants were suitable for shotguns but not rifles.[10] + +Poudre B single-base smokeless powder flakes +In 1884, Paul Vieille invented a smokeless powder called Poudre B (short for poudre blanche—white powder, as distinguished from black powder)[11] made from 68.2% insoluble nitrocellulose, 29.8% soluble nitrocellusose gelatinized with ether and 2% paraffin. This was adopted for the Lebel rifle.[12] It was passed through rollers to form paper thin sheets, which were cut into flakes of the desired size.[11] The resulting propellant, today known as pyrocellulose, contains somewhat less nitrogen than guncotton and is less volatile. A particularly good feature of the propellant is that it will not detonate unless it is compressed, making it very safe to handle under normal conditions. +Vieille's powder revolutionized the effectiveness of small guns, because it gave off almost no smoke and was three times more powerful than black powder. Higher muzzle velocity meant a flatter trajectory and less wind drift and bullet drop, making 1000 meter shots practicable. Since less powder was needed to propel a bullet, the cartridge could be made smaller and lighter. This allowed troops to carry more ammunition for the same weight. Also, it would burn even when wet. Black powder ammunition had to be kept dry and was almost always stored and transported in watertight cartridges. +Other European countries swiftly followed and started using their own versions of Poudre B, the first being Germany and Austria, which introduced new weapons in 1888. Subsequently Poudre B was modified several times with various compounds being added and removed. Krupp began adding diphenylamine as a stabilizer in 1888.[9] +Meanwhile, in 1887, Alfred Nobel obtained an English patent for a smokeless gunpowder he called Ballistite. In this propellant the fibrous structure of cotton (nitro-cellulose) was destroyed by a nitro-glycerine solution instead of a solvent.[13] In England in 1889, a similar powder was patented by Hiram Maxim, and in the USA in 1890 by Hudson Maxim.[14] Ballistite was patented in the United States in 1891. +The Germans adopted ballistite for naval use in 1898, calling it WPC/98. The Italians adopted it as filite, in cord instead of flake form, but realising its drawbacks changed to a formulation with nitroglycerine they called solenite. In 1891 the Russians tasked the chemist Mendeleef with finding a suitable propellant, he created nitrocellulose gelatinised by ether-alcohol, which produced more nitrogen and more uniform colloidal structure than the French use of nitro-cottons in Poudre B. He called it pyro-collodion.[13] +Britain conducted trials on all the various types of propellant brought to their attention, but were dissatisfied with them all and sought something superior to all existing types. In 1889, Sir Frederick Abel, James Dewar and Dr W Kellner patented (Nos 5614 and 11,664 in the names of Abel and Dewar) a new formulation that was manufactured at the Royal Gunpowder Factory at Waltham Abbey. It entered British service in 1891 as Cordite Mark 1. Its main composition was 58% Nitro-glycerine, 37% Guncotton and 3% mineral jelly. A modified version, Cordite MD, entered service in 1901, this increased guncotton to 65% and reduced nitro-glycerine to 30%, this change reduced the combustion temperature and hence erosion and barrel wear. Cordite's advantages over gunpowder were reduced maximum pressure in the chamber (hence lighter breeches, etc.) but longer high pressure. Cordite could be made in any desired shape or size.[15] The creation of cordite led to a lengthy court battle between Nobel, Maxim, and another inventor over alleged British patent infringement. +The Anglo-American Explosives Company began manufacturing its shotgun powder in Oakland, New Jersey in 1890. DuPont began producing guncotton at Carneys Point Township, New Jersey in 1891.[3] Charles E. Munroe of the Naval Torpedo Station in Newport, Rhode Island patented a formulation of guncotton colloided with nitrobenzene, called Indurite, in 1891.[16] Several United States firms began producing smokeless powder when Winchester Repeating Arms Company started loading sporting cartridges with Explosives Company powder in 1893. California Powder Works began producing a mixture of nitroglycerine and nitrocellulose with ammonium picrate as Peyton Powder, Leonard Smokeless Powder Company began producing nitroglycerine-nitrocellulose Ruby powders, Laflin & Rand negotiated a license to produce Ballistite, and DuPont started producing smokeless shotgun powder. The United States Army evaluated 25 varieties of smokeless powder and selected Ruby and Peyton Powders as the most suitable for use in the Krag-Jørgensen service rifle. Ruby was preferred, because tin-plating was required to protect brass cartridge cases from picric acid in the Peyton Powder. Rather than paying the required royalties for Ballistite, Laflin & Rand financed Leonard's reorganization as the American Smokeless Powder Company. United States Army Lieutenant Whistler assisted American Smokeless Powder Company factory superintendent Aspinwall in formulating an improved powder named W.A. for their efforts. W.A. smokeless powder was the standard for United States military service rifles from 1897 until 1908.[3] +In 1897, United States Navy Lieutenant John Bernadou patented a nitrocellulose powder colloided with ether-alcohol.[16] The Navy licensed or sold patents for this formulation to DuPont and the California Powder Works while retaining manufacturing rights for the Naval Powder Factory, Indian Head, Maryland constructed in 1900. The United States Army adopted the Navy single-base formulation in 1908 and began manufacture at Picatinny Arsenal.[3] By that time Laflin & Rand had taken over the American Powder Company to protect their investment, and Laflin & Rand had been purchased by DuPont in 1902.[17] Upon securing a 99-year lease of the Explosives Company in 1903, DuPont enjoyed use of all significant smokeless powder patents in the United States, and was able to optimize production of smokeless powder.[3] When government anti-trust action forced divestiture in 1912, DuPont retained the nitrocellulose smokeless powder formulations used by the United States military and released the double-base formulations used in sporting ammunition to the reorganized Hercules Powder Company. These newer propellants were more stable and thus safer to handle than Poudre B, and also more powerful. +Chemical formulations[edit] +"Double base" redirects here. For the musical instrument, see double bass. +Currently, propellants using nitrocellulose (detonation velocity 7,300 m/s (23,950 ft/s)) (typically an ether-alcohol colloid of nitrocellulose) as the sole explosive propellant ingredient are described as single-base powder.[18] +Propellants mixtures containing nitrocellulose and nitroglycerin (detonation velocity 7,700 m/s (25,260 ft/s)) as explosive propellant ingredients are known as double-base powder.[19] +During the 1930s triple-base propellant containing nitrocellulose, nitroglycerin, and a substantial quantity of nitroguanidine (detonation velocity 8,200 m/s (26,900 ft/s)) as explosive propellant ingredients was developed. These propellant mixtures have reduced flash and flame temperature without sacrificing chamber pressure compared to single and double base propellants, albeit at the cost of more smoke. +In practice, triple base propellants are reserved mainly for large caliber ammunition such as used in (naval) artillery and tank guns. During World War II it had some use by British artillery. After that war it became the standard propellant in all British large caliber ammunition designs except small-arms. Most western nations, except the United States, followed a similar path. +In the late 20th century new propellant formulations started to appear. These are based on nitroguanidine and high explosives of the RDX (detonation velocity 8,750 m/s (28,710 ft/s)) type. +Instability and stabilization[edit] +Nitrocellulose deteriorates with time, yielding acidic byproducts. Those byproducts catalyze the further deterioration, increasing its rate. The released heat, in case of bulk storage of the powder, or too large blocks of solid propellant, can cause self-ignition of the material. Single-base nitrocellulose propellants are hygroscopic and most susceptible to degradation; double-base and triple-base propellants tend to deteriorate more slowly. To neutralize the decomposition products, which could otherwise cause corrosion of metals of the cartridges and gun barrels, calcium carbonate is added to some formulations. +To prevent buildup of the deterioration products, stabilizers are added. Diphenylamine is one of the most common stabilizers used. Nitrated analogs of diphenylamine formed in the process of stabilizing decomposing powder are sometimes used as stabilizers themselves.[20][21] The stabilizers are added in the amount of 0.5–2% of the total amount of the formulation; higher amounts tend to degrade its ballistic properties. The amount of the stabilizer is depleted with time. Propellants in storage should be periodically tested for the amount of stabilizer remaining, as its depletion may lead to auto-ignition of the propellant. +Physical variations[edit] + +Ammunition handloading powders +Smokeless powder may be corned into small spherical balls or extruded into cylinders or strips with many cross-sectional shapes (strips with various rectangular proportions, single or multi-hole cylinders, slotted cylinders) using solvents such as ether. These extrusions can be cut into short ('flakes') or long pieces ('cords' many inches long). Cannon powder has the largest pieces. +The properties of the propellant are greatly influenced by the size and shape of its pieces. The specific surface area of the propellant influences the speed of burning, and the size and shape of the particles determine the specific surface area. By manipulation of the shape it is possible to influence the burning rate and hence the rate at which pressure builds during combustion. Smokeless powder burns only on the surfaces of the pieces. Larger pieces burn more slowly, and the burn rate is further controlled by flame-deterrent coatings that retard burning slightly. The intent is to regulate the burn rate so that a more or less constant pressure is exerted on the propelled projectile as long as it is in the barrel so as to obtain the highest velocity. The perforations stabilize the burn rate because as the outside burns inward (thus shrinking the burning surface area) the inside is burning outward (thus increasing the burning surface area, but faster, so as to fill up the increasing volume of barrel presented by the departing projectile).[22] Fast-burning pistol powders are made by extruding shapes with more area such as flakes or by flattening the spherical granules. Drying is usually performed under a vacuum. The solvents are condensed and recycled. The granules are also coated with graphite to prevent static electricity sparks from causing undesired ignitions.[23] +Faster-burning propellants generate higher temperatures and higher pressures, however they also increase wear on gun barrels. +Smokeless propellant components[edit] +The propellant formulations may contain various energetic and auxiliary components: +Propellants: +Nitrocellulose, an energetic component of most smokeless propellants[24] +Nitroglycerin, an energetic component of double-base and triple-base formulations[24] +Nitroguanidine, a component of triple-base formulations[24] +D1NA (bis-nitroxyethylnitramine)[25] +Fivonite (tetramethylolcyclopentanone)[25] +DGN (di-ethylene glycol dinitrate)[26] +Acetyl cellulose[27] +Deterrents, (or moderants), to slow the burning rate +Centralites (symmetrical diphenyl urea—primarily diethyl or dimethyl)[28][29] +Dibutyl phthalate[24][29] +Dinitrotoluene (toxic, carcinogenic, and obsolete)[24][30] +Akardite (asymmetrical diphenyl urea)[26] +ortho-tolyl urethane[31] +Polyester adipate +Camphor (obsolete)[29] +Stabilizers, to prevent or slow down self-decomposition[32] +Diphenylamine[33] +Petroleum jelly[34] +Calcium carbonate[24] +Magnesium oxide[26] +Sodium bicarbonate[27] +beta-naphthol methyl ether[31] +Amyl alcohol (obsolete)[35] +Aniline (obsolete)[36] +Decoppering additives, to hinder the buildup of copper residues from the gun barrel rifling +Tin metal and compounds (e.g., tin dioxide)[24][37] +Bismuth metal and compounds (e.g., bismuth trioxide, bismuth subcarbonate, bismuth nitrate, bismuth antimonide); the bismuth compounds are favored as copper dissolves in molten bismuth, forming brittle and easily removable alloy +Lead foil and lead compounds, phased out due to toxicity[25] +Flash reducers, to reduce the brightness of the muzzle flash (all have a disadvantage: the production of smoke)[38] +Potassium chloride[39] +Potassium nitrate +Potassium sulfate[24][37] +Potassium hydrogen tartarate (a byproduct of wine production formerly used by French artillery)[39] +Wear reduction additives, to lower the wear of the gun barrel liners[40] +Wax +Talc +Titanium dioxide +Polyurethane jackets over the powder bags, in large guns +Other additives +Ethyl acetate, a solvent for manufacture of spherical powder[34] +Rosin, a surfactant to hold the grain shape of spherical powder +Graphite, a lubricant to cover the grains and prevent them from sticking together, and to dissipate static electricity[23] +Manufacturing[edit] +This section describes procedures used in the United States. See Cordite for alternative procedures formerly used in the United Kingdom. +The United States Navy manufactured single-base tubular powder for naval artillery at Indian Head, Maryland, beginning in 1900. Similar procedures were used for United States Army production at Picatinny Arsenal beginning in 1907[18] and for manufacture of smaller grained Improved Military Rifle (IMR) powders after 1914. Short-fiber cotton linter was boiled in a solution of sodium hydroxide to remove vegetable waxes, and then dried before conversion to nitrocellulose by mixing with concentrated nitric and sulfuric acids. Nitrocellulose still resembles fibrous cotton at this point in the manufacturing process, and was typically identified as pyrocellulose because it would spontaneously ignite in air until unreacted acid was removed. The term guncotton was also used; although some references identify guncotton as a more extensively nitrated and refined product used in torpedo and mine warheads prior to use of TNT.[41] +Unreacted acid was removed from pyrocellulose pulp by a multistage draining and water washing process similar to that used in paper mills during production of chemical woodpulp. Pressurized alcohol removed remaining water from drained pyrocellulose prior to mixing with ether and diphenylamine. The mixture was then fed through a press extruding a long turbular cord form to be cut into grains of the desired length.[42] +Alcohol and ether were then evaporated from "green" powder grains to a remaining solvent concentration between 3 percent for rifle powders and 7 percent for large artillery powder grains. Burning rate is inversely proportional to solvent concentration. Grains were coated with electrically conductive graphite to minimize generation of static electricity during subsequent blending. "Lots" containing more than ten tonnes of powder grains were mixed through a tower arrangement of blending hoppers to minimize ballistic differences. Each blended lot was then subjected to testing to determine the correct loading charge for the desired performance.[43][44] +Military quantities of old smokeless powder were sometimes reworked into new lots of propellants.[45] Through the 1920s Dr. Fred Olsen worked at Picatinny Arsenal experimenting with ways to salvage tons of single-base cannon powder manufactured for World War I. Dr. Olsen was employed by Western Cartridge Company in 1929 and developed a process for manufacturing spherical smokeless powder by 1933.[46] Reworked powder or washed pyrocellulose can be dissolved in ethyl acetate containing small quantities of desired stabilizers and other additives. The resultant syrup, combined with water and surfactants, can be heated and agitated in a pressurized container until the syrup forms an emulsion of small spherical globules of the desired size. Ethyl acetate distills off as pressure is slowly reduced to leave small spheres of nitrocellulose and additives. The spheres can be subsequently modified by adding nitroglycerine to increase energy, flattening between rollers to a uniform minimum dimension, coating with phthalate deterrents to retard ignition, and/or glazing with graphite to improve flow characteristics during blending.[47][48] +Modern smokeless powder is produced in the United States by St. Marks Powder, Inc. owned by General Dynamics.[49] +Flashless propellant[edit] +Muzzle flash is the light emitted in the vicinity of the muzzle by the hot propellant gases and the chemical reactions that follow as the gases mix with the surrounding air. Before projectiles exit a slight pre-flash may occur from gases leaking past the projectiles. Following muzzle exit the heat of gases is usually sufficient to emit visible radiation – the primary flash. The gases expand but as they pass through the Mach disc they are re-compressed to produce an intermediate flash. Hot combustible gases (e.g. hydrogen and carbon-monoxide) may follow when they mix with oxygen in the surrounding air to produce the secondary flash, the brightest. The secondary flash does not usually occur with small-arms.[50] +Nitrocellulose contains insufficient oxygen to completely oxidize its carbon and hydrogen. The oxygen deficit is increased by addition of graphite and organic stabilizers. Products of combustion within the gun barrel include flammable gasses like hydrogen and carbon monoxide. At high temperature, these flammable gasses will ignite when turbulently mixed with atmospheric oxygen beyond the muzzle of the gun. During night engagements the flash produced by ignition can reveal the location of the gun to enemy forces[51] and cause temporary night-blindness among the gun crew by photo-bleaching visual purple.[52] +Flash suppressors are commonly used on small arms to reduce the flash signature, but this approach is not practical for artillery. Artillery muzzle flash up to 150 feet (46 m) from the muzzle has been observed, and can be reflected off clouds and be visible for distances up to 30 miles (48 km).[51] For artillery the most effective method is a propellant that produces a large proportion of inert nitrogen at relatively low temperatures that dilutes the combustible gases. Triple based propellants are used for this because of the nitrogen in the nitroguandine.[53] +Before the use of triple based propellants the usual method of flash reduction was to add inorganic salts like potassium chloride so their specific heat capacity might reduce the temperature of combustion gasses and their finely divided particulate smoke might block visible wavelengths of radiant energy of combustion.[39] +See also[edit] +Portal icon Pyrotechnics portal +Antique guns +Ballistite +Cordite +Firearms +Gunpowder +Nitrocellulose +Small arms +Brown-brown – a drug created by mixing cocaine with cartridge powder +References[edit] +Notes[edit] +Jump up ^ Hatcher, Julian S. and Barr, Al Handloading Hennage Lithograph Company (1951) p.34 +Jump up ^ Fairfield, A. P., CDR USN Naval Ordnance Lord Baltimore Press (1921) p.44 +^ Jump up to: a b c d e Sharpe, Philip B. Complete Guide to Handloading 3rd Edition (1953) Funk & Wagnalls pp.146-149 +Jump up ^ seegunpowder +Jump up ^ Sharpe, Philip B. Complete Guide To Handloading (1953) Funk & Wagnalls p.60 +Jump up ^ Davis, William C., Jr. Handloading (1981) National Rifle Association p.21 +Jump up ^ Davis, Tenney L. The Chemistry of Powder & Explosives (1943) page 195 +Jump up ^ Davis, William C., Jr. Handloading National Rifle Association of America (1981) p.28 +^ Jump up to: a b c Sharpe, Philip B. Complete Guide to Handloading 3rd Edition (1953) Funk & Wagnalls pp.141-144 +Jump up ^ Hogg, Oliver F. G. Artillery: Its Origin, Heyday and Decline (1969) p.138-139 +^ Jump up to: a b Davis, Tenney L. The Chemistry of Powder & Explosives (1943) pages 289–292 +Jump up ^ Hogg, Oliver F. G. Artillery: Its Origin, Heyday and Decline (1969) p.139 +^ Jump up to: a b Hogg, Oliver F. G. Artillery: Its Origin, Heyday and Decline (1969) p.140 +Jump up ^ U.S. Patent 430,212 – Manufacture of explosive – H. S. Maxim +Jump up ^ Hogg, Oliver F. G. Artillery: Its Origin, Heyday and Decline (1969) p.141 +^ Jump up to: a b Davis, Tenney L. The Chemistry of Powder & Explosives (1943) pages 296-297 +Jump up ^ "Laflin & Rand Powder Company". DuPont. Retrieved 2012-02-24. +^ Jump up to: a b Davis, Tenny L. The Chemistry of Powder & Explosives (1943) p.297 +Jump up ^ Davis, Tenny L. The Chemistry of Powder & Explosives (1943) p.298 +Jump up ^ Fairfield, A. P., CDR USN Naval Ordnance Lord Baltimore Press (1921) p.28 +Jump up ^ Davis, Tenny L. The Chemistry of Powder & Explosives (1943) p. 310 +Jump up ^ Fairfield, A. P., CDR USN Naval Ordnance Lord Baltimore Press (1921) pp.41–43 +^ Jump up to: a b Davis, Tenny L. The Chemistry of Powder & Explosives (1943) p.306 +^ Jump up to: a b c d e f g h Campbell, John Naval Weapons of World War Two (1985) p. 5 +^ Jump up to: a b c Campbell, John Naval Weapons of World War Two (1985) p. 104 +^ Jump up to: a b c Campbell, John Naval Weapons of World War Two (1985) p. 221 +^ Jump up to: a b Campbell, John Naval Weapons of World War Two (1985) p. 318 +Jump up ^ Davis, Tenny L. The Chemistry of Powder & Explosives (1943) pages 317–320 +^ Jump up to: a b c Davis, William C., Jr. Handloading National Rifle Association of America (1981) p.30 +Jump up ^ Davis, William C., Jr. Handloading National Rifle Association of America (1981) p.31 +^ Jump up to: a b Campbell, John Naval Weapons of World War Two (1985) p. 174 +Jump up ^ Davis, Tenny L. The Chemistry of Powder & Explosives (1943) pages 307–311 +Jump up ^ Davis, Tenny L. The Chemistry of Powder & Explosives (1943) p. 302 +^ Jump up to: a b Davis, Tenny L. The Chemistry of Powder & Explosives (1943) p. 296 +Jump up ^ Davis, Tenny L. The Chemistry of Powder & Explosives (1943) p. 307 +Jump up ^ Davis, Tenny L. The Chemistry of Powder & Explosives (1943) p. 308 +^ Jump up to: a b Davis, William C., Jr. Handloading National Rifle Association of America (1981) p.32 +Jump up ^ Davis, Tenny L. The Chemistry of Powder & Explosives (1943) pages 322–327 +^ Jump up to: a b c Davis, Tenny L. The Chemistry of Powder & Explosives (1943) pages 323–327 +Jump up ^ "USA 16"/50 (40.6 cm) Mark 7". NavWeaps. 2008-11-03. Retrieved 2008-12-05. +Jump up ^ Fairfield, A. P., CDR USN Naval Ordnance Lord Baltimore Press (1921) pages 28–31 +Jump up ^ Fairfield, A. P., CDR USN Naval Ordnance Lord Baltimore Press (1921) pages 31–35 +Jump up ^ Fairfield, A. P., CDR USN Naval Ordnance Lord Baltimore Press (1921) pages 35–41 +Jump up ^ Davis, Tenny L. The Chemistry of Powder & Explosives (1943) pages 293 & 306 +Jump up ^ Fairfield, A. P., CDR USN Naval Ordnance Lord Baltimore Press (1921) p.39 +Jump up ^ Matunas, E. A. Winchester-Western Ball Powder Loading Data Olin Corporation (1978) p.3 +Jump up ^ Davis, Tenny L. The Chemistry of Powder & Explosives (1943) pages 328–330 +Jump up ^ Wolfe, Dave Propellant Profiles Volume 1 Wolfe Publishing Company (1982) pages 136–137 +Jump up ^ General Dynamics Commercial Powder Applications. +Jump up ^ Moss G. M., Leeming D. W., Farrar C. L. Military Ballisitcs (1969) pages 55–56 +^ Jump up to: a b Davis, Tenny L. The Chemistry of Powder & Explosives (1943) pages 322–323 +Jump up ^ Milner p.68 +Jump up ^ Moss G. M., Leeming D. W., Farrar C. L. Military Ballisitcs (1969) pages 59–60 +Sources[edit] +Campbell, John (1985). Naval Weapons of World War Two. Naval Institute Press. ISBN 0-87021-459-4. +Davis, Tenney L. (1943). The Chemistry of Powder & Explosives (Angriff Press [1992] ed.). John Wiley & Sons Inc. ISBN 0-913022-00-4. +Davis, William C., Jr. (1981). Handloading. National Rifle Association of America. ISBN 0-935998-34-9. +Fairfield, A. P., CDR USN (1921). Naval Ordnance. Lord Baltimore Press. +Hatcher, Julian S. and Barr, Al (1951). Handloading. Hennage Lithograph Company. +Matunas, E. A. (1978). Winchester-Western Ball Powder Loading Data. Olin Corporation. +Milner, Marc (1985). North Atlantic Run. Naval Institute Press. ISBN 0-87021-450-0. +Wolfe, Dave (1982). Propellant Profiles Volume 1. Wolfe Publishing Company. ISBN 0-935632-10-7. +External links[edit] +The Manufacture of Smokeless Powders and their Forensic Analysis: A Brief Review – Robert M. Heramb, Bruce R. McCord +Hudson Maxim papers (1851-1925) at Hagley Museum and Library. Collection includes material relating to Maxim's patent on the process of making smokeless powder. +Categories: CorditeExplosivesFirearm propellantsSolid fuels +Navigation menu +Create accountLog inArticleTalkReadEditView history + +Main page +Contents +Featured content +Current events +Random article +Donate to Wikipedia +Wikimedia Shop +Interaction +Help +About Wikipedia +Community portal +Recent changes +Contact page +Tools +What links here +Related changes +Upload file +Special pages +Permanent link +Page information +Wikidata item +Cite this page +Print/export +Create a book +Download as PDF +Printable version +Languages +العربية +Български +Dansk +Deutsch +Español +فارسی +Français +Bahasa Indonesia +Íslenska +Italiano +עברית +Nederlands +日本語 +Polski +Português +Русский +Svenska +தமிழ் +中文 +Edit links +This page was last modified on 25 July 2014 at 22:33. +Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Terms of Use and Privacy Policy. Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc., a non-profit organization. +Privacy policyAbout WikipediaDisclaimersContact WikipediaDevelopersMobile viewWikimedia Foundation Powered by MediaWiki + + +Deflagration +From Wikipedia, the free encyclopedia + +[hide]This article has multiple issues. Please help improve it or discuss these issues on the talk page. +This article needs additional citations for verification. (April 2011) +This article may be too technical for most readers to understand. (December 2013) + +A log in a fireplace. +Deflagration [1] (Lat: de + flagrare, "to burn down") is a term describing subsonic combustion propagating through heat transfer; hot burning material heats the next layer of cold material and ignites it. Most "fire" found in daily life, from flames to explosions, is deflagration. Deflagration is different from detonation, which is supersonic and propagates through shock. +Contents [hide] +1 Applications +2 Oil/wax fire and water +3 Flame physics +4 Damaging deflagration events +5 See also +6 References +Applications[edit] +In engineering applications, deflagrations are easier to control than detonations. Consequently, they are better suited when the goal is to move an object (a bullet in a gun, or a piston in an internal combustion engine) with the force of the expanding gas. Typical examples of deflagrations are the combustion of a gas-air mixture in a gas stove or a fuel-air mixture in an internal combustion engine, and the rapid burning of gunpowder in a firearm or of pyrotechnic mixtures in fireworks. Deflagration systems and products can also be used in mining, demolition and stone quarrying via gas pressure blasting as a beneficial alternative to high explosives. +Oil/wax fire and water[edit] +Adding water to a burning hydrocarbon such as oil or wax produces a deflagration. The water boils rapidly and ejects the burning material as a fine spray of droplets. A deflagration then occurs as the fine mist of oil ignites and burns extremely rapidly. These are particularly common in chip pan fires, which are responsible for one in five household fires in Britain.[2] +Flame physics[edit] +The underlying flame physics can be understood with the help of an idealized model consisting of a uniform one-dimensional tube of unburnt and burned gaseous fuel, separated by a thin transitional region of width \delta\; in which the burning occurs. The burning region is commonly referred to as the flame or flame front. In equilibrium, thermal diffusion across the flame front is balanced by the heat supplied by burning. +There are two characteristic timescales which are important here. The first is the thermal diffusion timescale \tau_d\;, which is approximately equal to +\tau_d \simeq \delta^2 / \kappa, +where \kappa \; is the thermal diffusivity. The second is the burning timescale \tau_b that strongly decreases with temperature, typically as +\tau_b\propto \exp[\Delta U/(k_B T_f)], +where \Delta U\; is the activation barrier for the burning reaction and T_f\; is the temperature developed as the result of burning; the value of this so-called "flame temperature" can be determined from the laws of thermodynamics. +For a stationary moving deflagration front, these two timescales must be equal: the heat generated by burning is equal to the heat carried away by heat transfer. This makes it possible to calculate the characteristic width \delta\; of the flame front: +\tau_b = \tau_d\;, +thus + \delta \simeq \sqrt {\kappa \tau_b} . +Now, the thermal flame front propagates at a characteristic speed S_l\;, which is simply equal to the flame width divided by the burn time: +S_l \simeq \delta / \tau_b \simeq \sqrt {\kappa / \tau_b} . +This simplified model neglects the change of temperature and thus the burning rate across the deflagration front. This model also neglects the possible influence of turbulence. As a result, this derivation gives only the laminar flame speed -- hence the designation S_l\;. +Damaging deflagration events[edit] +Damage to buildings, equipment and people can result from a large-scale, short-duration deflagration. The potential damage is primarily a function of the total amount of fuel burned in the event (total energy available), the maximum flame velocity that is achieved, and the manner in which the expansion of the combustion gases is contained. +In free-air deflagrations, there is a continuous variation in deflagration effects relative to the maximum flame velocity. When flame velocities are low, the effect of a deflagration is to release heat. Some authors use the term flash fire to describe these low-speed deflagrations. At flame velocities near the speed of sound, the energy released is in the form of pressure and the results resemble a detonation. Between these extremes both heat and pressure are released. +When a low-speed deflagration occurs within a closed vessel or structure, pressure effects can produce damage due to expansion of gases as a secondary effect. The heat released by the deflagration causes the combustion gases and excess air to expand thermally. The net result is that the volume of the vessel or structure must expand to accommodate the hot combustion gases, or the vessel must be strong enough to withstand the additional internal pressure, or it fails, allowing the gases to escape. The risks of deflagration inside waste storage drums is a growing concern in storage facilities. +See also[edit] + Look up deflagration in Wiktionary, the free dictionary. +Pressure piling +References[edit] +Jump up ^ "Glossary D-H". Hutchisonrodway.co.nz. Retrieved 2013-12-29. +Jump up ^ UK Fire Service advice on chip pan fires +Categories: Explosives +Navigation menu +Create accountLog inArticleTalkReadEditView history + +Main page +Contents +Featured content +Current events +Random article +Donate to Wikipedia +Wikimedia Shop +Interaction +Help +About Wikipedia +Community portal +Recent changes +Contact page +Tools +What links here +Related changes +Upload file +Special pages +Permanent link +Page information +Wikidata item +Cite this page +Print/export +Create a book +Download as PDF +Printable version +Languages +Català +Čeština +Deutsch +Español +Français +Italiano +Lietuvių +Nederlands +Norsk bokmål +Polski +Português +Русский +Српски / srpski +Svenska +Edit links +This page was last modified on 2 October 2014 at 16:44. +Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Terms of Use and Privacy Policy. Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc., a non-profit organization. +Privacy policyAbout WikipediaDisclaimersContact WikipediaDevelopersMobile viewWikimedia Foundation Powered by MediaWiki + + +United Kingdom +From Wikipedia, the free encyclopedia +This article is about the sovereign state. For the island, see Great Britain. For other uses, see United Kingdom (disambiguation) and UK (disambiguation). +Page semi-protected +United Kingdom of Great +Britain and Northern Ireland[show] + +A flag featuring both cross and saltire in red, white and blue Coat of arms containing shield and crown in centre, flanked by lion and unicorn +Flag Royal coat of arms[nb 1] +Anthem: "God Save the Queen"[nb 2] +MENU0:00 +Two islands to the north-west of continental Europe. Highlighted are the larger island and the north-eastern fifth of the smaller island to the west. +Location of the United Kingdom (dark green) +– in Europe (green & dark grey) +– in the European Union (green) +Capital +and largest city London +51°30′N 0°7′W +Official language +and national language English +Recognised regional +languages Cornish, Irish, Scots, Scottish Gaelic, Ulster-Scots, Welsh[nb 3] +Ethnic groups (2011) 87.1% White +7.0% Asian +3.0% Black +2.0% Mixed +0.9% Other +Demonym British, Briton +Government Unitary parliamentary constitutional monarchy + - Monarch Elizabeth II + - Prime Minister David Cameron +Legislature Parliament + - Upper house House of Lords + - Lower house House of Commons +Formation + - Acts of Union 1707 1 May 1707 + - Acts of Union 1800 1 January 1801 + - Irish Free State Constitution Act 5 December 1922 +Area + - Total 243,610 km2 (80th) +94,060 sq mi + - Water (%) 1.34 +Population + - 2013 estimate 64,100,000[3] (22nd) + - 2011 census 63,181,775[4] (22nd) + - Density 255.6/km2 (51st) +661.9/sq mi +GDP (PPP) 2014 estimate + - Total $2.435 trillion[5] (10th) + - Per capita $37,744[5] (27th) +GDP (nominal) 2014 estimate + - Total $2.848 trillion[5] (6th) + - Per capita $44,141[5] (22nd) +Gini (2012) positive decrease 32.8[6] +medium · 33rd +HDI (2013) Steady 0.892[7] +very high · 14th +Currency Pound sterling (GBP) +Time zone GMT (UTC​) + - Summer (DST) BST (UTC+1) +Date format dd/mm/yyyy (AD) +Drives on the left +Calling code +44 +ISO 3166 code GB +Internet TLD .uk +The United Kingdom of Great Britain and Northern Ireland Listeni/ɡreɪt ˈbrɪt(ə)n ənd ˈnɔːð(ə)n ˈʌɪələnd/, commonly known as the United Kingdom (UK) or Britain, is a sovereign state in Europe. Lying off the north-western coast of the European mainland, the country includes the island of Great Britain (a term also applied loosely to refer to the whole country),[8] the north-eastern part of the island of Ireland, and many smaller islands. Northern Ireland is the only part of the UK that shares a land border with another state: the Republic of Ireland.[nb 4] Apart from this land border, the UK is surrounded by the Atlantic Ocean, with the North Sea in the east and the English Channel in the south. The Irish Sea lies between Great Britain and Ireland. The UK has an area of 243,610 square kilometres (94,060 sq mi), making it the 78th-largest sovereign state in the world and the 11th-largest in Europe. +The United Kingdom is the 22nd-most populous country, with an estimated 64.1 million inhabitants.[3] It is a constitutional monarchy with a parliamentary system of governance.[9][10] Its capital city is London, an important global city and financial centre with the fourth-largest urban area in Europe.[11] The current monarch—since 6 February 1952—is Queen Elizabeth II. The UK consists of four countries: England, Scotland, Wales, and Northern Ireland.[12] The latter three have devolved administrations,[13] each with varying powers,[14][15] based in their capitals, Edinburgh, Cardiff, and Belfast, respectively. Guernsey, Jersey, and the Isle of Man are not part of the United Kingdom, being Crown dependencies with the British Government responsible for defence and international representation.[16] The UK has fourteen Overseas Territories,[17] including the disputed Falkland Islands, Gibraltar, and Indian Ocean Territory. +The relationships among the countries of the United Kingdom have changed over time. Wales was annexed by the Kingdom of England under the Acts of Union of 1536 and 1543. A treaty between England and Scotland resulted in a unified Kingdom of Great Britain in 1707, which in 1801, merged with the Kingdom of Ireland to form the United Kingdom of Great Britain and Ireland. In 1922, five-sixths of Ireland seceded from the country, leaving the present formulation of the United Kingdom of Great Britain and Northern Ireland.[nb 5] British Overseas Territories, formerly colonies, are the remnants of the British Empire which, at its height in the late 19th and early 20th centuries, encompassed almost a quarter of the world's land mass and was the largest empire in history. British influence can be observed in the language, culture, and legal systems of many of its former colonies. +The United Kingdom is a developed country and has the world's sixth-largest economy by nominal GDP and tenth-largest by purchasing power parity. The country is considered to have a high-income economy and is categorised as very high in the Human Development Index, currently ranking 14th in the world. It was the world's first industrialised country and the world's foremost power during the 19th and early 20th centuries.[18][19] The UK remains a great power with considerable economic, cultural, military, scientific, and political influence internationally.[20][21] It is a recognised nuclear weapons state and its military expenditure ranks fifth or sixth in the world.[22][23] The UK has been a permanent member of the United Nations Security Council since its first session in 1946. It has been a member state of the European Union (EU) and its predecessor, the European Economic Community (EEC), since 1973; it is also a member of the Commonwealth of Nations, the Council of Europe, the G7, the G8, the G20, NATO, the Organisation for Economic Co-operation and Development (OECD), and the World Trade Organization (WTO). +Contents [hide] +1 Etymology and terminology +2 History +2.1 Before 1707 +2.2 Since the Acts of Union of 1707 +3 Geography +3.1 Climate +3.2 Administrative divisions +4 Dependencies +5 Politics +5.1 Government +5.2 Devolved administrations +5.3 Law and criminal justice +5.4 Foreign relations +5.5 Military +6 Economy +6.1 Science and technology +6.2 Transport +6.3 Energy +7 Demographics +7.1 Ethnic groups +7.2 Languages +7.3 Religion +7.4 Migration +7.5 Education +7.6 Healthcare +8 Culture +8.1 Literature +8.2 Music +8.3 Visual art +8.4 Cinema +8.5 Media +8.6 Philosophy +8.7 Sport +8.8 Symbols +9 See also +10 Notes +11 References +12 Further reading +13 External links +Etymology and terminology +See also: Britain (placename) and Terminology of the British Isles +The 1707 Acts of Union declared that the kingdoms of England and Scotland were "United into One Kingdom by the Name of Great Britain", though the new state is also referred to in the Acts as the "Kingdom of Great Britain", "United Kingdom of Great Britain" and "United Kingdom".[24][25][nb 6] However, the term "united kingdom" is only found in informal use during the 18th century and the country was only occasionally referred to as he "United Kingdom of Great Britain".[26] The Acts of Union 1800 united the Kingdom of Great Britain and the Kingdom of Ireland in 1801, forming the United Kingdom of Great Britain and Ireland. The name "United Kingdom of Great Britain and Northern Ireland" was adopted following the independence of the Irish Free State, and the partition of Ireland, in 1922, which left Northern Ireland as the only part of the island of Ireland within the UK.[27] +Although the United Kingdom, as a sovereign state, is a country, England, Scotland, Wales, and to a lesser degree, Northern Ireland, are also regarded as countries, though they are not sovereign states.[28][29] Scotland, Wales and Northern Ireland have devolved self-government.[30][31] The British Prime Minister's website has used the phrase "countries within a country" to describe the United Kingdom.[12] Some statistical summaries, such as those for the twelve NUTS 1 regions of the UK, also refer to Scotland, Wales and Northern Ireland as "regions".[32][33] Northern Ireland is also referred to as a "province".[28][34] With regard to Northern Ireland, the descriptive name used "can be controversial, with the choice often revealing one's political preferences."[35] +The term Britain is often used as synonym for the United Kingdom. The term Great Britain, by contrast, refers conventionally to the island of Great Britain, or politically to England, Scotland and Wales in combination.[36][37][38] However, it is sometimes used as a loose synonym for the United Kingdom as a whole.[39][40] GB and GBR are the standard country codes for the United Kingdom (see ISO 3166-2 and ISO 3166-1 alpha-3) and are consequently used by international organisations to refer to the United Kingdom. Additionally, the United Kingdom's Olympic team competes under the name "Great Britain" or "Team GB".[41][42] +The adjective British is commonly used to refer to matters relating to the United Kingdom. The term has no definite legal connotation, but is used in law to refer to UK citizenship and matters to do with nationality.[43] People of the United Kingdom use a number of different terms to describe their national identity and may identify themselves as being British; or as being English, Scottish, Welsh, Northern Irish, or Irish;[44] or as being both.[45] +In 2006, a new design of British passport was introduced. Its first page shows the long form name of the state in English, Welsh and Scottish Gaelic.[46] In Welsh, the long form name of the state is "Teyrnas Unedig Prydain Fawr a Gogledd Iwerddon" with "Teyrnas Unedig" being used as a short form name on government websites.[47] In Scottish Gaelic, the long form is "Rìoghachd Aonaichte Bhreatainn is Èireann a Tuath" and the short form "Rìoghachd Aonaichte". +History +See also: History of the British Isles +Before 1707 + +Stonehenge, in Wiltshire, was erected around 2500 BC. +Main articles: History of England, History of Wales, History of Scotland, History of Ireland and History of the formation of the United Kingdom +Settlement by anatomically modern humans of what was to become the United Kingdom occurred in waves beginning by about 30,000 years ago.[48] By the end of the region's prehistoric period, the population is thought to have belonged, in the main, to a culture termed Insular Celtic, comprising Brythonic Britain and Gaelic Ireland.[49] The Roman conquest, beginning in 43 AD, and the 400-year rule of southern Britain, was followed by an invasion by Germanic Anglo-Saxon settlers, reducing the Brythonic area mainly to what was to become Wales and the historic Kingdom of Strathclyde.[50] Most of the region settled by the Anglo-Saxons became unified as the Kingdom of England in the 10th century.[51] Meanwhile, Gaelic-speakers in north west Britain (with connections to the north-east of Ireland and traditionally supposed to have migrated from there in the 5th century)[52][53] united with the Picts to create the Kingdom of Scotland in the 9th century.[54] +In 1066, the Normans invaded England from France and after its conquest, seized large parts of Wales, conquered much of Ireland and were invited to settle in Scotland, bringing to each country feudalism on the Northern French model and Norman-French culture.[55] The Norman elites greatly influenced, but eventually assimilated with, each of the local cultures.[56] Subsequent medieval English kings completed the conquest of Wales and made an unsuccessful attempt to annex Scotland. Thereafter, Scotland maintained its independence, albeit in near-constant conflict with England. The English monarchs, through inheritance of substantial territories in France and claims to the French crown, were also heavily involved in conflicts in France, most notably the Hundred Years War, while the Kings of Scots were in an alliance with the French during this period.[57] + +The Bayeux Tapestry depicts the Battle of Hastings and the events leading to it. +The early modern period saw religious conflict resulting from the Reformation and the introduction of Protestant state churches in each country.[58] Wales was fully incorporated into the Kingdom of England,[59] and Ireland was constituted as a kingdom in personal union with the English crown.[60] In what was to become Northern Ireland, the lands of the independent Catholic Gaelic nobility were confiscated and given to Protestant settlers from England and Scotland.[61] +In 1603, the kingdoms of England, Scotland and Ireland were united in a personal union when James VI, King of Scots, inherited the crowns of England and Ireland and moved his court from Edinburgh to London; each country nevertheless remained a separate political entity and retained its separate political, legal, and religious institutions.[62][63] +In the mid-17th century, all three kingdoms were involved in a series of connected wars (including the English Civil War) which led to the temporary overthrow of the monarchy and the establishment of the short-lived unitary republic of the Commonwealth of England, Scotland and Ireland.[64][65] +Although the monarchy was restored, it ensured (with the Glorious Revolution of 1688) that, unlike much of the rest of Europe, royal absolutism would not prevail, and a professed Catholic could never accede to the throne. The British constitution would develop on the basis of constitutional monarchy and the parliamentary system.[66] During this period, particularly in England, the development of naval power (and the interest in voyages of discovery) led to the acquisition and settlement of overseas colonies, particularly in North America.[67][68] +Since the Acts of Union of 1707 +Main article: History of the United Kingdom + +The Treaty of Union led to a single united kingdom encompassing all Great Britain. +On 1 May 1707, the united kingdom of Great Britain came into being, the result of Acts of Union being passed by the parliaments of England and Scotland to ratify the 1706 Treaty of Union and so unite the two kingdoms.[69][70][71] +In the 18th century, cabinet government developed under Robert Walpole, in practice the first prime minister (1721–1742). A series of Jacobite Uprisings sought to remove the Protestant House of Hanover from the British throne and restore the Catholic House of Stuart. The Jacobites were finally defeated at the Battle of Culloden in 1746, after which the Scottish Highlanders were brutally suppressed. The British colonies in North America that broke away from Britain in the American War of Independence became the United States of America in 1782. British imperial ambition turned elsewhere, particularly to India.[72] +During the 18th century, Britain was involved in the Atlantic slave trade. British ships transported an estimated 2 million slaves from Africa to the West Indies before banning the trade in 1807.[73] The term 'United Kingdom' became official in 1801 when the parliaments of Britain and Ireland each passed an Act of Union, uniting the two kingdoms and creating the United Kingdom of Great Britain and Ireland.[74] +In the early 19th century, the British-led Industrial Revolution began to transform the country. It slowly led to a shift in political power away from the old Tory and Whig landowning classes towards the new industrialists. An alliance of merchants and industrialists with the Whigs would lead to a new party, the Liberals, with an ideology of free trade and laissez-faire. In 1832 Parliament passed the Great Reform Act, which began the transfer of political power from the aristocracy to the middle classes. In the countryside, enclosure of the land was driving small farmers out. Towns and cities began to swell with a new urban working class. Few ordinary workers had the vote, and they created their own organisations in the form of trade unions. +Painting of a bloody battle. Horses and infantry fight or lie on grass. +The Battle of Waterloo marked the end of the Napoleonic Wars and the start of Pax Britannica. +After the defeat of France in the Revolutionary and Napoleonic Wars (1792–1815), the UK emerged as the principal naval and imperial power of the 19th century (with London the largest city in the world from about 1830).[75] Unchallenged at sea, British dominance was later described as Pax Britannica.[76][77] By the time of the Great Exhibition of 1851, Britain was described as the "workshop of the world".[78] The British Empire was expanded to include India, large parts of Africa and many other territories throughout the world. Alongside the formal control it exerted over its own colonies, British dominance of much of world trade meant that it effectively controlled the economies of many countries, such as China, Argentina and Siam.[79][80] Domestically, political attitudes favoured free trade and laissez-faire policies and a gradual widening of the voting franchise. During the century, the population increased at a dramatic rate, accompanied by rapid urbanisation, causing significant social and economic stresses.[81] After 1875, the UK's industrial monopoly was challenged by Germany and the USA. To seek new markets and sources of raw materials, the Conservative Party under Disraeli launched a period of imperialist expansion in Egypt, South Africa and elsewhere. Canada, Australia and New Zealand became self-governing dominions.[82] +Social reform and home rule for Ireland were important domestic issues after 1900. The Labour Party emerged from an alliance of trade unions and small Socialist groups in 1900, and suffragettes campaigned for women's right to vote before 1914. +Black-and-white photo of two dozen men in military uniforms and metal helmets sitting or standing in a muddy trench. +Infantry of the Royal Irish Rifles during the Battle of the Somme. More than 885,000 British soldiers died on the battlefields of World War I. +The UK fought with France, Russia and (after 1917) the US, against Germany and its allies in World War I (1914–18).[83] The UK armed forces were engaged across much of the British Empire and in several regions of Europe, particularly on the Western front.[84] The high fatalities of trench warfare caused the loss of much of a generation of men, with lasting social effects in the nation and a great disruption in the social order. +After the war, the UK received the League of Nations mandate over a number of former German and Ottoman colonies. The British Empire reached its greatest extent, covering a fifth of the world's land surface and a quarter of its population.[85] However, the UK had suffered 2.5 million casualties and finished the war with a huge national debt.[84] The rise of Irish Nationalism and disputes within Ireland over the terms of Irish Home Rule led eventually to the partition of the island in 1921,[86] and the Irish Free State became independent with Dominion status in 1922. Northern Ireland remained part of the United Kingdom.[87] A wave of strikes in the mid-1920s culminated in the UK General Strike of 1926. The UK had still not recovered from the effects of the war when the Great Depression (1929–32) occurred. This led to considerable unemployment and hardship in the old industrial areas, as well as political and social unrest in the 1930s. A coalition government was formed in 1931.[88] +The UK entered World War II by declaring war on Germany in 1939, after it had invaded Poland and Czechoslovakia. In 1940, Winston Churchill became prime minister and head of a coalition government. Despite the defeat of its European allies in the first year of the war, the UK continued the fight alone against Germany. In 1940, the RAF defeated the German Luftwaffe in a struggle for control of the skies in the Battle of Britain. The UK suffered heavy bombing during the Blitz. There were also eventual hard-fought victories in the Battle of the Atlantic, the North Africa campaign and Burma campaign. UK forces played an important role in the Normandy landings of 1944, achieved with its ally the US. After Germany's defeat, the UK was one of the Big Three powers who met to plan the post-war world; it was an original signatory to the Declaration of the United Nations. The UK became one of the five permanent members of the United Nations Security Council. However, the war left the UK severely weakened and depending financially on Marshall Aid and loans from the United States.[89] +Map of the world. Canada, the eastern United States, countries in east Africa, India, most of Australasia and some other countries are highlighted in pink. +Territories that were at one time part of the British Empire. Current British Overseas Territories are underlined in red. +In the immediate post-war years, the Labour government initiated a radical programme of reforms, which had a significant effect on British society in the following decades.[90] Major industries and public utilities were nationalised, a Welfare State was established, and a comprehensive, publicly funded healthcare system, the National Health Service, was created.[91] The rise of nationalism in the colonies coincided with Britain's now much-diminished economic position, so that a policy of decolonisation was unavoidable. Independence was granted to India and Pakistan in 1947.[92] Over the next three decades, most colonies of the British Empire gained their independence. Many became members of the Commonwealth of Nations.[93] +Although the UK was the third country to develop a nuclear weapons arsenal (with its first atomic bomb test in 1952), the new post-war limits of Britain's international role were illustrated by the Suez Crisis of 1956. The international spread of the English language ensured the continuing international influence of its literature and culture. From the 1960s onward, its popular culture was also influential abroad. As a result of a shortage of workers in the 1950s, the UK government encouraged immigration from Commonwealth countries. In the following decades, the UK became a multi-ethnic society.[94] Despite rising living standards in the late 1950s and 1960s, the UK's economic performance was not as successful as many of its competitors, such as West Germany and Japan. In 1973, the UK joined the European Economic Community (EEC), and when the EEC became the European Union (EU) in 1992, it was one of the 12 founding members. + +After the two vetos of France in 1961 and 1967, the UK entered in the European Union in 1973. In 1975, 67% of Britons voted yes to the permanence in the European Union. +From the late 1960s, Northern Ireland suffered communal and paramilitary violence (sometimes affecting other parts of the UK) conventionally known as the Troubles. It is usually considered to have ended with the Belfast "Good Friday" Agreement of 1998.[95][96][97] +Following a period of widespread economic slowdown and industrial strife in the 1970s, the Conservative Government of the 1980s initiated a radical policy of monetarism, deregulation, particularly of the financial sector (for example, Big Bang in 1986) and labour markets, the sale of state-owned companies (privatisation), and the withdrawal of subsidies to others.[98] This resulted in high unemployment and social unrest, but ultimately also economic growth, particularly in the services sector. From 1984, the economy was helped by the inflow of substantial North Sea oil revenues.[99] +Around the end of the 20th century there were major changes to the governance of the UK with the establishment of devolved administrations for Scotland, Wales and Northern Ireland.[13][100] The statutory incorporation followed acceptance of the European Convention on Human Rights. The UK is still a key global player diplomatically and militarily. It plays leading roles in the EU, UN and NATO. However, controversy surrounds some of Britain's overseas military deployments, particularly in Afghanistan and Iraq.[101] +The 2008 global financial crisis severely affected the UK economy. The coalition government of 2010 introduced austerity measures intended to tackle the substantial public deficits which resulted.[102] In 2014 the Scottish Government held a referendum on Scottish independence, with the majority of voters rejecting the independence proposal and opting to remain within the United Kingdom.[103] +Geography +Main article: Geography of the United Kingdom +Map of United Kingdom showing hilly regions to north and west, and flattest region in the south-east. +The topography of the UK +The total area of the United Kingdom is approximately 243,610 square kilometres (94,060 sq mi). The country occupies the major part of the British Isles[104] archipelago and includes the island of Great Britain, the northeastern one-sixth of the island of Ireland and some smaller surrounding islands. It lies between the North Atlantic Ocean and the North Sea with the south-east coast coming within 22 miles (35 km) of the coast of northern France, from which it is separated by the English Channel.[105] In 1993 10% of the UK was forested, 46% used for pastures and 25% cultivated for agriculture.[106] The Royal Greenwich Observatory in London is the defining point of the Prime Meridian.[107] +The United Kingdom lies between latitudes 49° to 61° N, and longitudes 9° W to 2° E. Northern Ireland shares a 224-mile (360 km) land boundary with the Republic of Ireland.[105] The coastline of Great Britain is 11,073 miles (17,820 km) long.[108] It is connected to continental Europe by the Channel Tunnel, which at 31 miles (50 km) (24 miles (38 km) underwater) is the longest underwater tunnel in the world.[109] +England accounts for just over half of the total area of the UK, covering 130,395 square kilometres (50,350 sq mi).[110] Most of the country consists of lowland terrain,[106] with mountainous terrain north-west of the Tees-Exe line; including the Cumbrian Mountains of the Lake District, the Pennines and limestone hills of the Peak District, Exmoor and Dartmoor. The main rivers and estuaries are the Thames, Severn and the Humber. England's highest mountain is Scafell Pike (978 metres (3,209 ft)) in the Lake District. Its principal rivers are the Severn, Thames, Humber, Tees, Tyne, Tweed, Avon, Exe and Mersey.[106] +Scotland accounts for just under a third of the total area of the UK, covering 78,772 square kilometres (30,410 sq mi)[111] and including nearly eight hundred islands,[112] predominantly west and north of the mainland; notably the Hebrides, Orkney Islands and Shetland Islands. The topography of Scotland is distinguished by the Highland Boundary Fault – a geological rock fracture – which traverses Scotland from Arran in the west to Stonehaven in the east.[113] The faultline separates two distinctively different regions; namely the Highlands to the north and west and the lowlands to the south and east. The more rugged Highland region contains the majority of Scotland's mountainous land, including Ben Nevis which at 1,343 metres (4,406 ft) is the highest point in the British Isles.[114] Lowland areas – especially the narrow waist of land between the Firth of Clyde and the Firth of Forth known as the Central Belt – are flatter and home to most of the population including Glasgow, Scotland's largest city, and Edinburgh, its capital and political centre. +A view of Ben Nevis in the distance, fronted by rolling plains +Ben Nevis, in Scotland, is the highest point in the British Isles +Wales accounts for less than a tenth of the total area of the UK, covering 20,779 square kilometres (8,020 sq mi).[115] Wales is mostly mountainous, though South Wales is less mountainous than North and mid Wales. The main population and industrial areas are in South Wales, consisting of the coastal cities of Cardiff, Swansea and Newport, and the South Wales Valleys to their north. The highest mountains in Wales are in Snowdonia and include Snowdon (Welsh: Yr Wyddfa) which, at 1,085 metres (3,560 ft), is the highest peak in Wales.[106] The 14, or possibly 15, Welsh mountains over 3,000 feet (914 m) high are known collectively as the Welsh 3000s. Wales has over 2,704 kilometres (1,680 miles) of coastline.[116] Several islands lie off the Welsh mainland, the largest of which is Anglesey (Ynys Môn) in the northwest. +Northern Ireland, separated from Great Britain by the Irish Sea and North Channel, has an area of 14,160 square kilometres (5,470 sq mi) and is mostly hilly. It includes Lough Neagh which, at 388 square kilometres (150 sq mi), is the largest lake in the British Isles by area.[117] The highest peak in Northern Ireland is Slieve Donard in the Mourne Mountains at 852 metres (2,795 ft).[106] +Climate +Main article: Climate of the United Kingdom +The United Kingdom has a temperate climate, with plentiful rainfall all year round.[105] The temperature varies with the seasons seldom dropping below −11 °C (12 °F) or rising above 35 °C (95 °F).[118] The prevailing wind is from the south-west and bears frequent spells of mild and wet weather from the Atlantic Ocean,[105] although the eastern parts are mostly sheltered from this wind since the majority of the rain falls over the western regions the eastern parts are therefore the driest. Atlantic currents, warmed by the Gulf Stream, bring mild winters; especially in the west where winters are wet and even more so over high ground. Summers are warmest in the south-east of England, being closest to the European mainland, and coolest in the north. Heavy snowfall can occur in winter and early spring on high ground, and occasionally settles to great depth away from the hills. +Administrative divisions +Main article: Administrative geography of the United Kingdom +Each country of the United Kingdom has its own system of administrative and geographic demarcation, whose origins often pre-date the formation of the United Kingdom. Thus there is "no common stratum of administrative unit encompassing the United Kingdom".[119] Until the 19th century there was little change to those arrangements, but there has since been a constant evolution of role and function.[120] Change did not occur in a uniform manner and the devolution of power over local government to Scotland, Wales and Northern Ireland means that future changes are unlikely to be uniform either. +The organisation of local government in England is complex, with the distribution of functions varying according to local arrangements. Legislation concerning local government in England is the responsibility of the UK parliament and the Government of the United Kingdom, as England has no devolved parliament. The upper-tier subdivisions of England are the nine Government office regions or European Union government office regions.[121] One region, Greater London, has had a directly elected assembly and mayor since 2000 following popular support for the proposal in a referendum.[122] It was intended that other regions would also be given their own elected regional assemblies, but a proposed assembly in the North East region was rejected by a referendum in 2004.[123] Below the regional tier, some parts of England have county councils and district councils and others have unitary authorities; while London consists of 32 London boroughs and the City of London. Councillors are elected by the first-past-the-post system in single-member wards or by the multi-member plurality system in multi-member wards.[124] +For local government purposes, Scotland is divided into 32 council areas, with wide variation in both size and population. The cities of Glasgow, Edinburgh, Aberdeen and Dundee are separate council areas, as is the Highland Council which includes a third of Scotland's area but only just over 200,000 people. Local councils are made up of elected councillors, of whom there are currently 1,222;[125] they are paid a part-time salary. Elections are conducted by single transferable vote in multi-member wards that elect either three or four councillors. Each council elects a Provost, or Convenor, to chair meetings of the council and to act as a figurehead for the area. Councillors are subject to a code of conduct enforced by the Standards Commission for Scotland.[126] The representative association of Scotland's local authorities is the Convention of Scottish Local Authorities (COSLA).[127] +Local government in Wales consists of 22 unitary authorities. These include the cities of Cardiff, Swansea and Newport which are unitary authorities in their own right.[128] Elections are held every four years under the first-past-the-post system.[129] The most recent elections were held in May 2012, except for the Isle of Anglesey. The Welsh Local Government Association represents the interests of local authorities in Wales.[130] +Local government in Northern Ireland has since 1973 been organised into 26 district councils, each elected by single transferable vote. Their powers are limited to services such as collecting waste, controlling dogs and maintaining parks and cemeteries.[131] On 13 March 2008 the executive agreed on proposals to create 11 new councils and replace the present system.[132] The next local elections were postponed until 2016 to facilitate this.[133] +Dependencies + +A view of the Caribbean Sea from the Cayman Islands, one of the world's foremost international financial centres[134] and tourist destinations.[135] +Main articles: British Overseas Territories, Crown dependencies and British Islands +The United Kingdom has sovereignty over seventeen territories which do not form part of the United Kingdom itself: fourteen British Overseas Territories[136] and three Crown dependencies.[137] +The fourteen British Overseas Territories are: Anguilla; Bermuda; the British Antarctic Territory; the British Indian Ocean Territory; the British Virgin Islands; the Cayman Islands; the Falkland Islands; Gibraltar; Montserrat; Saint Helena, Ascension and Tristan da Cunha; the Turks and Caicos Islands; the Pitcairn Islands; South Georgia and the South Sandwich Islands; and Sovereign Base Areas on Cyprus.[138] British claims in Antarctica are not universally recognised.[139] Collectively Britain's overseas territories encompass an approximate land area of 1,727,570 square kilometres (667,018 sq mi) and a population of approximately 260,000 people.[140] They are the remnants of the British Empire and several have specifically voted to remain British territories (Bermuda in 1995, Gibraltar in 2002 and the Falkland Islands in 2013).[141] +The Crown dependencies are possessions of the Crown, as opposed to overseas territories of the UK.[142] They comprise three independently administered jurisdictions: the Channel Islands of Jersey and Guernsey in the English Channel, and the Isle of Man in the Irish Sea. By mutual agreement, the British Government manages the islands' foreign affairs and defence and the UK Parliament has the authority to legislate on their behalf. However, internationally, they are regarded as "territories for which the United Kingdom is responsible".[143] The power to pass legislation affecting the islands ultimately rests with their own respective legislative assemblies, with the assent of the Crown (Privy Council or, in the case of the Isle of Man, in certain circumstances the Lieutenant-Governor).[144] Since 2005 each Crown dependency has had a Chief Minister as its head of government.[145] +Politics +Main articles: Politics of the United Kingdom, Monarchy of the United Kingdom and Elections in the United Kingdom +Elderly lady with a yellow hat and grey hair is smiling in outdoor setting. +Elizabeth II, Queen of the United Kingdom and the other Commonwealth realms +The United Kingdom is a unitary state under a constitutional monarchy. Queen Elizabeth II is the head of state of the UK as well as monarch of fifteen other independent Commonwealth countries. The monarch has "the right to be consulted, the right to encourage, and the right to warn".[146] The United Kingdom is one of only four countries in the world to have an uncodified constitution.[147][nb 7] The Constitution of the United Kingdom thus consists mostly of a collection of disparate written sources, including statutes, judge-made case law and international treaties, together with constitutional conventions. As there is no technical difference between ordinary statutes and "constitutional law", the UK Parliament can perform "constitutional reform" simply by passing Acts of Parliament, and thus has the political power to change or abolish almost any written or unwritten element of the constitution. However, no Parliament can pass laws that future Parliaments cannot change.[148] +Government +Main article: Government of the United Kingdom +The UK has a parliamentary government based on the Westminster system that has been emulated around the world: a legacy of the British Empire. The parliament of the United Kingdom that meets in the Palace of Westminster has two houses; an elected House of Commons and an appointed House of Lords. All bills passed are given Royal Assent before becoming law. +The position of prime minister,[nb 8] the UK's head of government,[149] belongs to the person most likely to command the confidence of the House of Commons; this individual is typically the leader of the political party or coalition of parties that holds the largest number of seats in that chamber. The prime minister chooses a cabinet and they are formally appointed by the monarch to form Her Majesty's Government. By convention, the Queen respects the prime minister's decisions of government.[150] +Large sand-coloured building of Gothic design beside brown river and road bridge. The building has several large towers, including large clock-tower. +The Palace of Westminster, seat of both houses of the Parliament of the United Kingdom +The cabinet is traditionally drawn from members of a prime minister's party or coalition and mostly from the House of Commons but always from both legislative houses, the cabinet being responsible to both. Executive power is exercised by the prime minister and cabinet, all of whom are sworn into the Privy Council of the United Kingdom, and become Ministers of the Crown. The current Prime Minister is David Cameron, who has been in office since 11 May 2010.[151] Cameron is the leader of the Conservative Party and heads a coalition with the Liberal Democrats. For elections to the House of Commons, the UK is currently divided into 650 constituencies,[152] each electing a single member of parliament (MP) by simple plurality. General elections are called by the monarch when the prime minister so advises. The Parliament Acts 1911 and 1949 require that a new election must be called no later than five years after the previous general election.[153] +The UK's three major political parties are the Conservative Party (Tories), the Labour Party and the Liberal Democrats, representing the British traditions of conservatism, socialism and social liberalism, respectively. During the 2010 general election these three parties won 622 out of 650 seats available in the House of Commons.[154][155] Most of the remaining seats were won by parties that contest elections only in one part of the UK: the Scottish National Party (Scotland only); Plaid Cymru (Wales only); and the Alliance Party, Democratic Unionist Party, Social Democratic and Labour Party and Sinn Féin (Northern Ireland only[nb 9]). In accordance with party policy, no elected Sinn Féin members of parliament have ever attended the House of Commons to speak on behalf of their constituents because of the requirement to take an oath of allegiance to the monarch. +Devolved administrations +Main articles: Devolution in the United Kingdom, Northern Ireland Executive, Scottish Government and Welsh Government +Modern one-story building with grass on roof and large sculpted grass area in front. Behind are residential buildings in a mixture of styles. +The Scottish Parliament Building in Holyrood is the seat of the Scottish Parliament. +Scotland, Wales and Northern Ireland each have their own government or executive, led by a First Minister (or, in the case of Northern Ireland, a diarchal First Minister and deputy First Minister), and a devolved unicameral legislature. England, the largest country of the United Kingdom, has no such devolved executive or legislature and is administered and legislated for directly by the UK government and parliament on all issues. This situation has given rise to the so-called West Lothian question which concerns the fact that members of parliament from Scotland, Wales and Northern Ireland can vote, sometimes decisively,[156] on matters that only affect England.[157] The McKay Commission reported on this matter in March 2013 recommending that laws affecting only England should need support from a majority of English members of parliament.[158] +The Scottish Government and Parliament have wide-ranging powers over any matter that has not been specifically reserved to the UK parliament, including education, healthcare, Scots law and local government.[159] At the 2011 elections the Scottish National Party won re-election and achieved an overall majority in the Scottish parliament, with its leader, Alex Salmond, as First Minister of Scotland.[160][161] In 2012, the UK and Scottish governments signed the Edinburgh Agreement setting out the terms for a referendum on Scottish independence in 2014, which was defeated 55% to 45%. +The Welsh Government and the National Assembly for Wales have more limited powers than those devolved to Scotland.[162] The Assembly is able to legislate on devolved matters through Acts of the Assembly, which require no prior consent from Westminster. The 2011 elections resulted in a minority Labour administration led by Carwyn Jones.[163] +The Northern Ireland Executive and Assembly have powers similar to those devolved to Scotland. The Executive is led by a diarchy representing unionist and nationalist members of the Assembly. Currently, Peter Robinson (Democratic Unionist Party) and Martin McGuinness (Sinn Féin) are First Minister and deputy First Minister respectively.[164] Devolution to Northern Ireland is contingent on participation by the Northern Ireland administration in the North-South Ministerial Council, where the Northern Ireland Executive cooperates and develops joint and shared policies with the Government of Ireland. The British and Irish governments co-operate on non-devolved matters affecting Northern Ireland through the British–Irish Intergovernmental Conference, which assumes the responsibilities of the Northern Ireland administration in the event of its non-operation. +The UK does not have a codified constitution and constitutional matters are not among the powers devolved to Scotland, Wales or Northern Ireland. Under the doctrine of parliamentary sovereignty, the UK Parliament could, in theory, therefore, abolish the Scottish Parliament, Welsh Assembly or Northern Ireland Assembly.[165][166] Indeed, in 1972, the UK Parliament unilaterally prorogued the Parliament of Northern Ireland, setting a precedent relevant to contemporary devolved institutions.[167] In practice, it would be politically difficult for the UK Parliament to abolish devolution to the Scottish Parliament and the Welsh Assembly, given the political entrenchment created by referendum decisions.[168] The political constraints placed upon the UK Parliament's power to interfere with devolution in Northern Ireland are even greater than in relation to Scotland and Wales, given that devolution in Northern Ireland rests upon an international agreement with the Government of Ireland.[169] +Law and criminal justice +Main article: Law of the United Kingdom + +The Royal Courts of Justice of England and Wales +The United Kingdom does not have a single legal system, as Article 19 of the 1706 Treaty of Union provided for the continuation of Scotland's separate legal system.[170] Today the UK has three distinct systems of law: English law, Northern Ireland law and Scots law. A new Supreme Court of the United Kingdom came into being in October 2009 to replace the Appellate Committee of the House of Lords.[171][172] The Judicial Committee of the Privy Council, including the same members as the Supreme Court, is the highest court of appeal for several independent Commonwealth countries, the British Overseas Territories and the Crown Dependencies.[173] +Both English law, which applies in England and Wales, and Northern Ireland law are based on common-law principles.[174] The essence of common law is that, subject to statute, the law is developed by judges in courts, applying statute, precedent and common sense to the facts before them to give explanatory judgements of the relevant legal principles, which are reported and binding in future similar cases (stare decisis).[175] The courts of England and Wales are headed by the Senior Courts of England and Wales, consisting of the Court of Appeal, the High Court of Justice (for civil cases) and the Crown Court (for criminal cases). The Supreme Court is the highest court in the land for both criminal and civil appeal cases in England, Wales and Northern Ireland and any decision it makes is binding on every other court in the same jurisdiction, often having a persuasive effect in other jurisdictions.[176] + +The High Court of Justiciary – the supreme criminal court of Scotland. +Scots law is a hybrid system based on both common-law and civil-law principles. The chief courts are the Court of Session, for civil cases,[177] and the High Court of Justiciary, for criminal cases.[178] The Supreme Court of the United Kingdom serves as the highest court of appeal for civil cases under Scots law.[179] Sheriff courts deal with most civil and criminal cases including conducting criminal trials with a jury, known as sheriff solemn court, or with a sheriff and no jury, known as sheriff summary Court.[180] The Scots legal system is unique in having three possible verdicts for a criminal trial: "guilty", "not guilty" and "not proven". Both "not guilty" and "not proven" result in an acquittal.[181] +Crime in England and Wales increased in the period between 1981 and 1995, though since that peak there has been an overall fall of 48% in crime from 1995 to 2007/08,[182] according to crime statistics. The prison population of England and Wales has almost doubled over the same period, to over 80,000, giving England and Wales the highest rate of incarceration in Western Europe at 147 per 100,000.[183] Her Majesty's Prison Service, which reports to the Ministry of Justice, manages most of the prisons within England and Wales. Crime in Scotland fell to its lowest recorded level for 32 years in 2009/10, falling by ten per cent.[184] At the same time Scotland's prison population, at over 8,000,[185] is at record levels and well above design capacity.[186] The Scottish Prison Service, which reports to the Cabinet Secretary for Justice, manages Scotland's prisons. +Foreign relations +Main article: Foreign relations of the United Kingdom + +The Prime Minister of the United Kingdom, David Cameron, and the President of the United States, Barack Obama, during the 2010 G-20 Toronto summit. +The UK is a permanent member of the United Nations Security Council, a member of NATO, the Commonwealth of Nations, G7, G8, G20, the OECD, the WTO, the Council of Europe, the OSCE, and is a member state of the European Union. The UK is said to have a "Special Relationship" with the United States and a close partnership with France—the "Entente cordiale"—and shares nuclear weapons technology with both countries.[187][188] The UK is also closely linked with the Republic of Ireland; the two countries share a Common Travel Area and co-operate through the British-Irish Intergovernmental Conference and the British-Irish Council. Britain's global presence and influence is further amplified through its trading relations, foreign investments, official development assistance and military engagements.[189] +Military + +Troopers of the Blues and Royals during the 2007 Trooping the Colour ceremony +Main article: British Armed Forces +The armed forces of the United Kingdom—officially, Her Majesty's Armed Forces—consist of three professional service branches: the Royal Navy and Royal Marines (forming the Naval Service), the British Army and the Royal Air Force.[190] The forces are managed by the Ministry of Defence and controlled by the Defence Council, chaired by the Secretary of State for Defence. The Commander-in-Chief is the British monarch, Elizabeth II, to whom members of the forces swear an oath of allegiance.[191] The Armed Forces are charged with protecting the UK and its overseas territories, promoting the UK's global security interests and supporting international peacekeeping efforts. They are active and regular participants in NATO, including the Allied Rapid Reaction Corps, as well as the Five Power Defence Arrangements, RIMPAC and other worldwide coalition operations. Overseas garrisons and facilities are maintained in Ascension Island, Belize, Brunei, Canada, Cyprus, Diego Garcia, the Falkland Islands, Germany, Gibraltar, Kenya and Qatar.[192] +The British armed forces played a key role in establishing the British Empire as the dominant world power in the 18th, 19th and early 20th centuries. Throughout its unique history the British forces have seen action in a number of major wars, such as the Seven Years' War, the Napoleonic Wars, the Crimean War, World War I and World War II—as well as many colonial conflicts. By emerging victorious from such conflicts, Britain has often been able to decisively influence world events. Since the end of the British Empire, the UK has nonetheless remained a major military power. Following the end of the Cold War, defence policy has a stated assumption that "the most demanding operations" will be undertaken as part of a coalition.[193] Setting aside the intervention in Sierra Leone, recent UK military operations in Bosnia, Kosovo, Afghanistan, Iraq and, most recently, Libya, have followed this approach. The last time the British military fought alone was the Falklands War of 1982. +According to various sources, including the Stockholm International Peace Research Institute and the International Institute for Strategic Studies, the United Kingdom has the fifth- or sixth-highest military expenditure in the world. Total defence spending currently accounts for around 2.4% of total national GDP.[22][23] +Economy +Main article: Economy of the United Kingdom + +The Bank of England – the central bank of the United Kingdom +The UK has a partially regulated market economy.[194] Based on market exchange rates the UK is today the sixth-largest economy in the world and the third-largest in Europe after Germany and France, having fallen behind France for the first time in over a decade in 2008.[195] HM Treasury, led by the Chancellor of the Exchequer, is responsible for developing and executing the British government's public finance policy and economic policy. The Bank of England is the UK's central bank and is responsible for issuing notes and coins in the nation's currency, the pound sterling. Banks in Scotland and Northern Ireland retain the right to issue their own notes, subject to retaining enough Bank of England notes in reserve to cover their issue. Pound sterling is the world's third-largest reserve currency (after the US Dollar and the Euro).[196] Since 1997 the Bank of England's Monetary Policy Committee, headed by the Governor of the Bank of England, has been responsible for setting interest rates at the level necessary to achieve the overall inflation target for the economy that is set by the Chancellor each year.[197] +The UK service sector makes up around 73% of GDP.[198] London is one of the three "command centres" of the global economy (alongside New York City and Tokyo),[199] it is the world's largest financial centre alongside New York,[200][201][202] and it has the largest city GDP in Europe.[203] Edinburgh is also one of the largest financial centres in Europe.[204] Tourism is very important to the British economy and, with over 27 million tourists arriving in 2004, the United Kingdom is ranked as the sixth major tourist destination in the world and London has the most international visitors of any city in the world.[205][206] The creative industries accounted for 7% GVA in 2005 and grew at an average of 6% per annum between 1997 and 2005.[207] + +The Airbus A350 has its wings and engines manufactured in the UK. +The Industrial Revolution started in the UK with an initial concentration on the textile industry,[208] followed by other heavy industries such as shipbuilding, coal mining and steelmaking.[209][210] +The empire was exploited as an overseas market for British products, allowing the UK to dominate international trade in the 19th century. As other nations industrialised, coupled with economic decline after two world wars, the United Kingdom began to lose its competitive advantage and heavy industry declined, by degrees, throughout the 20th century. Manufacturing remains a significant part of the economy but accounted for only 16.7% of national output in 2003.[211] +The automotive industry is a significant part of the UK manufacturing sector and employs over 800,000 people, with a turnover of some £52 billion, generating £26.6 billion of exports.[212] +The aerospace industry of the UK is the second- or third-largest national aerospace industry in the world depending upon the method of measurement and has an annual turnover of around £20 billion. The wings for the Airbus A380 and the A350 XWB are designed and manufactured at Airbus UK's world-leading Broughton facility, whilst over a quarter of the value of the Boeing 787 comes from UK manufacturers including Eaton (fuel subsystem pumps), Messier-Bugatti-Dowty (the landing gear) and Rolls-Royce (the engines). Other key names include GKN Aerospace – an expert in metallic and composite aerostructures that's involved in almost every civil and military fixed and rotary wing aircraft in production and development today.[213][214][215][216] +BAE Systems - plays a critical role on some of the world's biggest defence aerospace projects. The company makes large sections of the Typhoon Eurofighter at its sub-assembly plant in Salmesbury and assembles the aircraft for the RAF at its Warton Plant, near Preston. It is also a principal subcontractor on the F35 Joint Strike Fighter - the world's largest single defence project - for which it designs and manufactures a range of components including the aft fuselage, vertical and horizontal tail and wing tips and fuel system. As well as this it manufactures the Hawk, the world's most successful jet training aircraft.[216] Airbus UK also manufactures the wings for the A400m military transporter. Rolls-Royce, is the world's second-largest aero-engine manufacturer. Its engines power more than 30 types of commercial aircraft and it has more than 30,000 engines currently in service across both the civil and defence sectors. Agusta Westland designs and manufactures complete helicopters in the UK.[216] +The UK space industry is growing very fast. Worth £9.1bn in 2011 and employing 29,000 people, it is growing at a rate of some 7.5 per cent annually, according to its umbrella organisation, the UK Space Agency. Government strategy is for the space industry to be a £40bn business for the UK by 2030, capturing a 10 per cent share of the $250bn world market for commercial space technology.[216] On 16 July 2013, the British government pledged £60m to the Skylon project: this investment will provide support at a "crucial stage" to allow a full-scale prototype of the SABRE engine to be built. +The pharmaceutical industry plays an important role in the UK economy and the country has the third-highest share of global pharmaceutical R&D expenditures (after the United States and Japan).[217][218] +Agriculture is intensive, highly mechanised and efficient by European standards, producing about 60% of food needs with less than 1.6% of the labour force (535,000 workers).[219] Around two-thirds of production is devoted to livestock, one-third to arable crops. Farmers are subsidised by the EU's Common Agricultural Policy. The UK retains a significant, though much reduced fishing industry. It is also rich in a number of natural resources including coal, petroleum, natural gas, tin, limestone, iron ore, salt, clay, chalk, gypsum, lead, silica and an abundance of arable land. + +The City of London is the world's largest financial centre alongside New York[200][201][202] +In the final quarter of 2008 the UK economy officially entered recession for the first time since 1991.[220] Unemployment increased from 5.2% in May 2008 to 7.6% in May 2009 and by January 2012 the unemployment rate among 18 to 24-year-olds had risen from 11.9% to 22.5%, the highest since current records began in 1992.[221][222] Total UK government debt rose from 44.4% of GDP in 2007 to 82.9% of GDP in 2011.[223] In February 2013, the UK lost its top AAA credit rating for the first time since 1978.[224] +Inflation-adjusted wages in the UK fell by 3.2% between the third quarter of 2010 and the third quarter of 2012.[225] Since the 1980s, economic inequality has grown faster in the UK than in any other developed country.[226] +The poverty line in the UK is commonly defined as being 60% of the median household income.[nb 10] In 2007–2008 13.5 million people, or 22% of the population, lived below this line. This is a higher level of relative poverty than all but four other EU members.[227] In the same year 4.0 million children, 31% of the total, lived in households below the poverty line after housing costs were taken into account. This is a decrease of 400,000 children since 1998–1999.[228] The UK imports 40% of its food supplies.[229] The Office for National Statistics has estimated that in 2011, 14 million people were at risk of poverty or social exclusion, and that one person in 20 (5.1%) was now experiencing "severe material depression,"[230] up from 3 million people in 1977.[231][232] +Science and technology +Main article: Science and technology in the United Kingdom + +Charles Darwin (1809–82), whose theory of evolution by natural selection is the foundation of modern biological sciences +England and Scotland were leading centres of the Scientific Revolution from the 17th century[233] and the United Kingdom led the Industrial Revolution from the 18th century,[208] and has continued to produce scientists and engineers credited with important advances.[234] Major theorists from the 17th and 18th centuries include Isaac Newton, whose laws of motion and illumination of gravity have been seen as a keystone of modern science;[235] from the 19th century Charles Darwin, whose theory of evolution by natural selection was fundamental to the development of modern biology, and James Clerk Maxwell, who formulated classical electromagnetic theory; and more recently Stephen Hawking, who has advanced major theories in the fields of cosmology, quantum gravity and the investigation of black holes.[236] Major scientific discoveries from the 18th century include hydrogen by Henry Cavendish;[237] from the 20th century penicillin by Alexander Fleming,[238] and the structure of DNA, by Francis Crick and others.[239] Major engineering projects and applications by people from the UK in the 18th century include the steam locomotive, developed by Richard Trevithick and Andrew Vivian;[240] from the 19th century the electric motor by Michael Faraday, the incandescent light bulb by Joseph Swan,[241] and the first practical telephone, patented by Alexander Graham Bell;[242] and in the 20th century the world's first working television system by John Logie Baird and others,[243] the jet engine by Frank Whittle, the basis of the modern computer by Alan Turing, and the World Wide Web by Tim Berners-Lee.[244] +Scientific research and development remains important in British universities, with many establishing science parks to facilitate production and co-operation with industry.[245] Between 2004 and 2008 the UK produced 7% of the world's scientific research papers and had an 8% share of scientific citations, the third and second highest in the world (after the United States and China, and the United States, respectively).[246] Scientific journals produced in the UK include Nature, the British Medical Journal and The Lancet.[247] +Transport +Main article: Transport in the United Kingdom + +Heathrow Terminal 5 building. London Heathrow Airport has the most international passenger traffic of any airport in the world.[248][249] +A radial road network totals 29,145 miles (46,904 km) of main roads, 2,173 miles (3,497 km) of motorways and 213,750 miles (344,000 km) of paved roads.[105] In 2009 there were a total of 34 million licensed vehicles in Great Britain.[250] +The UK has a railway network of 10,072 miles (16,209 km) in Great Britain and 189 miles (304 km) in Northern Ireland. Railways in Northern Ireland are operated by NI Railways, a subsidiary of state-owned Translink. In Great Britain, the British Rail network was privatised between 1994 and 1997. Network Rail owns and manages most of the fixed assets (tracks, signals etc.). About 20 privately owned (and foreign state-owned railways including: Deutsche Bahn; SNCF and Nederlandse Spoorwegen) Train Operating Companies (including state-owned East Coast), operate passenger trains and carry over 18,000 passenger trains daily. There are also some 1,000 freight trains in daily operation.[105] The UK government is to spend £30 billion on a new high-speed railway line, HS2, to be operational by 2025.[251] Crossrail, under construction in London, Is Europe's largest construction project with a £15 billion projected cost.[252][253] +In the year from October 2009 to September 2010 UK airports handled a total of 211.4 million passengers.[254] In that period the three largest airports were London Heathrow Airport (65.6 million passengers), Gatwick Airport (31.5 million passengers) and London Stansted Airport (18.9 million passengers).[254] London Heathrow Airport, located 15 miles (24 km) west of the capital, has the most international passenger traffic of any airport in the world[248][249] and is the hub for the UK flag carrier British Airways, as well as for BMI and Virgin Atlantic.[255] +Energy +Main article: Energy in the United Kingdom + +An oil platform in the North Sea +In 2006, the UK was the world's ninth-largest consumer of energy and the 15th-largest producer.[256] The UK is home to a number of large energy companies, including two of the six oil and gas "supermajors" – BP and Royal Dutch Shell – and BG Group.[257][258] In 2011, 40% of the UK's electricity was produced by gas, 30% by coal, 19% by nuclear power and 4.2% by wind, hydro, biofuels and wastes.[259] +In 2009, the UK produced 1.5 million barrels per day (bbl/d) of oil and consumed 1.7 million bbl/d.[260] Production is now in decline and the UK has been a net importer of oil since 2005.[260] In 2010 the UK had around 3.1 billion barrels of proven crude oil reserves, the largest of any EU member state.[260] In 2009, 66.5% of the UK's oil supply was imported.[261] +In 2009, the UK was the 13th-largest producer of natural gas in the world and the largest producer in the EU.[262] Production is now in decline and the UK has been a net importer of natural gas since 2004.[262] In 2009, half of British gas was supplied from imports and this is expected to increase to at least 75% by 2015, as domestic reserves are depleted.[259] +Coal production played a key role in the UK economy in the 19th and 20th centuries. In the mid-1970s, 130 million tonnes of coal was being produced annually, not falling below 100 million tonnes until the early 1980s. During the 1980s and 1990s the industry was scaled back considerably. In 2011, the UK produced 18.3 million tonnes of coal.[263] In 2005 it had proven recoverable coal reserves of 171 million tons.[263] The UK Coal Authority has stated there is a potential to produce between 7 billion tonnes and 16 billion tonnes of coal through underground coal gasification (UCG) or 'fracking',[264] and that, based on current UK coal consumption, such reserves could last between 200 and 400 years.[265] However, environmental and social concerns have been raised over chemicals getting into the water table and minor earthquakes damaging homes.[266][267] +In the late 1990s, nuclear power plants contributed around 25% of total annual electricity generation in the UK, but this has gradually declined as old plants have been shut down and ageing-related problems affect plant availability. In 2012, the UK had 16 reactors normally generating about 19% of its electricity. All but one of the reactors will be retired by 2023. Unlike Germany and Japan, the UK intends to build a new generation of nuclear plants from about 2018.[259] +Demographics +Main article: Demographics of the United Kingdom + +Map of population density in the UK as at the 2011 census. +A census is taken simultaneously in all parts of the UK every ten years.[268] The Office for National Statistics is responsible for collecting data for England and Wales, the General Register Office for Scotland and the Northern Ireland Statistics and Research Agency each being responsible for censuses in their respective countries.[269] In the 2011 census the total population of the United Kingdom was 63,181,775.[270] It is the third-largest in the European Union, the fifth-largest in the Commonwealth and the 21st-largest in the world. 2010 was the third successive year in which natural change contributed more to population growth than net long-term international migration.[271][271] Between 2001 and 2011 the population increased by an average annual rate of approximately 0.7 per cent.[270] This compares to 0.3 per cent per year in the period 1991 to 2001 and 0.2 per cent in the decade 1981 to 1991.[271] The 2011 census also confirmed that the proportion of the population aged 0–14 has nearly halved (31 per cent in 1911 compared to 18 in 2011) and the proportion of older people aged 65 and over has more than trebled (from 5 to 16 per cent).[270] It has been estimated that the number of people aged 100 or over will rise steeply to reach over 626,000 by 2080.[272] +England's population in 2011 was found to be 53 million.[273] It is one of the most densely populated countries in the world, with 383 people resident per square kilometre in mid-2003,[274] with a particular concentration in London and the south-east.[275] The 2011 census put Scotland's population at 5.3 million,[276] Wales at 3.06 million and Northern Ireland at 1.81 million.[273] In percentage terms England has had the fastest growing population of any country of the UK in the period from 2001 to 2011, with an increase of 7.9%. +In 2012 the average total fertility rate (TFR) across the UK was 1.92 children per woman.[277] While a rising birth rate is contributing to current population growth, it remains considerably below the 'baby boom' peak of 2.95 children per woman in 1964,[278] below the replacement rate of 2.1, but higher than the 2001 record low of 1.63.[277] In 2012, Scotland had the lowest TFR at only 1.67, followed by Wales at 1.88, England at 1.94, and Northern Ireland at 2.03.[277] In 2011, 47.3% of births in the UK were to unmarried women.[279] A government figure estimated that there are 3.6 million homosexual people in Britain comprising 6 per cent of the population.[280] +view talk edit +view talk edit +Largest urban areas of the United Kingdom +United Kingdom 2011 census Built-up areas[281][282][283] +Rank Urban area Pop. Principal settlement Rank Urban area Pop. Principal settlement +Greater London Urban Area +Greater London Urban Area +Greater Manchester Urban Area +Greater Manchester Urban Area +1 Greater London Urban Area 9,787,426 London 11 Bristol Urban Area 617,280 Bristol West Midlands Urban Area +West Midlands Urban Area +West Yorkshire Urban Area +West Yorkshire Urban Area +2 Greater Manchester Urban Area 2,553,379 Manchester 12 Belfast Metropolitan Urban Area 579,236 Belfast +3 West Midlands Urban Area 2,440,986 Birmingham 13 Leicester Urban Area 508,916 Leicester +4 West Yorkshire Urban Area 1,777,934 Leeds 14 Edinburgh 488,610 Edinburgh +5 Greater Glasgow 976,970 Glasgow 15 Brighton/Worthing/Littlehampton 474,485 Brighton +6 Liverpool Urban Area 864,122 Liverpool 16 South East Dorset conurbation 466,266 Bournemouth +7 South Hampshire 855,569 Southampton 17 Cardiff Urban Area 390,214 Cardiff +8 Tyneside 774,891 Newcastle 18 Teesside 376,633 Middlesbrough +9 Nottingham Urban Area 729,977 Nottingham 19 The Potteries Urban Area 372,775 Stoke-on-Trent +10 Sheffield Urban Area 685,368 Sheffield 20 Coventry and Bedworth Urban Area 359,262 Coventry + +Ethnic groups + +Map showing the percentage of the population who are not white according to the 2011 census. +Ethnic group 2011 +population 2011 +% +White 55,010,359 87.1 +White: Irish Traveller 63,193 0.1 +Asian or Asian British: Indian 1,451,862 +2.3 +Asian or Asian British: Pakistani 1,173,892 +1.9 +Asian or Asian British: Bangladeshi 451,529 +0.7 +Asian or Asian British: Chinese 433,150 +0.7 +Asian or Asian British: Asian Other 861,815 +1.4 +Asian or Asian British: Total 4,373,339 +7.0 +Black or Black British 1,904,684 +3.0 +British Mixed 1,250,229 +2.0 +Other: Total 580,374 +0.9 +Total[284] 63,182,178 +100 +Historically, indigenous British people were thought to be descended from the various ethnic groups that settled there before the 11th century: the Celts, Romans, Anglo-Saxons, Norse and the Normans. Welsh people could be the oldest ethnic group in the UK.[285] A 2006 genetic study shows that more than 50 per cent of England's gene pool contains Germanic Y chromosomes.[286] Another 2005 genetic analysis indicates that "about 75 per cent of the traceable ancestors of the modern British population had arrived in the British isles by about 6,200 years ago, at the start of the British Neolithic or Stone Age", and that the British broadly share a common ancestry with the Basque people.[287][288][289] +The UK has a history of small-scale non-white immigration, with Liverpool having the oldest Black population in the country dating back to at least the 1730s during the period of the African slave trade,[290] and the oldest Chinese community in Europe, dating to the arrival of Chinese seamen in the 19th century.[291] In 1950 there were probably fewer than 20,000 non-white residents in Britain, almost all born overseas.[292] +Since 1948 substantial immigration from Africa, the Caribbean and South Asia has been a legacy of ties forged by the British Empire. Migration from new EU member states in Central and Eastern Europe since 2004 has resulted in growth in these population groups but, as of 2008, the trend is reversing. Many of these migrants are returning to their home countries, leaving the size of these groups unknown.[293] In 2011, 86% of the population identified themselves as White, meaning 12.9% of the UK population identify themselves as of mixed ethnic minority. +Ethnic diversity varies significantly across the UK. 30.4% of London's population and 37.4% of Leicester's was estimated to be non-white in 2005,[294][295] whereas less than 5% of the populations of North East England, Wales and the South West were from ethnic minorities, according to the 2001 census.[296] In 2011, 26.5% of primary and 22.2% of secondary pupils at state schools in England were members of an ethnic minority.[297] +The non-white British population of England and Wales increased by 38% from 6.6 million in 2001 to 9.1 million in 2009.[298] The fastest-growing group was the mixed-ethnicity population, which doubled from 672,000 in 2001 to 986,600 in 2009. Also in the same period, a decrease of 36,000 white British people was recorded.[299] +Languages +Main article: Languages of the United Kingdom + +The English-speaking world. Countries in dark blue have a majority of native speakers; countries where English is an official but not a majority language are shaded in light blue. English is one of the official languages of the European Union[300] and the United Nations[301] +The UK's de facto official language is English.[302][303] It is estimated that 95% of the UK's population are monolingual English speakers.[304] 5.5% of the population are estimated to speak languages brought to the UK as a result of relatively recent immigration.[304] South Asian languages, including Bengali, Tamil, Punjabi, Hindi and Gujarati, are the largest grouping and are spoken by 2.7% of the UK population.[304] According to the 2011 census, Polish has become the second-largest language spoken in England and has 546,000 speakers.[305] +Four Celtic languages are spoken in the UK: Welsh; Irish; Scottish Gaelic; and Cornish. All are recognised as regional or minority languages, subject to specific measures of protection and promotion under the European Charter for Regional or Minority Languages[2][306] and the Framework Convention for the Protection of National Minorities.[307] In the 2001 Census over a fifth (21%) of the population of Wales said they could speak Welsh,[308] an increase from the 1991 Census (18%).[309] In addition it is estimated that about 200,000 Welsh speakers live in England.[310] In the same census in Northern Ireland 167,487 people (10.4%) stated that they had "some knowledge of Irish" (see Irish language in Northern Ireland), almost exclusively in the nationalist (mainly Catholic) population. Over 92,000 people in Scotland (just under 2% of the population) had some Gaelic language ability, including 72% of those living in the Outer Hebrides.[311] The number of schoolchildren being taught through Welsh, Scottish Gaelic and Irish is increasing.[312] Among emigrant-descended populations some Scottish Gaelic is still spoken in Canada (principally Nova Scotia and Cape Breton Island),[313] and Welsh in Patagonia, Argentina.[314] +Scots, a language descended from early northern Middle English, has limited recognition alongside its regional variant, Ulster Scots in Northern Ireland, without specific commitments to protection and promotion.[2][315] +It is compulsory for pupils to study a second language up to the age of 14 in England,[316] and up to age 16 in Scotland. French and German are the two most commonly taught second languages in England and Scotland. All pupils in Wales are taught Welsh as a second language up to age 16, or are taught in Welsh.[317] +Religion +Main article: Religion in the United Kingdom + +Westminster Abbey is used for the coronation of British monarchs +Forms of Christianity have dominated religious life in what is now the United Kingdom for over 1,400 years.[318] Although a majority of citizens still identify with Christianity in many surveys, regular church attendance has fallen dramatically since the middle of the 20th century,[319] while immigration and demographic change have contributed to the growth of other faiths, most notably Islam.[320] This has led some commentators to variously describe the UK as a multi-faith,[321] secularised,[322] or post-Christian society.[323] +In the 2001 census 71.6% of all respondents indicated that they were Christians, with the next largest faiths (by number of adherents) being Islam (2.8%), Hinduism (1.0%), Sikhism (0.6%), Judaism (0.5%), Buddhism (0.3%) and all other religions (0.3%).[324] 15% of respondents stated that they had no religion, with a further 7% not stating a religious preference.[325] A Tearfund survey in 2007 showed only one in ten Britons actually attend church weekly.[326] Between the 2001 and 2011 census there was a decrease in the amount of people who identified as Christian by 12%, whilst the percentage of those reporting no religious affiliation doubled. This contrasted with growth in the other main religious group categories, with the number of Muslims increasing by the most substantial margin to a total of about 5%.[327] +The Church of England is the established church in England.[328] It retains a representation in the UK Parliament and the British monarch is its Supreme Governor.[329] In Scotland the Presbyterian Church of Scotland is recognised as the national church. It is not subject to state control, and the British monarch is an ordinary member, required to swear an oath to "maintain and preserve the Protestant Religion and Presbyterian Church Government" upon his or her accession.[330][331] The (Anglican) Church in Wales was disestablished in 1920 and, as the (Anglican) Church of Ireland was disestablished in 1870 before the partition of Ireland, there is no established church in Northern Ireland.[332] Although there are no UK-wide data in the 2001 census on adherence to individual Christian denominations, it has been estimated that 62% of Christians are Anglican, 13.5% Catholic, 6% Presbyterian, 3.4% Methodist with small numbers of other Protestant denominations such as Open Brethren, and Orthodox churches.[333] +Migration +Main article: Immigration to the United Kingdom since 1922 +See also: Foreign-born population of the United Kingdom + +Estimated foreign-born population by country of birth, April 2007 – March 2008 +The United Kingdom has experienced successive waves of migration. The Great Famine in Ireland, then part of the United Kingdom, resulted in perhaps a million people migrating to Great Brtain.[334] Unable to return to Poland at the end of World War II, over 120,000 Polish veterans remained in the UK permanently.[335] After World War II, there was significant immigration from the colonies and newly independent former colonies, partly as a legacy of empire and partly driven by labour shortages. Many of these migrants came from the Caribbean and the Indian subcontinent.[336] The British Asian population has increased from 2.2 million in 2001 to over 4.2 million in 2011.[337] +One of the more recent trends in migration has been the arrival of workers from the new EU member states in Eastern Europe. In 2010, there were 7.0 million foreign-born residents in the UK, corresponding to 11.3% of the total population. Of these, 4.76 million (7.7%) were born outside the EU and 2.24 million (3.6%) were born in another EU Member State.[338] The proportion of foreign-born people in the UK remains slightly below that of many other European countries.[339] However, immigration is now contributing to a rising population[340] with arrivals and UK-born children of migrants accounting for about half of the population increase between 1991 and 2001. Analysis of Office for National Statistics (ONS) data shows that a net total of 2.3 million migrants moved to the UK in the 15 years from 1991 to 2006.[341][342] In 2008 it was predicted that migration would add 7 million to the UK population by 2031,[343] though these figures are disputed.[344] The ONS reported that net migration rose from 2009 to 2010 by 21 per cent to 239,000.[345] In 2011 the net increase was 251,000: immigration was 589,000, while the number of people emigrating (for more than 12 months) was 338,000.[346][347] +195,046 foreign nationals became British citizens in 2010,[348] compared to 54,902 in 1999.[348][349] A record 241,192 people were granted permanent settlement rights in 2010, of whom 51 per cent were from Asia and 27 per cent from Africa.[350] 25.5 per cent of babies born in England and Wales in 2011 were born to mothers born outside the UK, according to official statistics released in 2012.[351] +Citizens of the European Union, including those of the UK, have the right to live and work in any EU member state.[352] The UK applied temporary restrictions to citizens of Romania and Bulgaria, which joined the EU in January 2007.[353] Research conducted by the Migration Policy Institute for the Equality and Human Rights Commission suggests that, between May 2004 and September 2009, 1.5 million workers migrated from the new EU member states to the UK, two-thirds of them Polish, but that many subsequently returned home, resulting in a net increase in the number of nationals of the new member states in the UK of some 700,000 over that period.[354][355] The late-2000s recession in the UK reduced the economic incentive for Poles to migrate to the UK,[356] the migration becoming temporary and circular.[357] In 2009, for the first time since enlargement, more nationals of the eight central and eastern European states that had joined the EU in 2004 left the UK than arrived.[358] In 2011, citizens of the new EU member states made up 13% of the immigrants entering the country.[346] + +Estimated number of British citizens living overseas by country, 2006 +The UK government has introduced a points-based immigration system for immigration from outside the European Economic Area to replace former schemes, including the Scottish Government's Fresh Talent Initiative.[359] In June 2010 the UK government introduced a temporary limit of 24,000 on immigration from outside the EU, aiming to discourage applications before a permanent cap was imposed in April 2011.[360] The cap has caused tension within the coalition: business secretary Vince Cable has argued that it is harming British businesses.[361] +Emigration was an important feature of British society in the 19th century. Between 1815 and 1930 around 11.4 million people emigrated from Britain and 7.3 million from Ireland. Estimates show that by the end of the 20th century some 300 million people of British and Irish descent were permanently settled around the globe.[362] Today, at least 5.5 million UK-born people live abroad,[363][364][365] mainly in Australia, Spain, the United States and Canada.[363][366] +Education +Main article: Education in the United Kingdom +See also: Education in England, Education in Northern Ireland, Education in Scotland and Education in Wales + +King's College, part of the University of Cambridge, which was founded in 1209 +Education in the United Kingdom is a devolved matter, with each country having a separate education system. +Whilst education in England is the responsibility of the Secretary of State for Education, the day-to-day administration and funding of state schools is the responsibility of local authorities.[367] Universally free of charge state education was introduced piecemeal between 1870 and 1944.[368][369] Education is now mandatory from ages five to sixteen (15 if born in late July or August). In 2011, the Trends in International Mathematics and Science Study (TIMSS) rated 13–14-year-old pupils in England and Wales 10th in the world for maths and 9th for science.[370] The majority of children are educated in state-sector schools, a small proportion of which select on the grounds of academic ability. Two of the top ten performing schools in terms of GCSE results in 2006 were state-run grammar schools. Over half of students at the leading universities of Cambridge and Oxford had attended state schools.[371] Despite a fall in actual numbers the proportion of children in England attending private schools has risen to over 7%.[372] In 2010, more than 45% of places at the University of Oxford and 40% at the University of Cambridge were taken by students from private schools, even though they educate just 7% of the population.[373] England has the two oldest universities in English-speaking world, Universities of Oxford and Cambridge (jointly known as "Oxbridge") with history of over eight centuries. The United Kingdom has 9 universities featured in the Times Higher Education top 100 rankings, making it second to the United States in terms of representation.[374] + +Queen's University Belfast, built in 1849[375] +Education in Scotland is the responsibility of the Cabinet Secretary for Education and Lifelong Learning, with day-to-day administration and funding of state schools the responsibility of Local Authorities. Two non-departmental public bodies have key roles in Scottish education. The Scottish Qualifications Authority is responsible for the development, accreditation, assessment and certification of qualifications other than degrees which are delivered at secondary schools, post-secondary colleges of further education and other centres.[376] The Learning and Teaching Scotland provides advice, resources and staff development to education professionals.[377] Scotland first legislated for compulsory education in 1496.[378] The proportion of children in Scotland attending private schools is just over 4%, and it has been rising slowly in recent years.[379] Scottish students who attend Scottish universities pay neither tuition fees nor graduate endowment charges, as fees were abolished in 2001 and the graduate endowment scheme was abolished in 2008.[380] +The Welsh Government has responsibility for education in Wales. A significant number of Welsh students are taught either wholly or largely in the Welsh language; lessons in Welsh are compulsory for all until the age of 16.[381] There are plans to increase the provision of Welsh-medium schools as part of the policy of creating a fully bilingual Wales. +Education in Northern Ireland is the responsibility of the Minister of Education and the Minister for Employment and Learning, although responsibility at a local level is administered by five education and library boards covering different geographical areas. The Council for the Curriculum, Examinations & Assessment (CCEA) is the body responsible for advising the government on what should be taught in Northern Ireland's schools, monitoring standards and awarding qualifications.[382] +A government commission's report in 2014 found that privately educated people comprise 7% of the general population of the UK but much larger percentages of the top professions, the most extreme case quoted being 71% of senior judges.[383][384] +Healthcare +Main article: Healthcare in the United Kingdom + +The Royal Aberdeen Children's Hospital, an NHS Scotland specialist children's hospital +Healthcare in the United Kingdom is a devolved matter and each country has its own system of private and publicly funded health care, together with alternative, holistic and complementary treatments. Public healthcare is provided to all UK permanent residents and is mostly free at the point of need, being paid for from general taxation. The World Health Organization, in 2000, ranked the provision of healthcare in the United Kingdom as fifteenth best in Europe and eighteenth in the world.[385][386] +Regulatory bodies are organised on a UK-wide basis such as the General Medical Council, the Nursing and Midwifery Council and non-governmental-based, such as the Royal Colleges. However, political and operational responsibility for healthcare lies with four national executives; healthcare in England is the responsibility of the UK Government; healthcare in Northern Ireland is the responsibility of the Northern Ireland Executive; healthcare in Scotland is the responsibility of the Scottish Government; and healthcare in Wales is the responsibility of the Welsh Assembly Government. Each National Health Service has different policies and priorities, resulting in contrasts.[387][388] +Since 1979 expenditure on healthcare has been increased significantly to bring it closer to the European Union average.[389] The UK spends around 8.4 per cent of its gross domestic product on healthcare, which is 0.5 percentage points below the Organisation for Economic Co-operation and Development average and about one percentage point below the average of the European Union.[390] +Culture +Main article: Culture of the United Kingdom +The culture of the United Kingdom has been influenced by many factors including: the nation's island status; its history as a western liberal democracy and a major power; as well as being a political union of four countries with each preserving elements of distinctive traditions, customs and symbolism. As a result of the British Empire, British influence can be observed in the language, culture and legal systems of many of its former colonies including Australia, Canada, India, Ireland, New Zealand, South Africa and the United States. The substantial cultural influence of the United Kingdom has led it to be described as a "cultural superpower."[391][392] +Literature +Main article: British literature + +The Chandos portrait, believed to depict William Shakespeare +'British literature' refers to literature associated with the United Kingdom, the Isle of Man and the Channel Islands. Most British literature is in the English language. In 2005, some 206,000 books were published in the United Kingdom and in 2006 it was the largest publisher of books in the world.[393] +The English playwright and poet William Shakespeare is widely regarded as the greatest dramatist of all time,[394][395][396] and his contemporaries Christopher Marlowe and Ben Jonson have also been held in continuous high esteem. More recently the playwrights Alan Ayckbourn, Harold Pinter, Michael Frayn, Tom Stoppard and David Edgar have combined elements of surrealism, realism and radicalism. +Notable pre-modern and early-modern English writers include Geoffrey Chaucer (14th century), Thomas Malory (15th century), Sir Thomas More (16th century), John Bunyan (17th century) and John Milton (17th century). In the 18th century Daniel Defoe (author of Robinson Crusoe) and Samuel Richardson were pioneers of the modern novel. In the 19th century there followed further innovation by Jane Austen, the gothic novelist Mary Shelley, the children's writer Lewis Carroll, the Brontë sisters, the social campaigner Charles Dickens, the naturalist Thomas Hardy, the realist George Eliot, the visionary poet William Blake and romantic poet William Wordsworth. 20th-century English writers include the science-fiction novelist H. G. Wells; the writers of children's classics Rudyard Kipling, A. A. Milne (the creator of Winnie-the-Pooh), Roald Dahl and Enid Blyton; the controversial D. H. Lawrence; the modernist Virginia Woolf; the satirist Evelyn Waugh; the prophetic novelist George Orwell; the popular novelists W. Somerset Maugham and Graham Greene; the crime writer Agatha Christie (the best-selling novelist of all time);[397] Ian Fleming (the creator of James Bond); the poets T.S. Eliot, Philip Larkin and Ted Hughes; the fantasy writers J. R. R. Tolkien, C. S. Lewis and J. K. Rowling; the graphic novelist Alan Moore, whose novel Watchmen is often cited by critics as comic's greatest series and graphic novel[398] and one of the best-selling graphic novels ever published.[399] + +A photograph of Victorian era novelist Charles Dickens +Scotland's contributions include the detective writer Arthur Conan Doyle (the creator of Sherlock Holmes), romantic literature by Sir Walter Scott, the children's writer J. M. Barrie, the epic adventures of Robert Louis Stevenson and the celebrated poet Robert Burns. More recently the modernist and nationalist Hugh MacDiarmid and Neil M. Gunn contributed to the Scottish Renaissance. A more grim outlook is found in Ian Rankin's stories and the psychological horror-comedy of Iain Banks. Scotland's capital, Edinburgh, was UNESCO's first worldwide City of Literature.[400] +Britain's oldest known poem, Y Gododdin, was composed in Yr Hen Ogledd (The Old North), most likely in the late 6th century. It was written in Cumbric or Old Welsh and contains the earliest known reference to King Arthur.[401] From around the seventh century, the connection between Wales and the Old North was lost, and the focus of Welsh-language culture shifted to Wales, where Arthurian legend was further developed by Geoffrey of Monmouth.[402] Wales's most celebrated medieval poet, Dafydd ap Gwilym (fl.1320–1370), composed poetry on themes including nature, religion and especially love. He is widely regarded as one of the greatest European poets of his age.[403] Until the late 19th century the majority of Welsh literature was in Welsh and much of the prose was religious in character. Daniel Owen is credited as the first Welsh-language novelist, publishing Rhys Lewis in 1885. The best-known of the Anglo-Welsh poets are both Thomases. Dylan Thomas became famous on both sides of the Atlantic in the mid-20th century. He is remembered for his poetry – his "Do not go gentle into that good night; Rage, rage against the dying of the light." is one of the most quoted couplets of English language verse – and for his 'play for voices', Under Milk Wood. The influential Church in Wales 'poet-priest' and Welsh nationalist R. S. Thomas was nominated for the Nobel Prize in Literature in 1996. Leading Welsh novelists of the twentieth century include Richard Llewellyn and Kate Roberts.[404][405] +Authors of other nationalities, particularly from Commonwealth countries, the Republic of Ireland and the United States, have lived and worked in the UK. Significant examples through the centuries include Jonathan Swift, Oscar Wilde, Bram Stoker, George Bernard Shaw, Joseph Conrad, T.S. Eliot, Ezra Pound and more recently British authors born abroad such as Kazuo Ishiguro and Sir Salman Rushdie.[406][407] +Music +Main article: Music of the United Kingdom +See also: British rock + +The Beatles are the most commercially successful and critically acclaimed band in the history of music, selling over a billion records internationally.[408][409][410] +Various styles of music are popular in the UK from the indigenous folk music of England, Wales, Scotland and Northern Ireland to heavy metal. Notable composers of classical music from the United Kingdom and the countries that preceded it include William Byrd, Henry Purcell, Sir Edward Elgar, Gustav Holst, Sir Arthur Sullivan (most famous for working with the librettist Sir W. S. Gilbert), Ralph Vaughan Williams and Benjamin Britten, pioneer of modern British opera. Sir Peter Maxwell Davies is one of the foremost living composers and current Master of the Queen's Music. The UK is also home to world-renowned symphonic orchestras and choruses such as the BBC Symphony Orchestra and the London Symphony Chorus. Notable conductors include Sir Simon Rattle, John Barbirolli and Sir Malcolm Sargent. Some of the notable film score composers include John Barry, Clint Mansell, Mike Oldfield, John Powell, Craig Armstrong, David Arnold, John Murphy, Monty Norman and Harry Gregson-Williams. George Frideric Handel, although born German, was a naturalised British citizen[411] and some of his best works, such as Messiah, were written in the English language.[412] Andrew Lloyd Webber has achieved enormous worldwide commercial success and is a prolific composer of musical theatre, works which have dominated London's West End for a number of years and have travelled to Broadway in New York.[413] +The Beatles have international sales of over one billion units and are the biggest-selling and most influential band in the history of popular music.[408][409][410][414] Other prominent British contributors to have influenced popular music over the last 50 years include; The Rolling Stones, Led Zeppelin, Pink Floyd, Queen, the Bee Gees, and Elton John, all of whom have world wide record sales of 200 million or more.[415][416][417][418][419][420] The Brit Awards are the BPI's annual music awards, and some of the British recipients of the Outstanding Contribution to Music award include; The Who, David Bowie, Eric Clapton, Rod Stewart and The Police.[421] More recent UK music acts that have had international success include Coldplay, Radiohead, Oasis, Spice Girls, Robbie Williams, Amy Winehouse and Adele.[422] +A number of UK cities are known for their music. Acts from Liverpool have had more UK chart number one hit singles per capita (54) than any other city worldwide.[423] Glasgow's contribution to music was recognised in 2008 when it was named a UNESCO City of Music, one of only three cities in the world to have this honour.[424] +Visual art +Main article: Art of the United Kingdom + +J. M. W. Turner self-portrait, oil on canvas, c. 1799 +The history of British visual art forms part of western art history. Major British artists include: the Romantics William Blake, John Constable, Samuel Palmer and J.M.W. Turner; the portrait painters Sir Joshua Reynolds and Lucian Freud; the landscape artists Thomas Gainsborough and L. S. Lowry; the pioneer of the Arts and Crafts Movement William Morris; the figurative painter Francis Bacon; the Pop artists Peter Blake, Richard Hamilton and David Hockney; the collaborative duo Gilbert and George; the abstract artist Howard Hodgkin; and the sculptors Antony Gormley, Anish Kapoor and Henry Moore. During the late 1980s and 1990s the Saatchi Gallery in London helped to bring to public attention a group of multi-genre artists who would become known as the "Young British Artists": Damien Hirst, Chris Ofili, Rachel Whiteread, Tracey Emin, Mark Wallinger, Steve McQueen, Sam Taylor-Wood and the Chapman Brothers are among the better-known members of this loosely affiliated movement. +The Royal Academy in London is a key organisation for the promotion of the visual arts in the United Kingdom. Major schools of art in the UK include: the six-school University of the Arts London, which includes the Central Saint Martins College of Art and Design and Chelsea College of Art and Design; Goldsmiths, University of London; the Slade School of Fine Art (part of University College London); the Glasgow School of Art; the Royal College of Art; and The Ruskin School of Drawing and Fine Art (part of the University of Oxford). The Courtauld Institute of Art is a leading centre for the teaching of the history of art. Important art galleries in the United Kingdom include the National Gallery, National Portrait Gallery, Tate Britain and Tate Modern (the most-visited modern art gallery in the world, with around 4.7 million visitors per year).[425] +Cinema +Main article: Cinema of the United Kingdom + +Film director Alfred Hitchcock +The United Kingdom has had a considerable influence on the history of the cinema. The British directors Alfred Hitchcock, whose film Vertigo is considered by some critics as the best film of all time,[426] and David Lean are among the most critically acclaimed of all-time.[427] Other important directors including Charlie Chaplin,[428] Michael Powell,[429] Carol Reed[430] and Ridley Scott.[431] Many British actors have achieved international fame and critical success, including: Julie Andrews,[432] Richard Burton,[433] Michael Caine,[434] Charlie Chaplin,[435] Sean Connery,[436] Vivien Leigh,[437] David Niven,[438] Laurence Olivier,[439] Peter Sellers,[440] Kate Winslet,[441] and Daniel Day-Lewis, the only person to win an Oscar in the best actor category three times.[442] Some of the most commercially successful films of all time have been produced in the United Kingdom, including the two highest-grossing film franchises (Harry Potter and James Bond).[443] Ealing Studios has a claim to being the oldest continuously working film studio in the world.[444] +Despite a history of important and successful productions, the industry has often been characterised by a debate about its identity and the level of American and European influence. British producers are active in international co-productions and British actors, directors and crew feature regularly in American films. Many successful Hollywood films have been based on British people, stories or events, including Titanic, The Lord of the Rings, Pirates of the Caribbean. +In 2009, British films grossed around $2 billion worldwide and achieved a market share of around 7% globally and 17% in the United Kingdom.[445] UK box-office takings totalled £944 million in 2009, with around 173 million admissions.[445] The British Film Institute has produced a poll ranking of what it considers to be the 100 greatest British films of all time, the BFI Top 100 British films.[446] The annual British Academy Film Awards, hosted by the British Academy of Film and Television Arts, are the British equivalent of the Oscars.[447] +Media +Main article: Media of the United Kingdom + +Broadcasting House in London, headquarters of the BBC, the oldest and largest broadcaster in the world.[448][449][450] +The BBC, founded in 1922, is the UK's publicly funded radio, television and Internet broadcasting corporation, and is the oldest and largest broadcaster in the world.[448][449][450] It operates numerous television and radio stations in the UK and abroad and its domestic services are funded by the television licence.[451][452] Other major players in the UK media include ITV plc, which operates 11 of the 15 regional television broadcasters that make up the ITV Network,[453] and News Corporation, which owns a number of national newspapers through News International such as the most popular tabloid The Sun and the longest-established daily "broadsheet" The Times,[454] as well as holding a large stake in satellite broadcaster British Sky Broadcasting.[455] London dominates the media sector in the UK: national newspapers and television and radio are largely based there, although Manchester is also a significant national media centre. Edinburgh and Glasgow, and Cardiff, are important centres of newspaper and broadcasting production in Scotland and Wales respectively.[456] The UK publishing sector, including books, directories and databases, journals, magazines and business media, newspapers and news agencies, has a combined turnover of around £20 billion and employs around 167,000 people.[457] +In 2009, it was estimated that individuals viewed a mean of 3.75 hours of television per day and 2.81 hours of radio. In that year the main BBC public service broadcasting channels accounted for an estimated 28.4% of all television viewing; the three main independent channels accounted for 29.5% and the increasingly important other satellite and digital channels for the remaining 42.1%.[458] Sales of newspapers have fallen since the 1970s and in 2009 42% of people reported reading a daily national newspaper.[459] In 2010 82.5% of the UK population were Internet users, the highest proportion amongst the 20 countries with the largest total number of users in that year.[460] +Philosophy +Main article: British philosophy +The United Kingdom is famous for the tradition of 'British Empiricism', a branch of the philosophy of knowledge that states that only knowledge verified by experience is valid, and 'Scottish Philosophy', sometimes referred to as the 'Scottish School of Common Sense'.[461] The most famous philosophers of British Empiricism are John Locke, George Berkeley and David Hume; while Dugald Stewart, Thomas Reid and William Hamilton were major exponents of the Scottish "common sense" school. Two Britons are also notable for a theory of moral philosophy utilitarianism, first used by Jeremy Bentham and later by John Stuart Mill in his short work Utilitarianism.[462][463] Other eminent philosophers from the UK and the unions and countries that preceded it include Duns Scotus, John Lilburne, Mary Wollstonecraft, Sir Francis Bacon, Adam Smith, Thomas Hobbes, William of Ockham, Bertrand Russell and A.J. "Freddie" Ayer. Foreign-born philosophers who settled in the UK include Isaiah Berlin, Karl Marx, Karl Popper and Ludwig Wittgenstein. +Sport +Main article: Sport in the United Kingdom + +Wembley Stadium, London, home of the England national football team, is one of the most expensive stadia ever built.[464] +Major sports, including association football, tennis, rugby union, rugby league, golf, boxing, rowing and cricket, originated or were substantially developed in the UK and the states that preceded it. With the rules and codes of many modern sports invented and codified in late 19th-century Victorian Britain, in 2012, the President of the IOC, Jacques Rogge, stated; "This great, sports-loving country is widely recognized as the birthplace of modern sport. It was here that the concepts of sportsmanship and fair play were first codified into clear rules and regulations. It was here that sport was included as an educational tool in the school curriculum".[465][466] +In most international competitions, separate teams represent England, Scotland and Wales. Northern Ireland and the Republic of Ireland usually field a single team representing all of Ireland, with notable exceptions being association football and the Commonwealth Games. In sporting contexts, the English, Scottish, Welsh and Irish / Northern Irish teams are often referred to collectively as the Home Nations. There are some sports in which a single team represents the whole of United Kingdom, including the Olympics, where the UK is represented by the Great Britain team. The 1908, 1948 and 2012 Summer Olympics were held in London, making it the first city to host the games three times. Britain has participated in every modern Olympic Games to date and is third in the medal count. +A 2003 poll found that football is the most popular sport in the United Kingdom.[467] Each of the Home Nations has its own football association, national team and league system. The English top division, the Premier League, is the most watched football league in the world.[468] The first-ever international football match was contested by England and Scotland on 30 November 1872.[469] England, Scotland, Wales and Northern Ireland compete as separate countries in international competitions.[470] A Great Britain Olympic football team was assembled for the first time to compete in the London 2012 Olympic Games. However, the Scottish, Welsh and Northern Irish football associations declined to participate, fearing that it would undermine their independent status – a fear confirmed by FIFA president Sepp Blatter.[471] + +The Millennium Stadium, Cardiff, opened for the 1999 Rugby World Cup. +Cricket was invented in England. The England cricket team, controlled by the England and Wales Cricket Board,[472] is the only national team in the UK with Test status. Team members are drawn from the main county sides, and include both English and Welsh players. Cricket is distinct from football and rugby where Wales and England field separate national teams, although Wales had fielded its own team in the past. Irish and Scottish players have played for England because neither Scotland nor Ireland have Test status and have only recently started to play in One Day Internationals.[473][474] Scotland, England (and Wales), and Ireland (including Northern Ireland) have competed at the Cricket World Cup, with England reaching the finals on three occasions. There is a professional league championship in which clubs representing 17 English counties and 1 Welsh county compete.[475] +Rugby league is a popular sport in some regions of the UK. It originated in Huddersfield and is generally played in Northern England.[476] A single 'Great Britain Lions' team had competed in the Rugby League World Cup and Test match games, but this changed in 2008 when England, Scotland and Ireland competed as separate nations.[477] Great Britain is still being retained as the full national team for Ashes tours against Australia, New Zealand and France. Super League is the highest level of professional rugby league in the UK and Europe. It consists of 11 teams from Northern England, 1 from London, 1 from Wales and 1 from France. +In rugby union, England, Scotland, Wales, Ireland, France and Italy compete in the Six Nations Championship; the premier international tournament in the northern hemisphere. Sport governing bodies in England, Scotland, Wales and Ireland organise and regulate the game separately.[478] If any of the British teams or the Irish team beat the other three in a tournament, then it is awarded the Triple Crown.[479] + +The Wimbledon Championships, a Grand Slam tennis tournament, is held in Wimbledon, London every June or July. +Thoroughbred racing, which originated under Charles II of England as the "sport of kings", is popular throughout the UK with world-famous races including the Grand National, the Epsom Derby, Royal Ascot and the Cheltenham National Hunt Festival (including the Cheltenham Gold Cup). The UK has proved successful in the international sporting arena in rowing. +The UK is closely associated with motorsport. Many teams and drivers in Formula One (F1) are based in the UK, and the country has won more drivers' and constructors' titles than any other. The UK hosted the very first F1 Grand Prix in 1950 at Silverstone, the current location of the British Grand Prix held each year in July. The country also hosts legs of the Grand Prix motorcycle racing, World Rally Championship and FIA World Endurance Championship. The premier national auto racing event is the British Touring Car Championship (BTCC). Motorcycle road racing has a long tradition with races such as the Isle of Man TT and the North West 200. +Golf is the sixth-most popular sport, by participation, in the UK. Although The Royal and Ancient Golf Club of St Andrews in Scotland is the sport's home course,[480] the world's oldest golf course is actually Musselburgh Links' Old Golf Course.[481] +Snooker is one of the UK's popular sporting exports, with the world championships held annually in Sheffield.[482] The modern game of lawn tennis first originated in the city of Birmingham between 1859 and 1865.[483] The Championships, Wimbledon are international tennis events held in Wimbledon in south London every summer and are regarded as the most prestigious event of the global tennis calendar. In Northern Ireland Gaelic football and hurling are popular team sports, both in terms of participation and spectating, and Irish expatriates in the UK and the US also play them.[484] Shinty (or camanachd) is popular in the Scottish Highlands.[485] +Symbols +Main article: Symbols of the United Kingdom, the Channel Islands and the Isle of Man + +The Statue of Britannia in Plymouth. Britannia is a national personification of the UK. +The flag of the United Kingdom is the Union Flag (also referred to as the Union Jack). It was created in 1606 by the superimposition of the Flag of England on the Flag of Scotland and updated in 1801 with the addition of Saint Patrick's Flag. Wales is not represented in the Union Flag, as Wales had been conquered and annexed to England prior to the formation of the United Kingdom. The possibility of redesigning the Union Flag to include representation of Wales has not been completely ruled out.[486] The national anthem of the United Kingdom is "God Save the King", with "King" replaced with "Queen" in the lyrics whenever the monarch is a woman. +Britannia is a national personification of the United Kingdom, originating from Roman Britain.[487] Britannia is symbolised as a young woman with brown or golden hair, wearing a Corinthian helmet and white robes. She holds Poseidon's three-pronged trident and a shield, bearing the Union Flag. Sometimes she is depicted as riding on the back of a lion. Since the height of the British Empire in the late 19th century, Britannia has often been associated with British maritime dominance, as in the patriotic song "Rule, Britannia!". Up until 2008, the lion symbol was depicted behind Britannia on the British fifty pence coin and on the back of the British ten pence coin. It is also used as a symbol on the non-ceremonial flag of the British Army. The bulldog is sometimes used as a symbol of the United Kingdom and has been associated with Winston Churchill's defiance of Nazi Germany.[488] +See also +Outline of the United Kingdom + United Kingdom – Wikipedia book +Walking in the United Kingdom +Flag of the United Kingdom.svgUnited Kingdom portal Flag of Europe.svgEuropean Union portal Europe green light.pngEurope portal +Notes +Jump up ^ The Royal coat of arms used in Scotland: + Royal Coat of Arms of the United Kingdom (Scotland).svg +Jump up ^ There is no authorised version of the national anthem as the words are a matter of tradition; only the first verse is usually sung.[1] No law was passed making "God Save the Queen" the official anthem. In the English tradition, such laws are not necessary; proclamation and usage are sufficient to make it the national anthem. "God Save the Queen" also serves as the Royal anthem for several other countries, namely certain Commonwealth realms. +Jump up ^ Under the Council of Europe's European Charter for Regional or Minority Languages, Scots, Ulster-Scots, Welsh, Cornish, Irish and Scottish Gaelic, are officially recognised as regional or minority languages by the British government for the purposes of the Charter. See also Languages of the United Kingdom.[2] +Jump up ^ Although Northern Ireland is the only part of the UK that shares a land border with another state, two of its Overseas Territories also share land borders with other states. Gibraltar shares a border with Spain, while the Sovereign Base Areas of Akrotiri and Dhekelia share borders with the Republic of Cyprus, Turkish Republic of Northern Cyprus and UN buffer zone separating the two Cypriot polities. +Jump up ^ The Anglo-Irish Treaty was signed on 6 December 1921 to resolve the Irish War of Independence. Effective one year later, it established the Irish Free State as a separate dominion within the Commonwealth. The UK's current name was adopted in 1927 to reflect the change. +Jump up ^ Compare to section 1 of both of the 1800 Acts of Union which reads: the Kingdoms of Great Britain and Ireland shall...be united into one Kingdom, by the Name of "The United Kingdom of Great Britain and Ireland" +Jump up ^ New Zealand, Israel and San Marino are the other countries with uncodified constitutions. +Jump up ^ Since the early twentieth century the prime minister has held the office of First Lord of the Treasury, and in recent decades has also held the office of Minister for the Civil Service. +Jump up ^ Sinn Féin, an Irish republican party, also contests elections in the Republic of Ireland. +Jump up ^ In 2007–2008, this was calculated to be £115 per week for single adults with no dependent children; £199 per week for couples with no dependent children; £195 per week for single adults with two dependent children under 14; and £279 per week for couples with two dependent children under 14. +References +Jump up ^ National Anthem, British Monarchy official website. Retrieved 16 November 2013. +^ Jump up to: a b c "List of declarations made with respect to treaty No. 148". Council of Europe. Retrieved 12 December 2013. +^ Jump up to: a b "Population Estimates for UK, England and Wales, Scotland and Northern Ireland, Mid-2013". Office for National Statistics. Retrieved 26 June 2014. +Jump up ^ "2011 UK censuses". Office for National Statistics. Retrieved 17 December 2012. +^ Jump up to: a b c d "United Kingdom". International Monetary Fund. Retrieved 1 November 2014. +Jump up ^ "Gini coefficient of equivalised disposable income (source: SILC)". Eurostat Data Explorer. Retrieved 13 August 2013. +Jump up ^ "2014 Human Development Report". 14 March 2013. pp. 22–25. Retrieved 27 July 2014. +Jump up ^ "Definition of Great Britain in English". Oxford University Press. Retrieved 29 October 2014. Great Britain is the name for the island that comprises England, Scotland, and Wales, although the term is also used loosely to refer to the United Kingdom. +Jump up ^ The British Monarchy, What is constitutional monarchy?. Retrieved 17 July 2013 +Jump up ^ CIA, The World Factbook. Retrieved 17 July 2013 +Jump up ^ "The World Factbook". Central Intelligence Agency. 1 February 2014. Retrieved 23 February 2014. +^ Jump up to: a b "Countries within a country". Prime Minister's Office. 10 January 2003. +^ Jump up to: a b "Devolution of powers to Scotland, Wales, and Northern Ireland". United Kingdom Government. Retrieved 17 April 2013. In a similar way to how the government is formed from members from the two Houses of Parliament, members of the devolved legislatures nominate ministers from among themselves to comprise an executive, known as the devolved administrations... +Jump up ^ "Fall in UK university students". BBC News. 29 January 2009. +Jump up ^ "Country Overviews: United Kingdom". Transport Research Knowledge Centre. Retrieved 28 March 2010. +Jump up ^ "Key facts about the United Kingdom". Directgov. Retrieved 3 May 2011. The full title of this country is 'the United Kingdom of Great Britain and Northern Ireland'. 'The UK' is made up of England, Scotland, Wales and Northern Ireland. 'Britain' is used informally, usually meaning the United Kingdom. 'Great Britain' is made up of England, Scotland and Wales. The Channel Islands and the Isle of Man are not part of the UK.[dead link] +Jump up ^ "Working with Overseas Territories". Foreign and Commonwealth Office. Retrieved 3 May 2011. +Jump up ^ Mathias, P. (2001). The First Industrial Nation: the Economic History of Britain, 1700–1914. London: Routledge. ISBN 0-415-26672-6. +Jump up ^ Ferguson, Niall (2004). Empire: The rise and demise of the British world order and the lessons for global power. New York: Basic Books. ISBN 0-465-02328-2. +Jump up ^ Sheridan, Greg (15 May 2010). "Cameron has chance to make UK great again". The Australian (Sydney). Retrieved 23 May 2011. +Jump up ^ Dugan, Emily (18 November 2012). "Britain is now most powerful nation on earth". The Independent (London). Retrieved 18 November 2012. +^ Jump up to: a b "The 15 countries with the highest military expenditure in 2013 (table)" (PDF). Stockholm International Peace Research Institute. Retrieved 4 May 2014. +^ Jump up to: a b The Military Balance 2014: Top 15 Defence Budgets 2013 (IISS) +Jump up ^ "Treaty of Union, 1706". Scots History Online. Retrieved 23 August 2011. +Jump up ^ Barnett, Hilaire; Jago, Robert (2011). Constitutional & Administrative Law (8th ed.). Abingdon: Routledge. p. 165. ISBN 978-0-415-56301-7. +Jump up ^ Gascoigne, Bamber. "History of Great Britain (from 1707)". History World. Retrieved 18 July 2011. +Jump up ^ Cottrell, P. (2008). The Irish Civil War 1922–23. p. 85. ISBN 1-84603-270-9. +^ Jump up to: a b S. Dunn; H. Dawson (2000), An Alphabetical Listing of Word, Name and Place in Northern Ireland and the Living Language of Conflict, Lampeter: Edwin Mellen Press, One specific problem - in both general and particular senses - is to know what to call Northern Ireland itself: in the general sense, it is not a country, or a province, or a state - although some refer to it contemptuously as a statelet: the least controversial word appears to be jurisdiction, but this might change. +Jump up ^ "Changes in the list of subdivision names and code elements". ISO 3166-2. International Organization for Standardization. 15 December 2011. Retrieved 28 May 2012. +Jump up ^ Population Trends, Issues 75–82, p.38, 1994, UK Office of Population Censuses and Surveys +Jump up ^ Life in the United Kingdom: a journey to citizenship, p. 7, United Kingdom Home Office, 2007, ISBN 978-0-11-341313-3. +Jump up ^ "Statistical bulletin: Regional Labour Market Statistics". Retrieved 5 March 2014. +Jump up ^ "13.4% Fall In Earnings Value During Recession". Retrieved 5 March 2014. +Jump up ^ Murphy, Dervla (1979). A Place Apart. London: Penguin. ISBN 978-0-14-005030-1. +Jump up ^ Whyte, John; FitzGerald, Garret (1991). Interpreting Northern Ireland. Oxford: Clarendon Press. ISBN 978-0-19-827380-6. +Jump up ^ "Guardian Unlimited Style Guide". London: Guardian News and Media Limited. 19 December 2008. Retrieved 23 August 2011. +Jump up ^ "BBC style guide (Great Britain)". BBC News. 19 August 2002. Retrieved 23 August 2011. +Jump up ^ "Key facts about the United Kingdom". Government, citizens and rights. HM Government. Retrieved 24 August 2011.[dead link] +Jump up ^ "Merriam-Webster Dictionary Online Definition of ''Great Britain''". Merriam Webster. 31 August 2012. Retrieved 9 April 2013. +Jump up ^ New Oxford American Dictionary: "Great Britain: England, Wales, and Scotland considered as a unit. The name is also often used loosely to refer to the United Kingdom." +Jump up ^ "Great Britain". International Olympic Committee. Retrieved 10 May 2011. +Jump up ^ "Team GB – Our Greatest Team". British Olympic Association. Retrieved 10 May 2011.[dead link] +Jump up ^ Bradley, Anthony Wilfred; Ewing, Keith D. (2007). Constitutional and administrative law 1 (14th ed.). Harlow: Pearson Longman. p. 36. ISBN 978-1-4058-1207-8. +Jump up ^ "Which of these best describes the way you think of yourself?". Northern Ireland Life and Times Survey 2010. ARK – Access Research Knowledge. 2010. Retrieved 1 July 2010. +Jump up ^ Schrijver, Frans (2006). Regionalism after regionalisation: Spain, France and the United Kingdom. Amsterdam University Press. pp. 275–277. ISBN 978-90-5629-428-1. +Jump up ^ Jack, Ian (11 December 2010). "Why I'm saddened by Scotland going Gaelic". The Guardian (London). +Jump up ^ Ffeithiau allweddol am y Deyrnas Unedig : Directgov – Llywodraeth, dinasyddion a hawliau[dead link] +Jump up ^ "Ancient skeleton was 'even older'". BBC News. 30 October 2007. Retrieved 27 April 2011. +Jump up ^ Koch, John T. (2006). Celtic culture: A historical encyclopedia. Santa Barbara, CA: ABC-CLIO. p. 973. ISBN 978-1-85109-440-0. +Jump up ^ Davies, John; Jenkins, Nigel; Baines, Menna; Lynch, Peredur I., eds. (2008). The Welsh Academy Encyclopaedia of Wales. Cardiff: University of Wales Press. p. 915. ISBN 978-0-7083-1953-6. +Jump up ^ "Short Athelstan biography". BBC History. Retrieved 9 April 2013. +Jump up ^ Mackie, J.D. (1991). A History of Scotland. London: Penguin. pp. 18–19. ISBN 978-0-14-013649-4. +Jump up ^ Campbell, Ewan (1999). Saints and Sea-kings: The First Kingdom of the Scots. Edinburgh: Canongate. pp. 8–15. ISBN 0-86241-874-7. +Jump up ^ Haigh, Christopher (1990). The Cambridge Historical Encyclopedia of Great Britain and Ireland. Cambridge University Press. p. 30. ISBN 978-0-521-39552-6. +Jump up ^ Ganshof, F.L. (1996). Feudalism. University of Toronto. p. 165. ISBN 978-0-8020-7158-3. +Jump up ^ Chibnall, Marjorie (1999). The debate on the Norman Conquest. Manchester University Press. pp. 115–122. ISBN 978-0-7190-4913-2. +Jump up ^ Keen, Maurice. "The Hundred Years War". BBC History. +Jump up ^ The Reformation in England and Scotland and Ireland: The Reformation Period & Ireland under Elizabth I, Encyclopædia Britannica Online. +Jump up ^ "British History in Depth – Wales under the Tudors". BBC History. 5 November 2009. Retrieved 21 September 2010. +Jump up ^ Nicholls, Mark (1999). A history of the modern British Isles, 1529–1603: The two kingdoms. Oxford: Blackwell. pp. 171–172. ISBN 978-0-631-19334-0. +Jump up ^ Canny, Nicholas P. (2003). Making Ireland British, 1580–1650. Oxford University Press. pp. 189–200. ISBN 978-0-19-925905-2. +Jump up ^ Ross, D. (2002). Chronology of Scottish History. Glasgow: Geddes & Grosset. p. 56. ISBN 1-85534-380-0 +Jump up ^ Hearn, J. (2002). Claiming Scotland: National Identity and Liberal Culture. Edinburgh University Press. p. 104. ISBN 1-902930-16-9 +Jump up ^ "English Civil Wars". Encyclopaedia Britannica. Retrieved 28 April 2013. +Jump up ^ "Scotland and the Commonwealth: 1651–1660". Archontology.org. 14 March 2010. Retrieved 20 April 2010. +Jump up ^ Lodge, Richard (2007) [1910]. The History of England – From the Restoration to the Death of William III (1660–1702). Read Books. p. 8. ISBN 978-1-4067-0897-4. +Jump up ^ "Tudor Period and the Birth of a Regular Navy". Royal Navy History. Institute of Naval History. Retrieved 24 December 2010.[dead link] +Jump up ^ Canny, Nicholas (1998). The Origins of Empire, The Oxford History of the British Empire Volume I. Oxford University Press. ISBN 0-19-924676-9. +Jump up ^ "Articles of Union with Scotland 1707". UK Parliament. Retrieved 19 October 2008. +Jump up ^ "Acts of Union 1707". UK Parliament. Retrieved 6 January 2011. +Jump up ^ "Treaty (act) of Union 1706". Scottish History online. Retrieved 3 February 2011. +Jump up ^ Library of Congress, The Impact of the American Revolution Abroad, p. 73. +Jump up ^ Loosemore, Jo (2007). Sailing against slavery. BBC Devon. 2007. +Jump up ^ "The Act of Union". Act of Union Virtual Library. Retrieved 15 May 2006. +Jump up ^ Tellier, L.-N. (2009). Urban World History: an Economic and Geographical Perspective. Quebec: PUQ. p. 463. ISBN 2-7605-1588-5. +Jump up ^ Sondhaus, L. (2004). Navies in Modern World History. London: Reaktion Books. p. 9. ISBN 1-86189-202-0. +Jump up ^ Porter, Andrew (1998). The Nineteenth Century, The Oxford History of the British Empire Volume III. Oxford University Press. p. 332. ISBN 0-19-924678-5. +Jump up ^ "The Workshop of the World". BBC History. Retrieved 28 April 2013. +Jump up ^ Porter, Andrew (1998). The Nineteenth Century, The Oxford History of the British Empire Volume III. Oxford University Press. p. 8. ISBN 0-19-924678-5. +Jump up ^ Marshall, P.J. (1996). The Cambridge Illustrated History of the British Empire. Cambridge University Press. pp. 156–57. ISBN 0-521-00254-0. +Jump up ^ Tompson, Richard S. (2003). Great Britain: a reference guide from the Renaissance to the present. New York: Facts on File. p. 63. ISBN 978-0-8160-4474-0. +Jump up ^ Hosch, William L. (2009). World War I: People, Politics, and Power. America at War. New York: Britannica Educational Publishing. p. 21. ISBN 978-1-61530-048-8. +Jump up ^ Turner, John (1988). Britain and the First World War. London: Unwin Hyman. pp. 22–35. ISBN 978-0-04-445109-9. +^ Jump up to: a b Westwell, I.; Cove, D. (eds) (2002). History of World War I, Volume 3. London: Marshall Cavendish. pp. 698 and 705. ISBN 0-7614-7231-2. +Jump up ^ Turner, J. (1988). Britain and the First World War. Abingdon: Routledge. p. 41. ISBN 0-04-445109-1. +Jump up ^ SR&O 1921, No. 533 of 3 May 1921. +Jump up ^ "The Anglo-Irish Treaty, 6 December 1921". CAIN. Retrieved 15 May 2006. +Jump up ^ Rubinstein, W. D. (2004). Capitalism, Culture, and Decline in Britain, 1750–1990. Abingdon: Routledge. p. 11. ISBN 0-415-03719-0. +Jump up ^ "Britain to make its final payment on World War II loan from U.S.". The New York Times. 28 December 2006. Retrieved 25 August 2011. +Jump up ^ Francis, Martin (1997). Ideas and policies under Labour, 1945–1951: Building a new Britain. Manchester University Press. pp. 225–233. ISBN 978-0-7190-4833-3. +Jump up ^ Lee, Stephen J. (1996). Aspects of British political history, 1914–1995. London; New York: Routledge. pp. 173–199. ISBN 978-0-415-13103-2. +Jump up ^ Larres, Klaus (2009). A companion to Europe since 1945. Chichester: Wiley-Blackwell. p. 118. ISBN 978-1-4051-0612-2. +Jump up ^ "Country List". Commonwealth Secretariat. 19 March 2009. Retrieved 11 September 2012.[dead link] +Jump up ^ Julios, Christina (2008). Contemporary British identity: English language, migrants, and public discourse. Studies in migration and diaspora. Aldershot: Ashgate. p. 84. ISBN 978-0-7546-7158-9. +Jump up ^ Aughey, Arthur (2005). The Politics of Northern Ireland: Beyond the Belfast Agreement. London: Routledge. p. 7. ISBN 978-0-415-32788-6. +Jump up ^ "The troubles were over, but the killing continued. Some of the heirs to Ireland's violent traditions refused to give up their inheritance." Holland, Jack (1999). Hope against History: The Course of Conflict in Northern Ireland. New York: Henry Holt. p. 221. ISBN 978-0-8050-6087-4. +Jump up ^ Elliot, Marianne (2007). The Long Road to Peace in Northern Ireland: Peace Lectures from the Institute of Irish Studies at Liverpool University. University of Liverpool Institute of Irish Studies, Liverpool University Press. p. 2. ISBN 1-84631-065-2. +Jump up ^ Dorey, Peter (1995). British politics since 1945. Making contemporary Britain. Oxford: Blackwell. pp. 164–223. ISBN 978-0-631-19075-2. +Jump up ^ Griffiths, Alan; Wall, Stuart (2007). Applied Economics (11th ed.). Harlow: Financial Times Press. p. 6. ISBN 978-0-273-70822-3. Retrieved 26 December 2010. +Jump up ^ Keating, Michael (1 January 1998). "Reforging the Union: Devolution and Constitutional Change in the United Kingdom". Publius: the Journal of Federalism 28 (1): 217. doi:10.1093/oxfordjournals.pubjof.a029948. Retrieved 4 February 2009. +Jump up ^ Jackson, Mike (3 April 2011). "Military action alone will not save Libya". Financial Times (London). +Jump up ^ "United Kingdom country profile". BBC. 24 January 2013. Retrieved 9 April 2013. +Jump up ^ "Scotland to hold independence poll in 2014 – Salmond". BBC News. 10 January 2012. Retrieved 10 January 2012. +Jump up ^ Oxford English Dictionary: "British Isles: a geographical term for the islands comprising Great Britain and Ireland with all their offshore islands including the Isle of Man and the Channel Islands." +^ Jump up to: a b c d e f "United Kingdom". The World Factbook. Central Intelligence Agency. Retrieved 23 September 2008. +^ Jump up to: a b c d e Latimer Clarke Corporation Pty Ltd. "United Kingdom – Atlapedia Online". Atlapedia.com. Retrieved 26 October 2010. +Jump up ^ ROG Learing Team (23 August 2002). "The Prime Meridian at Greenwich". Royal Museums Greenwich. Royal Museums Greenwich. Retrieved 11 September 2012. +Jump up ^ Neal, Clare. "How long is the UK coastline?". British Cartographic Society. Retrieved 26 October 2010. +Jump up ^ "The Channel Tunnel". Eurotunnel. Retrieved 29 November 2010.[dead link] +Jump up ^ "England – Profile". BBC News. 11 February 2010. +Jump up ^ "Scotland Facts". Scotland Online Gateway. Archived from the original on 21 June 2008. Retrieved 16 July 2008. +Jump up ^ Winter, Jon (19 May 2001). "The complete guide to Scottish Islands". The Independent (London). +Jump up ^ "Overview of Highland Boundary Fault". Gazetteer for Scotland. University of Edinburgh. Retrieved 27 December 2010. +Jump up ^ "Ben Nevis Weather". Ben Nevis Weather. Retrieved 26 October 2008. +Jump up ^ "Profile: Wales". BBC News. 9 June 2010. Retrieved 7 November 2010. +Jump up ^ Giles Darkes (26 April 2014). "How long is the UK coastline?". The British Cartographic Society. +Jump up ^ "Geography of Northern Ireland". University of Ulster. Retrieved 22 May 2006. +Jump up ^ "UK climate summaries". Met Office. Retrieved 1 May 2011. +Jump up ^ United Nations Economic and Social Council (August 2007). "Ninth UN Conference on the standardization of Geographical Names". UN Statistics Division. Archived from the original on 1 December 2009. Retrieved 21 October 2008. +Jump up ^ Barlow, I.M. (1991). Metropolitan Government. London: Routledge. ISBN 978-0-415-02099-2. +Jump up ^ "Welcome to the national site of the Government Office Network". Government Offices. Archived from the original on 15 June 2009. Retrieved 3 July 2008. +Jump up ^ "A short history of London government". Greater London Authority. Archived from the original on 21 April 2008. Retrieved 4 October 2008. +Jump up ^ Sherman, Jill; Norfolk, Andrew (5 November 2004). "Prescott's dream in tatters as North East rejects assembly". The Times (London). Retrieved 15 February 2008. The Government is now expected to tear up its twelve-year-old plan to create eight or nine regional assemblies in England to mirror devolution in Scotland and Wales. (subscription required) +Jump up ^ "Local Authority Elections". Local Government Association. Retrieved 3 October 2008.[dead link] +Jump up ^ "STV in Scotland: Local Government Elections 2007". Political Studies Association. Archived from the original on 20 March 2011. Retrieved 2 August 2008. +Jump up ^ Ethical Standards in Public Life framework: "Ethical Standards in Public Life". The Scottish Government. Retrieved 3 October 2008. +Jump up ^ "Who we are". Convention of Scottish Local Authorities. Retrieved 5 July 2011. +Jump up ^ "Local Authorities". The Welsh Assembly Government. Retrieved 31 July 2008. +Jump up ^ "Local government elections in Wales". The Electoral Commission. 2008. Retrieved 8 April 2011. +Jump up ^ "Welsh Local Government Association". Welsh Local Government Association. Retrieved 20 March 2008. +Jump up ^ Devenport, Mark (18 November 2005). "NI local government set for shake-up". BBC News. Retrieved 15 November 2008. +Jump up ^ "Foster announces the future shape of local government" (Press release). Northern Ireland Executive. 13 March 2008. Retrieved 20 October 2008. +Jump up ^ "Local Government elections to be aligned with review of public administration" (Press release). Northern Ireland Office. 25 April 2008. Retrieved 2 August 2008.[dead link] +Jump up ^ "CIBC PWM Global – Introduction to The Cayman Islands". Cibc.com. 11 July 2012. Retrieved 17 August 2012. +Jump up ^ Rappeport, Laurie. "Cayman Islands Tourism". Washington DC: USA Today Travel Tips. Retrieved 9 April 2013. +Jump up ^ "Working with Overseas Territories". Foreign & Commonwealth Office. 6 October 2010. Retrieved 5 November 2010. +Jump up ^ http://www.justice.gov.uk/downloads/about/moj/our-responsibilities/Background_Briefing_on_the_Crown_Dependencies2.pdf +Jump up ^ "Overseas Territories". Foreign & Commonwealth Office. Retrieved 6 September 2010. +Jump up ^ "The World Factbook". CIA. Retrieved 26 December 2010. +Jump up ^ "Country profiles". Foreign & Commonwealth Office. 21 February 2008. Retrieved 6 September 2010.[dead link] +Jump up ^ Davison, Phil (18 August 1995). "Bermudians vote to stay British". The Independent (London). Retrieved 11 September 2012. +Jump up ^ The Committee Office, House of Commons. "House of Commons – Crown Dependencies – Justice Committee". Publications.parliament.uk. Retrieved 7 November 2010. +Jump up ^ Fact sheet on the UK's relationship with the Crown Dependencies – gov.uk, Ministry of Justice. Retrieved 25 August 2014. +Jump up ^ "Profile of Jersey". States of Jersey. Retrieved 31 July 2008. The legislature passes primary legislation, which requires approval by The Queen in Council, and enacts subordinate legislation in many areas without any requirement for Royal Sanction and under powers conferred by primary legislation. +Jump up ^ "Chief Minister to meet Channel Islands counterparts – Isle of Man Public Services" (Press release). Isle of Man Government. 29 May 2012. Retrieved 9 April 2013.[dead link] +Jump up ^ Bagehot, Walter (1867). The English Constitution. London: Chapman and Hall. p. 103. +Jump up ^ Carter, Sarah. "A Guide To the UK Legal System". University of Kent at Canterbury. Retrieved 16 May 2006. +Jump up ^ "Parliamentary sovereignty". UK Parliament. n.d. Archived from the original on 27 May 2012. +Jump up ^ "The Government, Prime Minister and Cabinet". Public services all in one place. Directgov. Retrieved 12 February 2010. +Jump up ^ "Brown is UK's new prime minister". BBC News. 27 June 2007. Retrieved 23 January 2008. +Jump up ^ "David Cameron is UK's new prime minister". BBC News. 11 May 2010. Retrieved 11 May 2010. +Jump up ^ November 2010 "Elections and voting". UK Parliament. Archived from the original on 14 November 2010. Retrieved 14 November 2010. +Jump up ^ November 2010 "The Parliament Acts". UK Parliament. Archived from the original on 14 November 2010. +Jump up ^ "United Kingdom". European Election Database. Norwegian Social Science Data Services. Retrieved 3 July 2010. +Jump up ^ Wainwright, Martin (28 May 2010). "Thirsk and Malton: Conservatives take final seat in parliament". The Guardian (London). Retrieved 3 July 2010. +Jump up ^ "Scots MPs attacked over fees vote". BBC News. 27 January 2004. Retrieved 21 October 2008. +Jump up ^ Taylor, Brian (1 June 1998). "Talking Politics: The West Lothian Question". BBC News. Retrieved 21 October 2008. +Jump up ^ "England-only laws 'need majority from English MPs'". BBC News. 25 March 2013. Retrieved 28 April 2013. +Jump up ^ "Scotland's Parliament – powers and structures". BBC News. 8 April 1999. Retrieved 21 October 2008. +Jump up ^ "Salmond elected as first minister". BBC News. 16 May 2007. Retrieved 21 October 2008. +Jump up ^ "Scottish election: SNP wins election". BBC News. 6 May 2011. +Jump up ^ "Structure and powers of the Assembly". BBC News. 9 April 1999. Retrieved 21 October 2008. +Jump up ^ "Carwyn Jones clinches leadership in Wales". WalesOnline (Media Wales). 1 December 2009. Retrieved 1 December 2009. +Jump up ^ "Devolved Government – Ministers and their departments". Northern Ireland Executive. Archived from the original on 22 August 2007. +Jump up ^ Burrows, N. (1999). "Unfinished Business: The Scotland Act 1998". The Modern Law Review 62 (2): 241–60 [p. 249]. doi:10.1111/1468-2230.00203. The UK Parliament is sovereign and the Scottish Parliament is subordinate. The White Paper had indicated that this was to be the approach taken in the legislation. The Scottish Parliament is not to be seen as a reflection of the settled will of the people of Scotland or of popular sovereignty but as a reflection of its subordination to a higher legal authority. Following the logic of this argument, the power of the Scottish Parliament to legislate can be withdrawn or overridden... +Jump up ^ Elliot, M. (2004). "United Kingdom: Parliamentary sovereignty under pressure". International Journal of Constitutional Law 2 (3): 545–627 [pp. 553–554]. doi:10.1093/icon/2.3.545. Notwithstanding substantial differences among the schemes, an important common factor is that the U.K. Parliament has not renounced legislative sovereignty in relation to the three nations concerned. For example, the Scottish Parliament is empowered to enact primary legislation on all matters, save those in relation to which competence is explicitly denied ... but this power to legislate on what may be termed "devolved matters" is concurrent with the Westminster Parliament's general power to legislate for Scotland on any matter at all, including devolved matters ... In theory, therefore, Westminster may legislate on Scottish devolved matters whenever it chooses... +Jump up ^ Walker, G. (2010). "Scotland, Northern Ireland, and Devolution, 1945–1979". Journal of British Studies 39 (1): 124 & 133. doi:10.1086/644536. +Jump up ^ Gamble, A. "The Constitutional Revolution in the United Kingdom". Publius 36 (1): 19–35 [p. 29]. doi:10.1093/publius/pjj011. The British parliament has the power to abolish the Scottish parliament and the Welsh assembly by a simple majority vote in both houses, but since both were sanctioned by referenda, it would be politically difficult to abolish them without the sanction of a further vote by the people. In this way several of the constitutional measures introduced by the Blair government appear to be entrenched and not subject to a simple exercise of parliamentary sovereignty at Westminster. +Jump up ^ Meehan, E. (1999). "The Belfast Agreement—Its Distinctiveness and Points of Cross-Fertilization in the UK's Devolution Programme". Parliamentary Affairs 52 (1): 19–31 [p. 23]. doi:10.1093/pa/52.1.19. [T]he distinctive involvement of two governments in the Northern Irish problem means that Northern Ireland's new arrangements rest upon an intergovernmental agreement. If this can be equated with a treaty, it could be argued that the forthcoming distribution of power between Westminster and Belfast has similarities with divisions specified in the written constitutions of federal states... Although the Agreement makes the general proviso that Westminster's 'powers to make legislation for Northern Ireland' remains 'unaffected', without an explicit categorical reference to reserved matters, it may be more difficult than in Scotland or Wales for devolved powers to be repatriated. The retraction of devolved powers would not merely entail consultation in Northern Ireland backed implicitly by the absolute power of parliamentary sovereignty but also the renegotiation of an intergovernmental agreement. +Jump up ^ "The Treaty (act) of the Union of Parliament 1706". Scottish History Online. Retrieved 5 October 2008. +Jump up ^ "UK Supreme Court judges sworn in". BBC News. 1 October 2009. +Jump up ^ "Constitutional reform: A Supreme Court for the United Kingdom". Department for Constitutional Affairs. July 2003. Retrieved 13 May 2013. +Jump up ^ "Role of the JCPC". Judicial Committee of the Privy Council. Retrieved 28 April 2013. +Jump up ^ Bainham, Andrew (1998). The international survey of family law: 1996. The Hague: Martinus Nijhoff. p. 298. ISBN 978-90-411-0573-8. +Jump up ^ Adeleye, Gabriel; Acquah-Dadzie, Kofi; Sienkewicz, Thomas; McDonough, James (1999). World dictionary of foreign expressions. Waucojnda, IL: Bolchazy-Carducci. p. 371. ISBN 978-0-86516-423-9. +Jump up ^ "The Australian courts and comparative law". Australian Law Postgraduate Network. Retrieved 28 December 2010. +Jump up ^ "Court of Session – Introduction". Scottish Courts. Retrieved 5 October 2008.[dead link] +Jump up ^ "High Court of Justiciary – Introduction". Scottish Courts. Retrieved 5 October 2008.[dead link] +Jump up ^ "House of Lords – Practice Directions on Permission to Appeal". UK Parliament. Retrieved 22 June 2009. +Jump up ^ "Introduction". Scottish Courts. Retrieved 5 October 2008.[dead link] +Jump up ^ Samuel Bray (2005). "Not proven: introducing a third verdict". The University of Chicago Law Review 72 (4): 1299. Retrieved 30 November 2013. +Jump up ^ "Police-recorded crime down by 9%". BBC News. 17 July 2008. Retrieved 21 October 2008. +Jump up ^ "New record high prison population". BBC News. 8 February 2008. Retrieved 21 October 2008. +Jump up ^ "Crime falls to 32 year low" (Press release). Scottish Government. 7 September 2010. Retrieved 21 April 2011. +Jump up ^ "Prisoner Population at Friday 22 August 2008". Scottish Prison Service. Retrieved 28 August 2008. +Jump up ^ "Scots jail numbers at record high". BBC News. 29 August 2008. Retrieved 21 October 2008. +Jump up ^ Swaine, Jon (13 January 2009). "Barack Obama presidency will strengthen special relationship, says Gordon Brown". The Daily Telegraph (London). Retrieved 3 May 2011. +Jump up ^ Kirchner, E. J.; Sperling, J. (2007). Global Security Governance: Competing Perceptions of Security in the 21st Century. London: Taylor & Francis. p. 100. ISBN 0-415-39162-8 +Jump up ^ The Committee Office, House of Commons (19 February 2009). "DFID's expenditure on development assistance". UK Parliament. Retrieved 28 April 2013. +Jump up ^ "Ministry of Defence". Ministry of Defence. Retrieved 21 February 2012. +Jump up ^ "Speaker addresses Her Majesty Queen Elizabeth II". UK Parliament. 30 March 2012. Retrieved 28 April 2013. +Jump up ^ "House of Commons Hansard". UK Parliament. Retrieved 23 October 2008. +Jump up ^ UK 2005: The Official Yearbook of the United Kingdom of Great Britain and Northern Ireland. Office for National Statistics. p. 89. +Jump up ^ "Principles for Economic Regulation". Department for Business, Innovation & Skills. April 2011. Retrieved 1 May 2011. +Jump up ^ "United Kingdom". International Monetary Fund. Retrieved 1 October 2009. +Jump up ^ Chavez-Dreyfuss, Gertrude (1 April 2008). "Global reserves, dollar share up at end of 2007-IMF". Reuters. Retrieved 21 December 2009. +Jump up ^ "More About the Bank". Bank of England. n.d. Archived from the original on 12 March 2008. +Jump up ^ "Index of Services (experimental)". Office for National Statistics. 7 May 2006. Archived from the original on 7 May 2006. +Jump up ^ Sassen, Saskia (2001). The Global City: New York, London, Tokyo (2nd ed.). Princeton University Press. ISBN 0-691-07866-1. +^ Jump up to: a b "Global Financial Centres 7". Z/Yen. 2010. Retrieved 21 April 2010. +^ Jump up to: a b "Worldwide Centres of Commerce Index 2008". Mastercard. Retrieved 5 July 2011. +^ Jump up to: a b Zumbrun, Joshua (15 July 2008). ""World's Most Economically Powerful Cities".". Forbes (New York). Archived from the original on 19 May 2011. Retrieved 3 October 2010. +Jump up ^ "Global city GDP rankings 2008–2025". PricewaterhouseCoopers. Archived from the original on 19 May 2011. Retrieved 16 November 2010. +Jump up ^ Lazarowicz, Mark (Labour MP) (30 April 2003). "Financial Services Industry". UK Parliament. Retrieved 17 October 2008. +Jump up ^ International Tourism Receipts[dead link]. UNWTO Tourism Highlights, Edition 2005. page 12. World Tourism Organisation. Retrieved 24 May 2006. +Jump up ^ Bremner, Caroline (10 January 2010). "Euromonitor International's Top City Destination Ranking". Euromonitor International. Archived from the original on 19 May 2011. Retrieved 31 May 2011. +Jump up ^ "From the Margins to the Mainstream – Government unveils new action plan for the creative industries". DCMS. 9 March 2007. Retrieved 9 March 2007.[dead link] +^ Jump up to: a b "European Countries – United Kingdom". Europa (web portal). Retrieved 15 December 2010. +Jump up ^ Harrington, James W.; Warf, Barney (1995). Industrial location: Principles, practices, and policy. London: Routledge. p. 121. ISBN 978-0-415-10479-1. +Jump up ^ Spielvogel, Jackson J. (2008). Western Civilization: Alternative Volume: Since 1300. Belmont, CA: Thomson Wadsworth. ISBN 978-0-495-55528-5. +Jump up ^ Hewitt, Patricia (15 July 2004). "TUC Manufacturing Conference". Department of Trade and Industry. Retrieved 16 May 2006. +Jump up ^ "Industry topics". Society of Motor Manufacturers and Traders. 2011. Retrieved 5 July 2011. +Jump up ^ Robertson, David (9 January 2009). "The Aerospace industry has thousands of jobs in peril". The Times (London). Retrieved 9 June 2011. (subscription required) +Jump up ^ "Facts & Figures – 2009". Aerospace & Defence Association of Europe. Retrieved 9 June 2011.[dead link] +Jump up ^ "UK Aerospace Industry Survey – 2010". ADS Group. Retrieved 9 June 2011. +^ Jump up to: a b c d http://www.theengineer.co.uk/aerospace/in-depth/reasons-to-be-cheerful-about-the-uk-aerospace-sector/1017274.article +Jump up ^ "The Pharmaceutical sector in the UK". Department for Business, Innovation & Skills. Retrieved 9 June 2011. +Jump up ^ "Ministerial Industry Strategy Group – Pharmaceutical Industry: Competitiveness and Performance Indicators". Department of Health. Retrieved 9 June 2011.[dead link] +Jump up ^ [1][dead link] +Jump up ^ "UK in recession as economy slides". BBC News. 23 January 2009. Retrieved 23 January 2009. +Jump up ^ "UK youth unemployment at its highest in two decades: 22.5%". MercoPress. 15 April 2012. +Jump up ^ Groom, Brian (19 January 2011). "UK youth unemployment reaches record". Financial Times (London). +Jump up ^ "Release: EU Government Debt and Deficit returns". Office for National Statistics. March 2012. Retrieved 17 August 2012. +Jump up ^ "UK loses top AAA credit rating for first time since 1978". BBC News. 23 February 2013. Retrieved 23 February 2013. +Jump up ^ "Britain sees real wages fall 3.2%". Daily Express (London). 2 March 2013. +Jump up ^ Beckford, Martin (5 December 2011). "Gap between rich and poor growing fastest in Britain". The Daily Telegraph (London). +Jump up ^ "United Kingdom: Numbers in low income". The Poverty Site. Retrieved 25 September 2009. +Jump up ^ "United Kingdom: Children in low income households". The Poverty Site. Retrieved 25 September 2009. +Jump up ^ "Warning of food price hike crisis". BBC News. 4 April 2009. +Jump up ^ Andrews, J. (16 January 2013). "How poor is Britain now". Yahoo! Finance UK +Jump up ^ Glynn, S.; Booth, A. (1996). Modern Britain: An Economic and Social History. London: Routledge. +Jump up ^ "Report highlights 'bleak' poverty levels in the UK" Phys.org, 29 March 2013 +Jump up ^ Gascoin, J. "A reappraisal of the role of the universities in the Scientific Revolution", in Lindberg, David C. and Westman, Robert S., eds (1990), Reappraisals of the Scientific Revolution. Cambridge University Press. p. 248. ISBN 0-521-34804-8. +Jump up ^ Reynolds, E.E.; Brasher, N.H. (1966). Britain in the Twentieth Century, 1900–1964. Cambridge University Press. p. 336. OCLC 474197910 +Jump up ^ Burtt, E.A. (2003) [1924].The Metaphysical Foundations of Modern Science. Mineola, NY: Courier Dover. p. 207. ISBN 0-486-42551-7. +Jump up ^ Hatt, C. (2006). Scientists and Their Discoveries. London: Evans Brothers. pp. 16, 30 and 46. ISBN 0-237-53195-X. +Jump up ^ Jungnickel, C.; McCormmach, R. (1996). Cavendish. American Philosophical Society. ISBN 0-87169-220-1. +Jump up ^ "The Nobel Prize in Physiology or Medicine 1945: Sir Alexander Fleming, Ernst B. Chain, Sir Howard Florey". The Nobel Foundation. Archived from the original on 21 June 2011. +Jump up ^ Hatt, C. (2006). Scientists and Their Discoveries. London: Evans Brothers. p. 56. ISBN 0-237-53195-X. +Jump up ^ James, I. (2010). Remarkable Engineers: From Riquet to Shannon. Cambridge University Press. pp. 33–6. ISBN 0-521-73165-8. +Jump up ^ Bova, Ben (2002) [1932]. The Story of Light. Naperville, IL: Sourcebooks. p. 238. ISBN 978-1-4022-0009-0. +Jump up ^ "Alexander Graham Bell (1847–1922)". Scottish Science Hall of Fame. Archived from the original on 21 June 2011. +Jump up ^ "John Logie Baird (1888–1946)". BBC History. Archived from the original on 21 June 2011. +Jump up ^ Cole, Jeffrey (2011). Ethnic Groups of Europe: An Encyclopedia. Santa Barbara, CA: ABC-CLIO. p. 121. ISBN 1-59884-302-8. +Jump up ^ Castells, M.; Hall, P.; Hall, P.G. (2004). Technopoles of the World: the Making of Twenty-First-Century Industrial Complexes. London: Routledge. pp. 98–100. ISBN 0-415-10015-1. +Jump up ^ "Knowledge, networks and nations: scientific collaborations in the twenty-first century". Royal Society. 2011. Archived from the original on 22 June 2011. +Jump up ^ McCook, Alison. "Is peer review broken?". Reprinted from the Scientist 20(2) 26, 2006. Archived from the original on 21 June 2011. +^ Jump up to: a b "Heathrow 'needs a third runway'". BBC News. 25 June 2008. Retrieved 17 October 2008. +^ Jump up to: a b "Statistics: Top 30 World airports" (Press release). Airports Council International. July 2008. Retrieved 15 October 2008. +Jump up ^ "Transport Statistics Great Britain: 2010". Department for Transport. Archived from the original on 16 December 2010. +Jump up ^ "Major new rail lines considered". BBC News. 21 June 2008. Archived from the original on 9 October 2010. +Jump up ^ "Crossrail's giant tunnelling machines unveiled". BBC News. 2 January 2012. +Jump up ^ Leftly, Mark (29 August 2010). "Crossrail delayed to save £1bn". The Independent on Sunday (London). +^ Jump up to: a b "Size of Reporting Airports October 2009 – September 2010". Civil Aviation Authority. Retrieved 5 December 2010. +Jump up ^ "BMI being taken over by Lufthansa". BBC News. 29 October 2008. Retrieved 23 December 2009. +Jump up ^ "United Kingdom Energy Profile". U.S. Energy Information Administration. Retrieved 4 November 2010. +Jump up ^ Mason, Rowena (24 October 2009). "Let the battle begin over black gold". The Daily Telegraph (London). Retrieved 26 November 2010. +Jump up ^ Heath, Michael (26 November 2010). "RBA Says Currency Containing Prices, Rate Level 'Appropriate' in Near Term". Bloomberg (New York). Retrieved 26 November 2010. +^ Jump up to: a b c "Nuclear Power in the United Kingdom". World Nuclear Association. April 2013. Retrieved 9 April 2013. +^ Jump up to: a b c "United Kingdom – Oil". U.S. Energy Information Administration. Retrieved 4 November 2010.[dead link] +Jump up ^ "Diminishing domestic reserves, escalating imports". EDF Energy. Retrieved 9 April 2013. +^ Jump up to: a b "United Kingdom – Natural Gas". U.S. Energy Information Administration. Retrieved 4 November 2010.[dead link] +^ Jump up to: a b "United Kingdom – Quick Facts Energy Overview". U.S. Energy Information Administration. Retrieved 4 November 2010.[dead link] +Jump up ^ The Coal Authority (10 April 2006). "Coal Reserves in the United Kingdom". The Coal Authority. Archived from the original on 4 January 2009. Retrieved 5 July 2011. +Jump up ^ "England Expert predicts 'coal revolution'". BBC News. 16 October 2007. Retrieved 23 September 2008. +Jump up ^ Watts, Susan (20 March 2012). "Fracking: Concerns over gas extraction regulations". BBC News. Retrieved 9 April 2013. +Jump up ^ "Quit fracking aboot". Friends of the Earth Scotland. Retrieved 9 April 2013. +Jump up ^ "Census Geography". Office for National Statistics. 30 October 2007. Archived from the original on 4 June 2011. Retrieved 14 April 2012. +Jump up ^ "Welcome to the 2011 Census for England and Wales". Office for National Statistics. n.d. Retrieved 11 October 2008. +^ Jump up to: a b c "2011 Census: Population Estimates for the United Kingdom". Office for National Statistics. 27 March 2011. Retrieved 18 December 2012. +^ Jump up to: a b c "Annual Mid-year Population Estimates, 2010". Office for National Statistics. 2011. Retrieved 14 April 2012. +Jump up ^ Batty, David (30 December 2010). "One in six people in the UK today will live to 100, study says". The Guardian (London). +^ Jump up to: a b "2011 UK censuses". Office for National Statistics. Retrieved 18 December 2012. +Jump up ^ "Population: UK population grows to 59.6 million" (Press release). Office for National Statistics. 24 June 2004. Archived from the original on 22 July 2004. Retrieved 14 April 2012. +Jump up ^ Khan, Urmee (16 September 2008). "England is most crowded country in Europe". The Daily Telegraph (London). Retrieved 5 September 2009. +Jump up ^ Carrell, Severin (17 December 2012). "Scotland's population at record high". The Guardian. London. Retrieved 18 December 2012. +^ Jump up to: a b c "Vital Statistics: Population and Health Reference Tables (February 2014 Update): Annual Time Series Data". ONS. Retrieved 27 April 2014. +Jump up ^ Boseley, Sarah (14 July 2008). "The question: What's behind the baby boom?". The Guardian (London). p. 3. Retrieved 28 August 2009. +Jump up ^ Tables, Graphs and Maps Interface (TGM) table. Eurostat (26 February 2013). Retrieved 12 July 2013. +Jump up ^ Campbell, Denis (11 December 2005). "3.6m people in Britain are gay – official". The Observer (London). Retrieved 28 April 2013. +Jump up ^ "2011 Census - Built-up areas". ONS. Retrieved 1 July 2013. +Jump up ^ Mid-2012 Population Estimates for Settlements and Localities in Scotland General Register Office for Scotland +Jump up ^ "Belfast Metropolitan Urban Area NISRA 2005". Retrieved 28 April 2013. +Jump up ^ 2011 Census: KS201UK Ethnic group, local authorities in the United Kingdom, Accessed 21 February 2014 +Jump up ^ "Welsh people could be most ancient in UK, DNA suggests". BBC News. 19 June 2012. Retrieved 28 April 2013. +Jump up ^ Thomas, Mark G. et al. "Evidence for a segregated social structure in early Anglo-Saxon England". Proceedings of the Royal Society B: Biological Sciences 273(1601): 2651–2657. +Jump up ^ Owen, James (19 July 2005). "Review of 'The Tribes of Britain'". National Geographic (Washington DC). +Jump up ^ Oppenheimer, Stephen (October 2006). "Myths of British ancestry" at the Wayback Machine (archived 26 September 2006). Prospect (London). Retrieved 5 November 2010. +Jump up ^ Henderson, Mark (23 October 2009). "Scientist – Griffin hijacked my work to make race claim about 'British aborigines'". The Times (London). Retrieved 26 October 2009. (subscription required) +Jump up ^ Costello, Ray (2001). Black Liverpool: The Early History of Britain's Oldest Black Community 1730–1918. Liverpool: Picton Press. ISBN 1-873245-07-6. +Jump up ^ "Culture and Ethnicity Differences in Liverpool – Chinese Community". Chambré Hardman Trust. Retrieved 26 October 2009. +Jump up ^ Coleman, David; Compton, Paul; Salt, John (2002). "The demographic characteristics of immigrant populations", Council of Europe, p.505. ISBN 92-871-4974-7. +Jump up ^ Mason, Chris (30 April 2008). "'Why I left UK to return to Poland'". BBC News. +Jump up ^ "Resident population estimates by ethnic group (percentages): London". Office for National Statistics. Retrieved 23 April 2008. +Jump up ^ "Resident population estimates by ethnic group (percentages): Leicester". Office for National Statistics. Retrieved 23 April 2008. +Jump up ^ "Census 2001 – Ethnicity and religion in England and Wales". Office for National Statistics. Retrieved 23 April 2008. +Jump up ^ Loveys, Kate (22 June 2011). "One in four primary school pupils are from an ethnic minority and almost a million schoolchildren do not speak English as their first language". Daily Mail (London). Retrieved 28 June 2011. +Jump up ^ Rogers, Simon (19 May 2011). "Non-white British population reaches 9.1 million". The Guardian (London). +Jump up ^ Wallop, Harry (18 May 2011). "Population growth of last decade driven by non-white British". The Daily Telegraph (London). +Jump up ^ "Official EU languages". European Commission. 8 May 2009. Retrieved 16 October 2009. +Jump up ^ "Language Courses in New York". United Nations. 2006. Retrieved 29 November 2010. +Jump up ^ "English language – Government, citizens and rights". Directgov. Retrieved 23 August 2011. +Jump up ^ "Commonwealth Secretariat – UK". Commonwealth Secretariat. Retrieved 23 August 2011. +^ Jump up to: a b c "Languages across Europe: United Kingdom". BBC. Retrieved 4 February 2013. +Jump up ^ Booth, Robert (30 January 2013). "Polish becomes England's second language". The Guardian (London). Retrieved 4 February 2012. +Jump up ^ European Charter for Regional or Minority Languages, Strasbourg, 5.XI.1992 - http://conventions.coe.int/treaty/en/Treaties/Html/148.htm +Jump up ^ Framework Convention for the Protection of National Minorities, Strasbourg, 1.II.1995 - http://conventions.coe.int/Treaty/en/Treaties/Html/157.htm +Jump up ^ National Statistics Online – Welsh Language[dead link]. National Statistics Office. +Jump up ^ "Differences in estimates of Welsh Language Skills". Office for National Statistics. Archived from the original on 12 January 2010. Retrieved 30 December 2008. +Jump up ^ Wynn Thomas, Peter (March 2007). "Welsh today". Voices. BBC. Retrieved 5 July 2011. +Jump up ^ "Scotland's Census 2001 – Gaelic Report". General Register Office for Scotland. Retrieved 28 April 2013. +Jump up ^ "Local UK languages 'taking off'". BBC News. 12 February 2009. +Jump up ^ Edwards, John R. (2010). Minority languages and group identity: cases and categories. John Benjamins. pp. 150–158. ISBN 978-90-272-1866-7. Retrieved 12 March 2011. +Jump up ^ Koch, John T. (2006). Celtic culture: a historical encyclopedia. ABC-CLIO. p. 696. ISBN 978-1-85109-440-0. +Jump up ^ "Language Data – Scots". European Bureau for Lesser-Used Languages. Archived from the original on 23 June 2007. Retrieved 2 November 2008. +Jump up ^ "Fall in compulsory language lessons". BBC News. 4 November 2004. +Jump up ^ "The School Gate for parents in Wales". BBC. Retrieved 28 April 2013. +Jump up ^ Cannon, John, ed. (2nd edn., 2009). A Dictionary of British History. Oxford University Press. p. 144. ISBN 0-19-955037-9. +Jump up ^ Field, Clive D. (November 2009). "British religion in numbers"[dead link]. BRIN Discussion Series on Religious Statistics, Discussion Paper 001. Retrieved 3 June 2011. +Jump up ^ Yilmaz, Ihsan (2005). Muslim Laws, Politics and Society in Modern Nation States: Dynamic Legal Pluralisms in England, Turkey, and Pakistan. Aldershot: Ashgate Publishing. pp. 55–6. ISBN 0-7546-4389-1. +Jump up ^ Brown, Callum G. (2006). Religion and Society in Twentieth-Century Britain. Harlow: Pearson Education. p. 291. ISBN 0-582-47289-X. +Jump up ^ Norris, Pippa; Inglehart, Ronald (2004). Sacred and Secular: Religion and Politics Worldwide. Cambridge University Press. p. 84. ISBN 0-521-83984-X. +Jump up ^ Fergusson, David (2004). Church, State and Civil Society. Cambridge University Press. p. 94. ISBN 0-521-52959-X. +Jump up ^ "UK Census 2001". National Office for Statistics. Archived from the original on 12 March 2007. Retrieved 22 April 2007. +Jump up ^ "Religious Populations". Office for National Statistics. 11 October 2004. Archived from the original on 6 June 2011. +Jump up ^ "United Kingdom: New Report Finds Only One in 10 Attend Church". News.adventist.org. 4 April 2007. Retrieved 12 September 2010. +Jump up ^ Philby, Charlotte (12 December 2012). "Less religious and more ethnically diverse: Census reveals a picture of Britain today". The Independent (London). +Jump up ^ The History of the Church of England. The Church of England. Retrieved 23 November 2008. +Jump up ^ "Queen and Church of England". British Monarchy Media Centre. Archived from the original on 8 October 2006. Retrieved 5 June 2010. +Jump up ^ "Queen and the Church". The British Monarchy (Official Website). Archived from the original on 7 June 2011. +Jump up ^ "How we are organised". Church of Scotland. Archived from the original on 7 June 2011. +Jump up ^ Weller, Paul (2005). Time for a Change: Reconfiguring Religion, State, and Society. London: Continuum. pp. 79–80. ISBN 0567084876. +Jump up ^ Peach, Ceri, "United Kingdom, a major transformation of the religious landscape", in H. Knippenberg. ed. (2005). The Changing Religious Landscape of Europe. Amsterdam: Het Spinhuis. pp. 44–58. ISBN 90-5589-248-3. +Jump up ^ Richards, Eric (2004). Britannia's children: Emigration from England, Scotland, Wales and Ireland since 1600. London: Hambledon, p. 143. ISBN 978-1-85285-441-6. +Jump up ^ Gibney, Matthew J.; Hansen, Randall (2005). Immigration and asylum: from 1900 to the present, ABC-CLIO, p. 630. ISBN 1-57607-796-9 +Jump up ^ "Short history of immigration". BBC. 2005. Retrieved 28 August 2010. +Jump up ^ Rogers, Simon (11 December 2012). "Census 2011 mapped and charted: England & Wales in religion, immigration and race". London: Guardian. Retrieved 11 December 2012. +Jump up ^ 6.5% of the EU population are foreigners and 9.4% are born abroad, Eurostat, Katya Vasileva, 34/2011. +Jump up ^ Muenz, Rainer (June 2006). "Europe: Population and Migration in 2005". Migration Policy Institute. Retrieved 2 April 2007. +Jump up ^ "Immigration and births to non-British mothers pushes British population to record high". London Evening Standard. 21 August 2008. +Jump up ^ Doughty, Steve; Slack, James (3 June 2008). "Third World migrants behind our 2.3m population boom". Daily Mail (London). +Jump up ^ Bentham, Martin (20 October 2008). "Tories call for tougher control of immigration". London Evening Standard. +Jump up ^ "Minister rejects migrant cap plan". BBC News. 8 September 2008. Retrieved 26 April 2011. +Jump up ^ Johnston, Philip (5 January 2007). "Immigration 'far higher' than figures say". The Daily Telegraph (London). Retrieved 20 April 2007. +Jump up ^ Travis, Alan (25 August 2011). "UK net migration rises 21%". The Guardian (London). +^ Jump up to: a b "Migration Statistics Quarterly Report May 2012". Office for National Statistics. 24 May 2012. +Jump up ^ "Migration to UK more than double government target". BBC News. 24 May 2012. +^ Jump up to: a b "Citizenship". Home Office. August 2011. Retrieved 24 October 2011.[dead link] +Jump up ^ Bamber, David (20 December 2000). "Migrant squad to operate in France". The Daily Telegraph (London). +Jump up ^ "Settlement". Home Office. August 2011. Retrieved 24 October 2011.[dead link] +Jump up ^ "Births in England and Wales by parents' country of birth, 2011". Office for National Statistics. 30 August 2012. Retrieved 28 April 2013. +Jump up ^ "Right of Union citizens and their family members to move and reside freely within the territory of the Member States". European Commission. Retrieved 28 April 2013. +Jump up ^ Doward, Jamie; Temko, Ned (23 September 2007). "Home Office shuts the door on Bulgaria and Romania". The Observer (London). p. 2. Retrieved 23 August 2008. +Jump up ^ Sumption, Madeleine; Somerville, Will (January 2010). The UK's new Europeans: Progress and challenges five years after accession. Policy Report (London: Equality and Human Rights Commission). p. 13. ISBN 978-1-84206-252-4. Retrieved 19 January 2010. +Jump up ^ Doward, Jamie; Rogers, Sam (17 January 2010). "Young, self-reliant, educated: portrait of UK's eastern European migrants". The Observer (London). Retrieved 19 January 2010. +Jump up ^ Hopkirk, Elizabeth (20 October 2008). "Packing up for home: Poles hit by UK's economic downturn". London Evening Standard. +Jump up ^ "Migrants to UK 'returning home'". BBC News. 8 September 2009. Retrieved 8 September 2009. +Jump up ^ "UK sees shift in migration trend". BBC News. 27 May 2010. Retrieved 28 May 2010. +Jump up ^ "Fresh Talent: Working in Scotland". London: UK Border Agency. Retrieved 30 October 2010. +Jump up ^ Boxell, James (28 June 2010). "Tories begin consultation on cap for migrants". Financial Times (London). Retrieved 17 September 2010. +Jump up ^ "Vince Cable: Migrant cap is hurting economy". The Guardian (London). Press Association. 17 September 2010. Retrieved 17 September 2010. +Jump up ^ Richards (2004), pp. 6–7. +^ Jump up to: a b Sriskandarajah, Dhananjayan; Drew, Catherine (11 December 2006). "Brits Abroad: Mapping the scale and nature of British emigration". Institute for Public Policy Research. Retrieved 20 January 2007. +Jump up ^ "Brits Abroad: world overview". BBC. n.d. Retrieved 20 April 2007. +Jump up ^ Casciani, Dominic (11 December 2006). "5.5 m Britons 'opt to live abroad'". BBC News. Retrieved 20 April 2007. +Jump up ^ "Brits Abroad: Country-by-country". BBC News. 11 December 2006. +Jump up ^ "Local Authorities". Department for Children, Schools and Families. Retrieved 21 December 2008. +Jump up ^ Gordon, J.C.B. (1981). Verbal Deficit: A Critique. London: Croom Helm. p. 44 note 18. ISBN 978-0-85664-990-5. +Jump up ^ Section 8 ('Duty of local education authorities to secure provision of primary and secondary schools'), Sections 35–40 ('Compulsory attendance at Primary and Secondary Schools') and Section 61 ('Prohibition of fees in schools maintained by local education authorities ...'), Education Act 1944. +Jump up ^ "England's pupils in global top 10". BBC News. 10 December 2008. +Jump up ^ "More state pupils in universities". BBC News. 19 July 2007. +Jump up ^ MacLeod, Donald (9 November 2007). "Private school pupil numbers in decline". The Guardian (London). Retrieved 31 March 2010. +Jump up ^ Frankel, Hannah (3 September 2010). "Is Oxbridge still a preserve of the posh?". TES (London). Retrieved 9 April 2013. +Jump up ^ "World's top 100 universities 2013: their reputations ranked by Times Higher Education". The Guardian (London). 2013. Retrieved 23 October 2014. +Jump up ^ Davenport, F.; Beech, C.; Downs, T.; Hannigan, D. (2006). Ireland. Lonely Planet, 7th edn. ISBN 1-74059-968-3. p. 564. +Jump up ^ "About SQA". Scottish Qualifications Authority. 10 April 2013. Retrieved 28 April 2013. +Jump up ^ "About Learning and Teaching Scotland". Learning and Teaching Scotland. Retrieved 28 April 2013. +Jump up ^ "Brain drain in reverse". Scotland Online Gateway. July 2002. Archived from the original on 4 December 2007. +Jump up ^ "Increase in private school intake". BBC News. 17 April 2007. +Jump up ^ "MSPs vote to scrap endowment fee". BBC News. 28 February 2008. +Jump up ^ What will your child learn?[dead link] The Welsh Assembly Government. Retrieved 22 January 2010. +Jump up ^ CCEA. "About Us – What we do". Council for the Curriculum Examinations & Assessment. Retrieved 28 April 2013. +Jump up ^ Elitist Britain?, Social Mobility and Child Poverty Commission, 28 August 2014 +Jump up ^ Arnett, George (28 August 2014). "Elitism in Britain - breakdown by profession". The Guardian: Datablog. +Jump up ^ Haden, Angela; Campanini, Barbara, eds. (2000). The world health report 2000 – Health systems: improving performance. Geneva: World Health Organisation. ISBN 92-4-156198-X. Retrieved 5 July 2011. +Jump up ^ World Health Organization. "Measuring overall health system performance for 191 countries". New York University. Retrieved 5 July 2011. +Jump up ^ "'Huge contrasts' in devolved NHS". BBC News. 28 August 2008. +Jump up ^ Triggle, Nick (2 January 2008). "NHS now four different systems". BBC News. +Jump up ^ Fisher, Peter. "The NHS from Thatcher to Blair". NHS Consultants Association (International Association of Health Policy). The Budget ... was even more generous to the NHS than had been expected amounting to an annual rise of 7.4% above the rate of inflation for the next 5 years. This would take us to 9.4% of GDP spent on health ie around EU average. +Jump up ^ "OECD Health Data 2009 – How Does the United Kingdom Compare". Paris: Organisation for Economic Co-operation and Development. Retrieved 28 April 2013.[dead link] +Jump up ^ "The cultural superpower: British cultural projection abroad". Journal of the British Politics Society, Norway. Volume 6. No. 1. Winter 2011 +Jump up ^ Sheridan, Greg (15 May 2010). "Cameron has chance to make UK great again". The Australian (Sydney). Retrieved 20 May 2012. +Jump up ^ Goldfarb, Jeffrey (10 May 2006). "Bookish Britain overtakes America as top publisher". RedOrbit (Texas). Reuters. +Jump up ^ "William Shakespeare (English author)". Britannica Online encyclopedia. Retrieved 26 February 2006. +Jump up ^ MSN Encarta Encyclopedia article on Shakespeare. Archived from the original on 9 February 2006. Retrieved 26 February 2006. +Jump up ^ William Shakespeare. Columbia Electronic Encyclopedia. Retrieved 26 February 2006. +Jump up ^ "Mystery of Christie's success is solved". The Daily Telegraph (London). 19 December 2005. Retrieved 14 November 2010. +Jump up ^ "All-Time Essential Comics". IGN. Retrieved 15 August 2013. +Jump up ^ Johnston, Rich."Before Watchmen To Double Up For Hardcover Collections". Bleeding Cool. 10 December 2012. Retrieved 15 August 2013. +Jump up ^ "Edinburgh, UK appointed first UNESCO City of Literature". Unesco. 2004. Retrieved 28 April 2013.[dead link] +Jump up ^ "Early Welsh poetry". BBC Wales. Retrieved 29 December 2010. +Jump up ^ Lang, Andrew (2003) [1913]. History of English Literature from Beowulf to Swinburne. Holicong, PA: Wildside Press. p. 42. ISBN 978-0-8095-3229-2. +Jump up ^ "Dafydd ap Gwilym". Academi website. Academi. 2011. Retrieved 3 January 2011. Dafydd ap Gwilym is widely regarded as one of the greatest Welsh poets of all time, and amongst the leading European poets of the Middle Ages. +Jump up ^ True birthplace of Wales's literary hero. BBC News. Retrieved 28 April 2012 +Jump up ^ Kate Roberts: Biography at the Wayback Machine. BBC Wales. Retrieved 28 April 2012 +Jump up ^ Swift, Jonathan; Fox, Christopher (1995). Gulliver's travels: complete, authoritative text with biographical and historical contexts, critical history, and essays from five contemporary critical perspectives. Basingstoke: Macmillan. p. 10. ISBN 978-0-333-63438-7. +Jump up ^ "Bram Stoker." (PDF). The New York Times. 23 April 1912. Retrieved 1 January 2011. +^ Jump up to: a b "1960–1969". EMI Group. Retrieved 31 May 2008. +^ Jump up to: a b "Paul At Fifty". Time (New York). 8 June 1992. +^ Jump up to: a b Most Successful Group The Guinness Book of Records 1999, p. 230. Retrieved 19 March 2011. +Jump up ^ "British Citizen by Act of Parliament: George Frideric Handel". UK Parliament. 20 July 2009. Retrieved 11 September 2009.[dead link] +Jump up ^ Andrews, John (14 April 2006). "Handel all'inglese". Playbill (New York). Retrieved 11 September 2009. +Jump up ^ Citron, Stephen (2001). Sondheim and Lloyd-Webber: The new musical. London: Chatto & Windus. ISBN 978-1-85619-273-6. +Jump up ^ "Beatles a big hit with downloads". Belfast Telegraph. 25 November 2010. Retrieved 16 May 2011. +Jump up ^ "British rock legends get their own music title for PlayStation3 and PlayStation2" (Press release). EMI. 2 February 2009. +Jump up ^ Khan, Urmee (17 July 2008). "Sir Elton John honoured in Ben and Jerry ice cream". The Daily Telegraph (London). +Jump up ^ Alleyne, Richard (19 April 2008). "Rock group Led Zeppelin to reunite". The Daily Telegraph (London). Retrieved 31 March 2010. +Jump up ^ Fresco, Adam (11 July 2006). "Pink Floyd founder Syd Barrett dies at home". The Times (London). Retrieved 31 March 2010. (subscription required) +Jump up ^ Holton, Kate (17 January 2008). "Rolling Stones sign Universal album deal". Reuters. Retrieved 26 October 2008. +Jump up ^ Walker, Tim (12 May 2008). "Jive talkin': Why Robin Gibb wants more respect for the Bee Gees". The Independent (London). Retrieved 26 October 2008. +Jump up ^ "Brit awards winners list 2012: every winner since 1977". The Guardian (London). Retrieved 28 February 2012. +Jump up ^ Corner, Lewis (16 February 2012). "Adele, Coldplay biggest-selling UK artists worldwide in 2011". Digital Spy. Retrieved 22 March 2012. +Jump up ^ Hughes, Mark (14 January 2008). "A tale of two cities of culture: Liverpool vs Stavanger". The Independent (London). Retrieved 2 August 2009. +Jump up ^ "Glasgow gets city of music honour". BBC News. 20 August 2008. Retrieved 2 August 2009. +Jump up ^ Bayley, Stephen (24 April 2010). "The startling success of Tate Modern". The Times (London). Retrieved 19 January 2011. (subscription required) +Jump up ^ "Vertigo is named 'greatest film of all time'". BBC News. 2 August 2012. Retrieved 18 August 2012. +Jump up ^ "The Directors' Top Ten Directors". British Film Institute. Archived from the original on 27 May 2012. +Jump up ^ "Chaplin, Charles (1889–1977)". British Film Institute. Retrieved 25 January 2011. +Jump up ^ "Powell, Michael (1905–1990)". British Film Institute. Retrieved 25 January 2011. +Jump up ^ "Reed, Carol (1906–1976)". British Film Institute. Retrieved 25 January 2011. +Jump up ^ "Scott, Sir Ridley (1937–)". British Film Institute. Retrieved 25 January 2011. +Jump up ^ "Andrews, Julie (1935–)". British Film Institute. Retrieved 11 December 2010. +Jump up ^ "Burton, Richard (1925–1984)". British Film Institute. Retrieved 11 December 2010. +Jump up ^ "Caine, Michael (1933–)". British Film Institute. Retrieved 11 December 2010. +Jump up ^ "Chaplin, Charles (1889–1977)". British Film Institute. Retrieved 11 December 2010. +Jump up ^ "Connery, Sean (1930–)". British Film Institute. Retrieved 11 December 2010. +Jump up ^ "Leigh, Vivien (1913–1967)". British Film Institute. Retrieved 11 December 2010. +Jump up ^ "Niven, David (1910–1983)". British Film Institute. Retrieved 11 December 2010. +Jump up ^ "Olivier, Laurence (1907–1989)". British Film Institute. Retrieved 11 December 2010. +Jump up ^ "Sellers, Peter (1925–1980)". British Film Institute. Retrieved 11 December 2010. +Jump up ^ "Winslet, Kate (1975–)". British Film Institute. Retrieved 11 December 2010. +Jump up ^ "Daniel Day-Lewis makes Oscar history with third award"'. BBC News. Retrieved 15 August 2013 +Jump up ^ "Harry Potter becomes highest-grossing film franchise". The Guardian (London). 11 September 2007. Retrieved 2 November 2010. +Jump up ^ "History of Ealing Studios". Ealing Studios. Retrieved 5 June 2010. +^ Jump up to: a b "UK film – the vital statistics". UK Film Council. Retrieved 22 October 2010.[dead link] +Jump up ^ "The BFI 100". British Film Institute. 6 September 2006. Archived from the original on 1 April 2011. +Jump up ^ "Baftas fuel Oscars race". BBC News. 26 February 2001. Retrieved 14 February 2011. +^ Jump up to: a b "BBC: World's largest broadcaster & Most trusted media brand". Media Newsline. Archived from the original on 5 October 2010. Retrieved 23 September 2010. +^ Jump up to: a b "Digital licence". Prospect. Retrieved 23 September 2010. +^ Jump up to: a b "About the BBC – What is the BBC". BBC Online. Retrieved 23 September 2010. +Jump up ^ Newswire7 (13 August 2009). "BBC: World's largest broadcaster & Most trusted media brand". Media Newsline. Archived from the original on 17 June 2011. +Jump up ^ "TV Licence Fee: facts & figures". BBC Press Office. April 2010. Archived from the original on 17 June 2011. +Jump up ^ "Publications & Policies: The History of ITV". ITV.com. Archived from the original on 17 June 2011. +Jump up ^ "Publishing". News Corporation. Archived from the original on 17 June 2011. +Jump up ^ "Direct Broadcast Satellite Television". News Corporation. Archived from the original on 17 June 2011. +Jump up ^ William, D. (2010). UK Cities: A Look at Life and Major Cities in England, Scotland, Wales and Northern Ireland. Eastbourne: Gardners Books. ISBN 978-9987-16-021-1, pp. 22, 46, 109 and 145. +Jump up ^ "Publishing". Department of Culture, Media and Sport. Archived from the original on 17 June 2011. +Jump up ^ Ofcom "Communication Market Report 2010", 19 August 2010, pp. 97, 164 and 191 +Jump up ^ "Social Trends: Lifestyles and social participation". Office for National Statistics. 16 February 2010. Archived from the original on 17 June 2011. +Jump up ^ "Top 20 countries with the highest number of Internet users". Internet World Stats. Archived from the original on 17 June 2011. +Jump up ^ Fieser, James, ed. (2000). A bibliography of Scottish common sense philosophy: Sources and origins. Bristol: Thoemmes Press. Retrieved 17 December 2010. +Jump up ^ Palmer, Michael (1999). Moral Problems in Medicine: A Practical Coursebook. Cambridge: Lutterworth Press. p. 66. ISBN 978-0-7188-2978-0. +Jump up ^ Scarre, Geoffrey (1995). Utilitarianism. London: Routledge. p. 82. ISBN 978-0-415-12197-2. +Jump up ^ Gysin, Christian (9 March 2007). "Wembley kick-off: Stadium is ready and England play first game in fortnight". Daily Mail (London). Retrieved 19 March 2007. +Jump up ^ "Opening ceremony of the games of the XXX Olympiad". Olympic.org. Retrieved 30 November 2013 +Jump up ^ "Unparalleled Sporting History" . Reuters. Retrieved 30 November 2013 +Jump up ^ "Rugby Union 'Britain's Second Most Popular Sport'". Ipsos-Mori. 22 December 2003. Retrieved 28 April 2013. +Jump up ^ Ebner, Sarah (2 July 2013). "History and time are key to power of football, says Premier League chief". The Times (London). Retrieved 30 November 2013. +Jump up ^ Mitchell, Paul (November 2005). "The first international football match". BBC Sport Scotland. Retrieved 15 December 2013. +Jump up ^ "Why is there no GB Olympics football team?". BBC Sport. 5 August 2008. Retrieved 31 December 2010. +Jump up ^ "Blatter against British 2012 team". BBC News. 9 March 2008. Retrieved 2 April 2008. +Jump up ^ "About ECB". England and Wales Cricket Board. n.d. Retrieved 28 April 2013. +Jump up ^ McLaughlin, Martyn (4 August 2009). "Howzat happen? England fields a Gaelic-speaking Scotsman in Ashes". The Scotsman (Edinburgh). Retrieved 30 December 2010. +Jump up ^ "Uncapped Joyce wins Ashes call up". BBC Sport. 15 November 2006. Retrieved 30 December 2010. +Jump up ^ "Glamorgan". BBC South East Wales. August 2009. Retrieved 30 December 2010. +Jump up ^ Ardener, Shirley (2007). Professional identities: policy and practice in business and bureaucracy. New York: Berghahn. p. 27. ISBN 978-1-84545-054-0. +Jump up ^ "Official Website of Rugby League World Cup 2008". Archived from the original on 16 October 2007. +Jump up ^ Louw, Jaco; Nesbit, Derrick (2008). The Girlfriends Guide to Rugby. Johannesburg: South Publishers. ISBN 978-0-620-39541-0. +Jump up ^ "Triple Crown". RBS 6 Nations. Retrieved 6 March 2011. +Jump up ^ "Tracking the Field". Ipsos MORI. Archived from the original on 5 February 2009. Retrieved 17 October 2008. +Jump up ^ "Links plays into the record books". BBC News. 17 March 2009. +Jump up ^ Chowdhury, Saj (22 January 2007). "China in Ding's hands". BBC Sport. Retrieved 2 January 2011. +Jump up ^ "Lawn Tennis and Major T.Gem". The Birmingham Civic Society. Archived from the original on 18 August 2011. Retrieved 31 December 2010. +Jump up ^ Gould, Joe (10 April 2007). "The ancient Irish sport of hurling catches on in America". Columbia News Service (Columbia Journalism School). Retrieved 17 May 2011. +Jump up ^ "Shinty". Scottishsport.co.uk. Retrieved 28 April 2013. +Jump up ^ "Welsh dragon call for Union flag". BBC News. 27 November 2007. Retrieved 17 October 2008. +Jump up ^ "Britannia on British Coins". Chard. Retrieved 25 June 2006. +Jump up ^ Baker, Steve (2001). Picturing the Beast. University of Illinois Press. p. 52. ISBN 0-252-07030-5. +Further reading +Hitchens, Peter (2000). The Abolition of Britain: from Winston Churchill to Princess Diana. Second ed. San Francisco, Calif.: Encounter Books. xi, 332 p. ISBN 1-893554-18-X. +Lambert, Richard S. (1964). The Great Heritage: a History of Britain for Canadians. House of Grant, 1964 (and earlier editions and/or printings). +External links +Find more about +United Kingdom +at Wikipedia's sister projects +Search Wiktionary Definitions from Wiktionary +Search Commons Media from Commons +Search Wikinews News stories from Wikinews +Search Wikiquote Quotations from Wikiquote +Search Wikisource Source texts from Wikisource +Search Wikibooks Textbooks from Wikibooks +Search Wikivoyage Travel guide from Wikivoyage +Search Wikiversity Learning resources from Wikiversity +Government +Official website of HM Government +Official website of the British Monarchy +Official Yearbook of the United Kingdom statistics +The official site of the British Prime Minister's Office +General information +United Kingdom from the BBC News +United Kingdom entry at The World Factbook +United Kingdom from UCB Libraries GovPubs +United Kingdom at DMOZ +United Kingdom Encyclopædia Britannica entry +United Kingdom from the OECD +United Kingdom at the EU + Wikimedia Atlas of United Kingdom + Geographic data related to United Kingdom at OpenStreetMap +Key Development Forecasts for the United Kingdom from International Futures +Travel +Official tourist guide to Britain +[hide] v t e +United Kingdom topics +History +Chronology +Formation Georgian era Victorian era Edwardian era World War I Interwar World War II UK since 1945 (Postwar Britain) +By topic +Economic Empire Maritime Military +Geography +Administrative +Countries of the United Kingdom Crown dependencies Overseas territories City status Towns Former colonies +Physical +British Isles terminology Great Britain Geology Northern Ireland Lakes and lochs Mountains Rivers Volcanoes +Resources +Energy/Renewable energy Biodiesel Coal Geothermal Hydraulic frac. Hydroelectricity Marine North Sea oil Solar Wind Food Agriculture Fishing English Scottish Hunting Materials Flora Forestry Mining +Politics +Constitution Courts Elections Foreign relations Judiciary Law Law enforcement Legislation Monarchy monarchs Nationality Parliament House of Commons House of Lords Political parties +Government +Cabinet list Civil service Departments Prime Minister list +Military +Royal Navy Army Royal Air Force Weapons of mass destruction +Economy +Banks Bank of England Budget Economic geography Pound (currency) Stock Exchange Taxation Telecommunications Tourism Transport +Society +Affordability of housing Crime Demography Drug policy Education Ethnic groups Health care Immigration Languages Poverty Food banks Prostitution Public holidays Social care Social structure +Culture +Art Cinema Cuisine Identity Literature Media television Music Religion Sport Symbols Theatre +[show] +Countries of the United Kingdom +Outline Index +Book Category Portal WikiProject +[show] +Gnome-globe.svg Geographic locale +[show] v t e +Member states of the European Union +[show] +International organisations +[show] v t e +English-speaking world +[show] v t e +National personifications +Coordinates: 55°N 3°W +Categories: United KingdomBritish IslandsConstitutional monarchiesCountries in EuropeEnglish-speaking countries and territoriesG20 nationsG7 nationsG8 nationsIsland countriesLiberal democraciesMember states of NATOMember states of the Commonwealth of NationsMember states of the Council of EuropeMember states of the European UnionMember states of the Union for the MediterraneanMember states of the United NationsNorthern EuropeWestern Europe +Navigation menu +Create accountLog inArticleTalkReadView sourceView history + +Main page +Contents +Featured content +Current events +Random article +Donate to Wikipedia +Wikimedia Shop +Interaction +Help +About Wikipedia +Community portal +Recent changes +Contact page +Tools +What links here +Related changes +Upload file +Special pages +Permanent link +Page information +Wikidata item +Cite this page +Print/export +Create a book +Download as PDF +Printable version +Languages +Адыгэбзэ +Afrikaans +Akan +Alemannisch +አማርኛ +Ænglisc +Аҧсшәа +العربية +Aragonés +ܐܪܡܝܐ +Armãneashti +Arpetan +Asturianu +Avañe'ẽ +Авар +Azərbaycanca +বাংলা +Bahasa Banjar +Bân-lâm-gú +Башҡортса +Беларуская +Беларуская (тарашкевіца)‎ +भोजपुरी +Bikol Central +Bislama +Български +Boarisch +བོད་ཡིག +Bosanski +Brezhoneg +Буряад +Català +Чӑвашла +Cebuano +Čeština +Chavacano de Zamboanga +ChiShona +Corsu +Cymraeg +Dansk +Deutsch +ދިވެހިބަސް +Diné bizaad +Dolnoserbski +ཇོང་ཁ +Eesti +Ελληνικά +Emiliàn e rumagnòl +Español +Esperanto +Estremeñu +Euskara +فارسی +Fiji Hindi +Føroyskt +Français +Frysk +Furlan +Gaeilge +Gaelg +Gagauz +Gàidhlig +Galego +贛語 +ગુજરાતી +客家語/Hak-kâ-ngî +Хальмг +한국어 +Hausa +Hawaii +Հայերեն +हिन्दी +Hornjoserbsce +Hrvatski +Ido +Igbo +Ilokano +বিষ্ণুপ্রিয়া মণিপুরী +Bahasa Indonesia +Interlingua +Interlingue +Ирон +IsiZulu +Íslenska +Italiano +עברית +Basa Jawa +Kalaallisut +ಕನ್ನಡ +Kapampangan +Къарачай-малкъар +ქართული +Kaszëbsczi +Қазақша +Kernowek +Kinyarwanda +Kiswahili +Коми +Kongo +Kreyòl ayisyen +Kurdî +Кыргызча +Кырык мары +Ladino +Лезги +ລາວ +Latgaļu +Latina +Latviešu +Lëtzebuergesch +Lietuvių +Ligure +Limburgs +Lingála +Lojban +Lumbaart +Magyar +Македонски +Malagasy +മലയാളം +Malti +Māori +मराठी +მარგალური +مصرى +مازِرونی +Bahasa Melayu +Mìng-dĕ̤ng-ngṳ̄ +Mirandés +Монгол +မြန်မာဘာသာ +Nāhuatl +Dorerin Naoero +Nederlands +Nedersaksies +नेपाली +नेपाल भाषा +日本語 +Napulitano +Нохчийн +Nordfriisk +Norfuk / Pitkern +Norsk bokmål +Norsk nynorsk +Nouormand +Novial +Occitan +Олык марий +ଓଡ଼ିଆ +Oromoo +Oʻzbekcha +ਪੰਜਾਬੀ +Pangasinan +پنجابی +Papiamentu +پښتو +Перем Коми +ភាសាខ្មែរ +Picard +Piemontèis +Tok Pisin +Plattdüütsch +Polski +Ποντιακά +Português +Qırımtatarca +Reo tahiti +Ripoarisch +Română +Romani +Rumantsch +Runa Simi +Русиньскый +Русский +Саха тыла +Sámegiella +संस्कृतम् +Sardu +Scots +Seeltersk +Shqip +Sicilianu +සිංහල +Simple English +SiSwati +Slovenčina +Slovenščina +Словѣньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ +Ślůnski +Soomaaliga +کوردی +Sranantongo +Српски / srpski +Srpskohrvatski / српскохрватски +Basa Sunda +Suomi +Svenska +Tagalog +தமிழ் +Taqbaylit +Tarandíne +Татарча/tatarça +తెలుగు +Tetun +ไทย +Тоҷикӣ +ᏣᎳᎩ +Tsetsêhestâhese +Türkçe +Twi +Удмурт +ᨅᨔ ᨕᨘᨁᨗ +Українська +اردو +ئۇيغۇرچە / Uyghurche +Vahcuengh +Vèneto +Vepsän kel’ +Tiếng Việt +Volapük +Võro +Walon +文言 +West-Vlams +Winaray +Wolof +吴语 +ייִדיש +Yorùbá +粵語 +Zazaki +Zeêuws +Žemaitėška +中文 +Edit links +This page was last modified on 22 November 2014 at 11:19. +Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Terms of Use and Privacy Policy. Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc., a non-profit organization. +Privacy policyAbout WikipediaDisclaimersContact WikipediaDevelopersMobile viewWikimedia Foundation Powered by MediaWiki + + +World Trade Organization +From Wikipedia, the free encyclopedia +"WTO" redirects here. For other uses, see WTO (disambiguation). +World Trade Organization (English) +Organisation mondiale du commerce (French) +Organización Mundial del Comercio (Spanish) +World Trade Organization (logo and wordmark).svg +Official logo of WTO +WTO members and observers.svg + Members + Members, dually represented by the EU + Observers + Non-members +Abbreviation WTO +Formation 1 January 1995; 19 years ago +Type International trade organization +Purpose Liberalize international trade +Headquarters Centre William Rappard, Geneva, Switzerland +Coordinates 46.12°N 6.09°ECoordinates: 46.12°N 6.09°E +Region served Worldwide +Membership 160 member states[1] +Official language English, French, Spanish[2] +Director-General Roberto Azevêdo +Budget 196 million Swiss francs (approx. 209 million US$) in 2011.[3] +Staff 640[4] +Website www.wto.org +The World Trade Organization (WTO) is an organization that intends to supervise and liberalize international trade. The organization officially commenced on 1 January 1995 under the Marrakech Agreement, replacing the General Agreement on Tariffs and Trade (GATT), which commenced in 1948.[5] The organization deals with regulation of trade between participating countries by providing a framework for negotiating and formalizing trade agreements and a dispute resolution process aimed at enforcing participants' adherence to WTO agreements, which are signed by representatives of member governments[6]:fol.9–10 and ratified by their parliaments.[7] Most of the issues that the WTO focuses on derive from previous trade negotiations, especially from the Uruguay Round (1986–1994). +The organization is attempting to complete negotiations on the Doha Development Round, which was launched in 2001 with an explicit focus on addressing the needs of developing countries. As of June 2012, the future of the Doha Round remained uncertain: the work programme lists 21 subjects in which the original deadline of 1 January 2005 was missed, and the round is still incomplete.[8] The conflict between free trade on industrial goods and services but retention of protectionism on farm subsidies to domestic agricultural sector (requested by developed countries) and the substantiation of the international liberalization of fair trade on agricultural products (requested by developing countries) remain the major obstacles. These points of contention have hindered any progress to launch new WTO negotiations beyond the Doha Development Round. As a result of this impasse, there has been an increasing number of bilateral free trade agreements signed.[9] As of July 2012, there were various negotiation groups in the WTO system for the current agricultural trade negotiation which is in the condition of stalemate.[10] +WTO's current Director-General is Roberto Azevêdo,[11][12] who leads a staff of over 600 people in Geneva, Switzerland.[13] A trade facilitation agreement known as the Bali Package was reached by all members on 7 December 2013, the first comprehensive agreement in the organization's history.[14][15] +Contents [hide] +1 History +1.1 GATT rounds of negotiations +1.1.1 From Geneva to Tokyo +1.1.2 Uruguay Round +1.2 Ministerial conferences +1.3 Doha Round (Doha Agenda) +2 Functions +3 Principles of the trading system +4 Organizational structure +5 Decision-making +6 Dispute settlement +7 Accession and membership +7.1 Accession process +7.2 Members and observers +8 Agreements +9 Office of director-general +9.1 List of directors-general +10 See also +11 Notes and references +12 External links +History + +The economists Harry White (left) and John Maynard Keynes at the Bretton Woods Conference. Both had been strong advocates of a central-controlled international trade environment and recommended the establishment of three institutions: the IMF (for fiscal and monetary issues); the World Bank (for financial and structural issues); and the ITO (for international economic cooperation).[16] +The WTO's predecessor, the General Agreement on Tariffs and Trade (GATT), was established after World War II in the wake of other new multilateral institutions dedicated to international economic cooperation – notably the Bretton Woods institutions known as the World Bank and the International Monetary Fund. A comparable international institution for trade, named the International Trade Organization was successfully negotiated. The ITO was to be a United Nations specialized agency and would address not only trade barriers but other issues indirectly related to trade, including employment, investment, restrictive business practices, and commodity agreements. But the ITO treaty was not approved by the U.S. and a few other signatories and never went into effect.[17][18][19] +In the absence of an international organization for trade, the GATT would over the years "transform itself" into a de facto international organization.[20] +GATT rounds of negotiations +See also: General Agreement on Tariffs and Trade +The GATT was the only multilateral instrument governing international trade from 1946 until the WTO was established on 1 January 1995.[21] Despite attempts in the mid-1950s and 1960s to create some form of institutional mechanism for international trade, the GATT continued to operate for almost half a century as a semi-institutionalized multilateral treaty regime on a provisional basis.[22] +From Geneva to Tokyo +Seven rounds of negotiations occurred under GATT. The first real GATT trade rounds concentrated on further reducing tariffs. Then, the Kennedy Round in the mid-sixties brought about a GATT anti-dumping Agreement and a section on development. The Tokyo Round during the seventies was the first major attempt to tackle trade barriers that do not take the form of tariffs, and to improve the system, adopting a series of agreements on non-tariff barriers, which in some cases interpreted existing GATT rules, and in others broke entirely new ground. Because these plurilateral agreements were not accepted by the full GATT membership, they were often informally called "codes". Several of these codes were amended in the Uruguay Round, and turned into multilateral commitments accepted by all WTO members. Only four remained plurilateral (those on government procurement, bovine meat, civil aircraft and dairy products), but in 1997 WTO members agreed to terminate the bovine meat and dairy agreements, leaving only two.[21] +Uruguay Round +Main article: Uruguay Round + +During the Doha Round, the US government blamed Brazil and India for being inflexible and the EU for impeding agricultural imports.[23] The then-President of Brazil, Luiz Inácio Lula da Silva (above right), responded to the criticisms by arguing that progress would only be achieved if the richest countries (especially the US and countries in the EU) made deeper cuts in agricultural subsidies and further opened their markets for agricultural goods.[24] +Well before GATT's 40th anniversary, its members concluded that the GATT system was straining to adapt to a new globalizing world economy.[25][26] In response to the problems identified in the 1982 Ministerial Declaration (structural deficiencies, spill-over impacts of certain countries' policies on world trade GATT could not manage etc.), the eighth GATT round – known as the Uruguay Round – was launched in September 1986, in Punta del Este, Uruguay.[25] +It was the biggest negotiating mandate on trade ever agreed: the talks were going to extend the trading system into several new areas, notably trade in services and intellectual property, and to reform trade in the sensitive sectors of agriculture and textiles; all the original GATT articles were up for review.[26] The Final Act concluding the Uruguay Round and officially establishing the WTO regime was signed 15 April 1994, during the ministerial meeting at Marrakesh, Morocco, and hence is known as the Marrakesh Agreement.[27] +The GATT still exists as the WTO's umbrella treaty for trade in goods, updated as a result of the Uruguay Round negotiations (a distinction is made between GATT 1994, the updated parts of GATT, and GATT 1947, the original agreement which is still the heart of GATT 1994).[25] GATT 1994 is not however the only legally binding agreement included via the Final Act at Marrakesh; a long list of about 60 agreements, annexes, decisions and understandings was adopted. The agreements fall into a structure with six main parts: +The Agreement Establishing the WTO +Goods and investment – the Multilateral Agreements on Trade in Goods including the GATT 1994 and the Trade Related Investment Measures (TRIMS) +Services — the General Agreement on Trade in Services +Intellectual property – the Agreement on Trade-Related Aspects of Intellectual Property Rights (TRIPS) +Dispute settlement (DSU) +Reviews of governments' trade policies (TPRM)[28] +In terms of the WTO's principle relating to tariff "ceiling-binding" (No. 3), the Uruguay Round has been successful in increasing binding commitments by both developed and developing countries, as may be seen in the percentages of tariffs bound before and after the 1986–1994 talks.[29] +Ministerial conferences + +The World Trade Organization Ministerial Conference of 1998, in the Palace of Nations (Geneva, Switzerland). +The highest decision-making body of the WTO is the Ministerial Conference, which usually meets every two years. It brings together all members of the WTO, all of which are countries or customs unions. The Ministerial Conference can take decisions on all matters under any of the multilateral trade agreements. The inaugural ministerial conference was held in Singapore in 1996. Disagreements between largely developed and developing economies emerged during this conference over four issues initiated by this conference, which led to them being collectively referred to as the "Singapore issues". The second ministerial conference was held in Geneva in Switzerland. The third conference in Seattle, Washington ended in failure, with massive demonstrations and police and National Guard crowd-control efforts drawing worldwide attention. The fourth ministerial conference was held in Doha in the Persian Gulf nation of Qatar. The Doha Development Round was launched at the conference. The conference also approved the joining of China, which became the 143rd member to join. The fifth ministerial conference was held in Cancún, Mexico, aiming at forging agreement on the Doha round. An alliance of 22 southern states, the G20 developing nations (led by India, China,[30] Brazil, ASEAN led by the Philippines), resisted demands from the North for agreements on the so-called "Singapore issues" and called for an end to agricultural subsidies within the EU and the US. The talks broke down without progress. +The sixth WTO ministerial conference was held in Hong Kong from 13–18 December 2005. It was considered vital if the four-year-old Doha Development Round negotiations were to move forward sufficiently to conclude the round in 2006. In this meeting, countries agreed to phase out all their agricultural export subsidies by the end of 2013, and terminate any cotton export subsidies by the end of 2006. Further concessions to developing countries included an agreement to introduce duty-free, tariff-free access for goods from the Least Developed Countries, following the Everything but Arms initiative of the European Union — but with up to 3% of tariff lines exempted. Other major issues were left for further negotiation to be completed by the end of 2010. The WTO General Council, on 26 May 2009, agreed to hold a seventh WTO ministerial conference session in Geneva from 30 November-3 December 2009. A statement by chairman Amb. Mario Matus acknowledged that the prime purpose was to remedy a breach of protocol requiring two-yearly "regular" meetings, which had lapsed with the Doha Round failure in 2005, and that the "scaled-down" meeting would not be a negotiating session, but "emphasis will be on transparency and open discussion rather than on small group processes and informal negotiating structures". The general theme for discussion was "The WTO, the Multilateral Trading System and the Current Global Economic Environment"[31] +Doha Round (Doha Agenda) +Main article: Doha Development Round + +The Doha Development Round started in 2001 is at an impasse. +The WTO launched the current round of negotiations, the Doha Development Round, at the fourth ministerial conference in Doha, Qatar in November 2001. This was to be an ambitious effort to make globalization more inclusive and help the world's poor, particularly by slashing barriers and subsidies in farming.[32] The initial agenda comprised both further trade liberalization and new rule-making, underpinned by commitments to strengthen substantial assistance to developing countries.[33] +The negotiations have been highly contentious. Disagreements still continue over several key areas including agriculture subsidies, which emerged as critical in July 2006.[34] According to a European Union statement, "The 2008 Ministerial meeting broke down over a disagreement between exporters of agricultural bulk commodities and countries with large numbers of subsistence farmers on the precise terms of a 'special safeguard measure' to protect farmers from surges in imports."[35] The position of the European Commission is that "The successful conclusion of the Doha negotiations would confirm the central role of multilateral liberalisation and rule-making. It would confirm the WTO as a powerful shield against protectionist backsliding."[33] An impasse remains and, as of August 2013, agreement has not been reached, despite intense negotiations at several ministerial conferences and at other sessions. On 27 March 2013, the chairman of agriculture talks announced "a proposal to loosen price support disciplines for developing countries’ public stocks and domestic food aid." He added: “...we are not yet close to agreement—in fact, the substantive discussion of the proposal is only beginning.”[36] +[show]v · t · eGATT and WTO trade rounds[37] +Functions +Among the various functions of the WTO, these are regarded by analysts as the most important: +It oversees the implementation, administration and operation of the covered agreements.[38][39] +It provides a forum for negotiations and for settling disputes.[40][41] +Additionally, it is the WTO's duty to review and propagate the national trade policies, and to ensure the coherence and transparency of trade policies through surveillance in global economic policy-making.[39][41] Another priority of the WTO is the assistance of developing, least-developed and low-income countries in transition to adjust to WTO rules and disciplines through technical cooperation and training.[42] +(i) The WTO shall facilitate the implementation, administration and operation and further the objec­tives of this Agreement and of the Multilateral Trade Agreements, and shall also provide the frame work for the implementation, administration and operation of the multilateral Trade Agreements. +(ii) The WTO shall provide the forum for negotiations among its members concerning their multilateral trade relations in matters dealt with under the Agreement in the Annexes to this Agreement. +(iii) The WTO shall administer the Understanding on Rules and Procedures Governing the Settlement of Disputes. +(iv) The WTO shall administer Trade Policy Review Mechanism. +(v) With a view to achieving greater coherence in global economic policy making, the WTO shall cooperate, as appropriate, with the international Monetary Fund (IMF) and with the International Bank for Reconstruction and Development (IBRD) and its affiliated agencies. [43] +The above five listings are the additional functions of the World Trade Organization. As globalization proceeds in today's society, the necessity of an International Organization to manage the trading systems has been of vital importance. As the trade volume increases, issues such as protectionism, trade barriers, subsidies, violation of intellectual property arise due to the differences in the trading rules of every nation. The World Trade Organization serves as the mediator between the nations when such problems arise. WTO could be referred to as the product of globalization and also as one of the most important organizations in today's globalized society. +The WTO is also a center of economic research and analysis: regular assessments of the global trade picture in its annual publications and research reports on specific topics are produced by the organization.[44] Finally, the WTO cooperates closely with the two other components of the Bretton Woods system, the IMF and the World Bank.[40] +Principles of the trading system +The WTO establishes a framework for trade policies; it does not define or specify outcomes. That is, it is concerned with setting the rules of the trade policy games.[45] Five principles are of particular importance in understanding both the pre-1994 GATT and the WTO: +Non-discrimination. It has two major components: the most favoured nation (MFN) rule, and the national treatment policy. Both are embedded in the main WTO rules on goods, services, and intellectual property, but their precise scope and nature differ across these areas. The MFN rule requires that a WTO member must apply the same conditions on all trade with other WTO members, i.e. a WTO member has to grant the most favorable conditions under which it allows trade in a certain product type to all other WTO members.[45] "Grant someone a special favour and you have to do the same for all other WTO members."[29] National treatment means that imported goods should be treated no less favorably than domestically produced goods (at least after the foreign goods have entered the market) and was introduced to tackle non-tariff barriers to trade (e.g. technical standards, security standards et al. discriminating against imported goods).[45] +Reciprocity. It reflects both a desire to limit the scope of free-riding that may arise because of the MFN rule, and a desire to obtain better access to foreign markets. A related point is that for a nation to negotiate, it is necessary that the gain from doing so be greater than the gain available from unilateral liberalization; reciprocal concessions intend to ensure that such gains will materialise.[46] +Binding and enforceable commitments. The tariff commitments made by WTO members in a multilateral trade negotiation and on accession are enumerated in a schedule (list) of concessions. These schedules establish "ceiling bindings": a country can change its bindings, but only after negotiating with its trading partners, which could mean compensating them for loss of trade. If satisfaction is not obtained, the complaining country may invoke the WTO dispute settlement procedures.[29][46] +Transparency. The WTO members are required to publish their trade regulations, to maintain institutions allowing for the review of administrative decisions affecting trade, to respond to requests for information by other members, and to notify changes in trade policies to the WTO. These internal transparency requirements are supplemented and facilitated by periodic country-specific reports (trade policy reviews) through the Trade Policy Review Mechanism (TPRM).[47] The WTO system tries also to improve predictability and stability, discouraging the use of quotas and other measures used to set limits on quantities of imports.[29] +Safety valves. In specific circumstances, governments are able to restrict trade. The WTO's agreements permit members to take measures to protect not only the environment but also public health, animal health and plant health.[48] +There are three types of provision in this direction: +articles allowing for the use of trade measures to attain non-economic objectives; +articles aimed at ensuring "fair competition"; members must not use environmental protection measures as a means of disguising protectionist policies.[48] +provisions permitting intervention in trade for economic reasons.[47] +Exceptions to the MFN principle also allow for preferential treatment of developing countries, regional free trade areas and customs unions.[6]:fol.93 +Organizational structure +The General Council has the following subsidiary bodies which oversee committees in different areas: +Council for Trade in Goods +There are 11 committees under the jurisdiction of the Goods Council each with a specific task. All members of the WTO participate in the committees. The Textiles Monitoring Body is separate from the other committees but still under the jurisdiction of Goods Council. The body has its own chairman and only 10 members. The body also has several groups relating to textiles.[49] +Council for Trade-Related Aspects of Intellectual Property Rights +Information on intellectual property in the WTO, news and official records of the activities of the TRIPS Council, and details of the WTO's work with other international organizations in the field.[50] +Council for Trade in Services +The Council for Trade in Services operates under the guidance of the General Council and is responsible for overseeing the functioning of the General Agreement on Trade in Services (GATS). It is open to all WTO members, and can create subsidiary bodies as required.[51] +Trade Negotiations Committee +The Trade Negotiations Committee (TNC) is the committee that deals with the current trade talks round. The chair is WTO's director-general. As of June 2012 the committee was tasked with the Doha Development Round.[52] +The Service Council has three subsidiary bodies: financial services, domestic regulations, GATS rules and specific commitments.[49] The council has several different committees, working groups, and working parties.[53] There are committees on the following: Trade and Environment; Trade and Development (Subcommittee on Least-Developed Countries); Regional Trade Agreements; Balance of Payments Restrictions; and Budget, Finance and Administration. There are working parties on the following: Accession. There are working groups on the following: Trade, debt and finance; and Trade and technology transfer. +Decision-making +The WTO describes itself as "a rules-based, member-driven organization — all decisions are made by the member governments, and the rules are the outcome of negotiations among members".[54] The WTO Agreement foresees votes where consensus cannot be reached, but the practice of consensus dominates the process of decision-making.[55] +Richard Harold Steinberg (2002) argues that although the WTO's consensus governance model provides law-based initial bargaining, trading rounds close through power-based bargaining favouring Europe and the U.S., and may not lead to Pareto improvement.[56] +Dispute settlement +Main article: Dispute settlement in the WTO +In 1994, the WTO members agreed on the Understanding on Rules and Procedures Governing the Settlement of Disputes (DSU) annexed to the "Final Act" signed in Marrakesh in 1994.[57] Dispute settlement is regarded by the WTO as the central pillar of the multilateral trading system, and as a "unique contribution to the stability of the global economy".[58] WTO members have agreed that, if they believe fellow-members are violating trade rules, they will use the multilateral system of settling disputes instead of taking action unilaterally.[59] +The operation of the WTO dispute settlement process involves the DSB panels, the Appellate Body, the WTO Secretariat, arbitrators, independent experts and several specialized institutions.[60] Bodies involved in the dispute settlement process, World Trade Organization. +Accession and membership +Main article: World Trade Organization accession and membership +The process of becoming a WTO member is unique to each applicant country, and the terms of accession are dependent upon the country's stage of economic development and current trade regime.[61] The process takes about five years, on average, but it can last more if the country is less than fully committed to the process or if political issues interfere. The shortest accession negotiation was that of the Kyrgyz Republic, while the longest was that of Russia, which, having first applied to join GATT in 1993, was approved for membership in December 2011 and became a WTO member on 22 August 2012.[62] The second longest was that of Vanuatu, whose Working Party on the Accession of Vanuatu was established on 11 July 1995. After a final meeting of the Working Party in October 2001, Vanuatu requested more time to consider its accession terms. In 2008, it indicated its interest to resume and conclude its WTO accession. The Working Party on the Accession of Vanuatu was reconvened informally on 4 April 2011 to discuss Vanuatu's future WTO membership. The re-convened Working Party completed its mandate on 2 May 2011. The General Council formally approved the Accession Package of Vanuatu on 26 October 2011. On 24 August 2012, the WTO welcomed Vanuatu as its 157th member.[63] An offer of accession is only given once consensus is reached among interested parties.[64] +Accession process + +WTO accession progress: + Members (including dual-representation with the European Union) + Draft Working Party Report or Factual Summary adopted + Goods and/or Services offers submitted + Memorandum on Foreign Trade Regime (FTR) submitted + Observer, negotiations to start later or no Memorandum on FTR submitted + Frozen procedures or no negotiations in the last 3 years + No official interaction with the WTO +A country wishing to accede to the WTO submits an application to the General Council, and has to describe all aspects of its trade and economic policies that have a bearing on WTO agreements.[65] The application is submitted to the WTO in a memorandum which is examined by a working party open to all interested WTO Members.[66] +After all necessary background information has been acquired, the working party focuses on issues of discrepancy between the WTO rules and the applicant's international and domestic trade policies and laws. The working party determines the terms and conditions of entry into the WTO for the applicant nation, and may consider transitional periods to allow countries some leeway in complying with the WTO rules.[61] +The final phase of accession involves bilateral negotiations between the applicant nation and other working party members regarding the concessions and commitments on tariff levels and market access for goods and services. The new member's commitments are to apply equally to all WTO members under normal non-discrimination rules, even though they are negotiated bilaterally.[65] +When the bilateral talks conclude, the working party sends to the general council or ministerial conference an accession package, which includes a summary of all the working party meetings, the Protocol of Accession (a draft membership treaty), and lists ("schedules") of the member-to-be's commitments. Once the general council or ministerial conference approves of the terms of accession, the applicant's parliament must ratify the Protocol of Accession before it can become a member.[67] Some countries may have faced tougher and a much longer accession process due to challenges during negotiations with other WTO members, such as Vietnam, whose negotiations took more than 11 years before it became official member in January 2007.[68] +Members and observers +The WTO has 160 members and 24 observer governments.[69] In addition to states, the European Union is a member. WTO members do not have to be full sovereign nation-members. Instead, they must be a customs territory with full autonomy in the conduct of their external commercial relations. Thus Hong Kong has been a member since 1995 (as "Hong Kong, China" since 1997) predating the People's Republic of China, which joined in 2001 after 15 years of negotiations. The Republic of China (Taiwan) acceded to the WTO in 2002 as "Separate Customs Territory of Taiwan, Penghu, Kinmen and Matsu" (Chinese Taipei) despite its disputed status.[70] The WTO Secretariat omits the official titles (such as Counselor, First Secretary, Second Secretary and Third Secretary) of the members of Chinese Taipei's Permanent Mission to the WTO, except for the titles of the Permanent Representative and the Deputy Permanent Representative.[71] +As of 2007, WTO member states represented 96.4% of global trade and 96.7% of global GDP.[72] Iran, followed by Algeria, are the economies with the largest GDP and trade outside the WTO, using 2005 data.[73][74] With the exception of the Holy See, observers must start accession negotiations within five years of becoming observers. A number of international intergovernmental organizations have also been granted observer status to WTO bodies.[75] 14 UN member states have no official affiliation with the WTO. +Agreements +Further information: Uruguay Round +The WTO oversees about 60 different agreements which have the status of international legal texts. Member countries must sign and ratify all WTO agreements on accession.[76] A discussion of some of the most important agreements follows. The Agreement on Agriculture came into effect with the establishment of the WTO at the beginning of 1995. The AoA has three central concepts, or "pillars": domestic support, market access and export subsidies. The General Agreement on Trade in Services was created to extend the multilateral trading system to service sector, in the same way as the General Agreement on Tariffs and Trade (GATT) provided such a system for merchandise trade. The agreement entered into force in January 1995. The Agreement on Trade-Related Aspects of Intellectual Property Rights sets down minimum standards for many forms of intellectual property (IP) regulation. It was negotiated at the end of the Uruguay Round of the General Agreement on Tariffs and Trade (GATT) in 1994.[77] +The Agreement on the Application of Sanitary and Phytosanitary Measures—also known as the SPS Agreement—was negotiated during the Uruguay Round of GATT, and entered into force with the establishment of the WTO at the beginning of 1995. Under the SPS agreement, the WTO sets constraints on members' policies relating to food safety (bacterial contaminants, pesticides, inspection and labelling) as well as animal and plant health (imported pests and diseases). The Agreement on Technical Barriers to Trade is an international treaty of the World Trade Organization. It was negotiated during the Uruguay Round of the General Agreement on Tariffs and Trade, and entered into force with the establishment of the WTO at the end of 1994. The object ensures that technical negotiations and standards, as well as testing and certification procedures, do not create unnecessary obstacles to trade".[78] The Agreement on Customs Valuation, formally known as the Agreement on Implementation of Article VII of GATT, prescribes methods of customs valuation that Members are to follow. Chiefly, it adopts the "transaction value" approach. +In December 2013, the biggest agreement within the WTO was signed and known as the Bali Package.[79] +Office of director-general + +The headquarters of the World Trade Organization, in Geneva, Switzerland. +The procedures for the appointment of the WTO director-general were published in January 2003.[80] Additionally, there are four deputy directors-general. As of 1 October 2013, under director-general Roberto Azevêdo, the four deputy directors-general are Yi Xiaozhun of China, Karl-Ernst Brauner of Germany, Yonov Frederick Agah of Nigeria and David Shark of the United States.[81] +List of directors-general +Source: Official website[82] +Brazil Roberto Azevedo, 2013– +France Pascal Lamy, 2005–2013 +Thailand Supachai Panitchpakdi, 2002–2005 +New Zealand Mike Moore, 1999–2002 +Italy Renato Ruggiero, 1995–1999 +Republic of Ireland Peter Sutherland, 1995 +(Heads of the precursor organization, GATT): +Republic of Ireland Peter Sutherland, 1993–1995 +Switzerland Arthur Dunkel, 1980–1993 +Switzerland Olivier Long, 1968–1980 +United Kingdom Eric Wyndham White, 1948–1968 +See also +Agreement on Trade Related Investment Measures (TRIMS) +Agreement on Trade-Related Aspects of Intellectual Property Rights (TRIPS) +Aide-mémoire non-paper +Anti-globalization movement +Criticism of the World Trade Organization +Foreign Affiliate Trade Statistics +Global administrative law +Globality +Information Technology Agreement +International Trade Centre +Labour Standards in the World Trade Organisation +List of member states of the World Trade Organization +North American Free Trade Agreement (NAFTA) +Subsidy +Swiss Formula +Trade bloc +Washington Consensus +World Trade Report +World Trade Organization Ministerial Conference of 1999 protest activity +China and the World Trade Organization +Notes and references +Jump up ^ Members and Observers at WTO official website +Jump up ^ Languages, Documentation and Information Management Division at WTO official site +Jump up ^ "WTO Secretariat budget for 2011". WTO official site. Retrieved 25 August 2008. +Jump up ^ Understanding the WTO: What We Stand For_ Fact File +Jump up ^ World Trade Organization - UNDERSTANDING THE WTO: BASICS +^ Jump up to: a b Understanding the WTO Handbook at WTO official website. (Note that the document's printed folio numbers do not match the pdf page numbers.) +Jump up ^ Malanczuk, P. (1999). "International Organisations and Space Law: World Trade Organization". Encyclopaedia Britannica 442. p. 305. Bibcode:1999ESASP.442..305M. +Jump up ^ Understanding the WTO: The Doha Agenda +Jump up ^ The Challenges to the World Trade Organization: It’s All About Legitimacy THE BROOKINGS INSTITUTION, Policy Paper 2011-04 +Jump up ^ GROUPS IN THE WTO Updated 1 July 2013 +Jump up ^ Bourcier, Nicolas (21 May 2013). "Roberto Azevedo's WTO appointment gives Brazil a seat at the top table". Guardian Weekly. Retrieved 2 September 2013. +Jump up ^ "Roberto Azevêdo takes over". WTO official website. 1 September 2013. Retrieved 2 September 2013. +Jump up ^ "Overview of the WTO Secretariat". WTO official website. Retrieved 2 September 2013. +Jump up ^ Ninth WTO Ministerial Conference | WTO - MC9 +Jump up ^ BBC News - WTO agrees global trade deal worth $1tn +Jump up ^ A.E. Eckes Jr., US Trade History, 73 +* A. Smithies, Reflections on the Work of Keynes, 578–601 +* N. Warren, Internet and Globalization, 193 +Jump up ^ P. van den Bossche, The Law and Policy of the World Trade Organization, 80 +Jump up ^ Palmeter-Mavroidis, Dispute Settlement, 2 +Jump up ^ Fergusson, Ian F. (9 May 2007). "The World Trade Organization: Background and Issues" (PDF). Congressional Research Service. p. 4. Retrieved 15 August 2008. +Jump up ^ It was contemplated that the GATT would be applied for several years until the ITO came into force. However, since the ITO was never brought into being, the GATT gradually became the focus for international governmental cooperation on trade matters with economist Nicholas Halford overseeing the implementation of GATT in members policies. (P. van den Bossche, The Law and Policy of the World Trade Organization, 81; J.H. Jackson, Managing the Trading System, 134). +^ Jump up to: a b The GATT Years: from Havana to Marrakesh, WTO official site +Jump up ^ Footer, M. E. Analysis of the World Trade Organization, 17 +Jump up ^ B.S. Klapper, With a "Short Window" +Jump up ^ Lula, Time to Get Serious about Agricultural Subsidies +^ Jump up to: a b c P. Gallagher, The First Ten Years of the WTO, 4 +^ Jump up to: a b The Uruguay Round, WTO official site +Jump up ^ "Legal texts – Marrakesh agreement". WTO. Retrieved 30 May 2010. +Jump up ^ Overview: a Navigational Guide, WTO official site. For the complete list of "The Uruguay Round Agreements", see WTO legal texts, WTO official site, and Uruguay Round Agreements, Understandings, Decisions and Declarations, WorldTradeLaw.net +^ Jump up to: a b c d Principles of the Trading System, WTO official site +Jump up ^ "Five Years of China WTO Membership. EU and US Perspectives about China's Compliance with Transparency Commitments and the Transitional Review Mechanism". Papers.ssrn.com. Retrieved 30 May 2010. +Jump up ^ WTO to hold 7th Ministerial Conference on 30 November-2 December 2009 WTO official website +Jump up ^ "In the twilight of Doha". The Economist (The Economist): 65. 27 July 2006. +^ Jump up to: a b European Commission The Doha Round +Jump up ^ Fergusson, Ian F. (18 January 2008). "World Trade Organization Negotiations: The Doha Development Agenda" (PDF). Congressional Research Service. Retrieved 13 April 2012. Page 9 (folio CRS-6) +Jump up ^ WTO trade negotiations: Doha Development Agenda Europa press release, 31 October 2011 +Jump up ^ "Members start negotiating proposal on poor countries’ food stockholding". WTO official website. 27 March 2013. Retrieved 2 September 2013. +Jump up ^ a)The GATT years: from Havana to Marrakesh, World Trade Organization +b)Timeline: World Trade Organization – A chronology of key events, BBC News +c)Brakman-Garretsen-Marrewijk-Witteloostuijn, Nations and Firms in the Global Economy, Chapter 10: Trade and Capital Restriction +Jump up ^ Functions of the WTO, IISD +^ Jump up to: a b Main Functions, WTO official site +^ Jump up to: a b A Bredimas, International Economic Law, II, 17 +^ Jump up to: a b C. Deere, Decision-making in the WTO: Medieval or Up-to-Date? +Jump up ^ WTO Assistance for Developing Countries[dead link], WTO official site +Jump up ^ Sinha, Aparijita. [1]. "What are the functions and objectives of the WTO?". Retrieved on 13 April, 2014. +Jump up ^ Economic research and analysis, WTO official site +^ Jump up to: a b c B. Hoekman, The WTO: Functions and Basic Principles, 42 +^ Jump up to: a b B. Hoekman, The WTO: Functions and Basic Principles, 43 +^ Jump up to: a b B. Hoekman, The WTO: Functions and Basic Principles, 44 +^ Jump up to: a b Understanding the WTO: What we stand for +^ Jump up to: a b "Fourth level: down to the nitty-gritty". WTO official site. Retrieved 18 August 2008. +Jump up ^ "Intellectual property – overview of TRIPS Agreement". Wto.org. 15 April 1994. Retrieved 30 May 2010. +Jump up ^ "The Services Council, its Committees and other subsidiary bodies". WTO official site. Retrieved 14 August 2008. +Jump up ^ "The Trade Negotiations Committee". WTO official site. Retrieved 14 August 2008. +Jump up ^ "WTO organization chart". WTO official site. Retrieved 14 August 2008. +Jump up ^ Decision-making at WTO official site +Jump up ^ Decision-Making in the World Trade Organization Abstract from Journal of International Economic Law at Oxford Journals +Jump up ^ Steinberg, Richard H. "In the Shadow of Law or Power? Consensus-based Bargaining and Outcomes in the GATT/WTO." International Organization. Spring 2002. pp. 339–374. +Jump up ^ Stewart-Dawyer, The WTO Dispute Settlement System, 7 +Jump up ^ S. Panitchpakdi, The WTO at ten, 8. +Jump up ^ Settling Disputes:a Unique Contribution, WTO official site +Jump up ^ "Disputes – Dispute Settlement CBT – WTO Bodies involved in the dispute settlement process – The Dispute Settlement Body (DSB) – Page 1". WTO. 25 July 1996. Retrieved 21 May 2011. +^ Jump up to: a b Accessions Summary, Center for International Development +Jump up ^ Ministerial Conference approves Russia's WTO membership WTO News Item, 16 December 2011 +Jump up ^ Accession status: Vanuatu. WTO. Retrieved on 12 July 2013. +Jump up ^ C. Michalopoulos, WTO Accession, 64 +^ Jump up to: a b Membership, Alliances and Bureaucracy, WTO official site +Jump up ^ C. Michalopoulos, WTO Accession, 62–63 +Jump up ^ How to Become a Member of the WTO, WTO official site +Jump up ^ Napier, Nancy K.; Vuong, Quan Hoang (2013). What we see, why we worry, why we hope: Vietnam going forward. Boise, ID, USA: Boise State University CCI Press. p. 140. ISBN 978-0985530587. +Jump up ^ "Members and Observers". World Trade Organization. 24 August 2012. +Jump up ^ Jackson, J. H. Sovereignty, 109 +Jump up ^ ROC Government Publication +Jump up ^ "Accession in perspective". World Trade Organization. Retrieved 22 December 2013. +Jump up ^ "ANNEX 1. STATISTICAL SURVEY". World Trade Organization. 2005. Retrieved 22 December 2013. +Jump up ^ Arjomandy, Danial (21 November 2013). "Iranian Membership in the World Trade Organization: An Unclear Future". Iranian Studies. Retrieved 22 December 2013. +Jump up ^ International intergovernmental organizations granted observer status to WTO bodies at WTO official website +Jump up ^ "Legal texts – the WTO agreements". WTO. Retrieved 30 May 2010. +Jump up ^ Understanding the WTO - Intellectual property: protection and enforcement. WTO. Retrieved on 29 July 2013. +Jump up ^ "A Summary of the Final Act of the Uruguay Round". Wto.org. Retrieved 30 May 2010. +Jump up ^ Zarocostas, John (7 December 2013). "Global Trade Deal Reached". WWD. Retrieved 8 December 2013. +Jump up ^ "WT/L/509". WTO. Retrieved 18 February 2013. +Jump up ^ "Director-General Elect Azevêdo announces his four Deputy Directors-General". 17 August 2013. Retrieved 2 September 2013. +Jump up ^ "Previous GATT and WTO Directors-General". WTO. Retrieved 21 May 2011. +External links + Wikiquote has quotations related to: World Trade Organization + Wikimedia Commons has media related to World Trade Organization. +Official pages +Official WTO homepage +WTO 10th Anniversary PDF (1.40 MB) — Highlights of the first decade, Annual Report 2005 pages 116–166 +Glossary of terms—a guide to 'WTO-speak' +International Trade Centre — joint UN/WTO agency +Government pages on the WTO +European Union position on the WTO +Media pages on the WTO +World Trade Organization +BBC News — Profile: WTO +Guardian Unlimited — Special Report: The World Trade Organisation ongoing coverage +Non-governmental organization pages on the WTO +Gatt.org — Parody of official WTO page by The Yes Men +Public Citizen +Transnational Institute: Beyond the WTO +[show] v t e +World Trade Organization +[show] v t e +International trade +[show] v t e +International organizations +Authority control +WorldCat VIAF: 149937768 LCCN: no94018277 ISNI: 0000 0001 2296 2735 GND: 2145784-0 SELIBR: 135910 ULAN: 500292980 NDL: 00577475 NKC: kn20010711437 BNE: XX4574846 +Categories: World Trade OrganizationInternational tradeInternational trade organizationsOrganisations based in GenevaOrganizations established in 1995World government +Navigation menu +Create accountLog inArticleTalkReadView sourceView history + +Main page +Contents +Featured content +Current events +Random article +Donate to Wikipedia +Wikimedia Shop +Interaction +Help +About Wikipedia +Community portal +Recent changes +Contact page +Tools +What links here +Related changes +Upload file +Special pages +Permanent link +Page information +Wikidata item +Cite this page +Print/export +Create a book +Download as PDF +Printable version +Languages +Afrikaans +العربية +Aragonés +Asturianu +Azərbaycanca +বাংলা +Bân-lâm-gú +Беларуская +Беларуская (тарашкевіца)‎ +Български +Bosanski +Brezhoneg +Català +Čeština +Cymraeg +Dansk +Deutsch +Eesti +Ελληνικά +Español +Esperanto +Euskara +فارسی +Fiji Hindi +Føroyskt +Français +Frysk +Galego +ગુજરાતી +客家語/Hak-kâ-ngî +한국어 +Հայերեն +हिन्दी +Hrvatski +Ido +Ilokano +Bahasa Indonesia +Íslenska +Italiano +עברית +Basa Jawa +ಕನ್ನಡ +Къарачай-малкъар +ქართული +Қазақша +Kiswahili +Latina +Latviešu +Lietuvių +Magyar +Македонски +മലയാളം +मराठी +مصرى +Bahasa Melayu +Baso Minangkabau +မြန်မာဘာသာ +Nederlands +नेपाली +नेपाल भाषा +日本語 +Нохчийн +Norsk bokmål +Norsk nynorsk +Occitan +Oʻzbekcha +ਪੰਜਾਬੀ +پنجابی +پښتو +ភាសាខ្មែរ +Piemontèis +Polski +Português +Română +Русиньскый +Русский +Саха тыла +Shqip +සිංහල +Simple English +Slovenčina +Slovenščina +کوردی +Српски / srpski +Srpskohrvatski / српскохрватски +Suomi +Svenska +Tagalog +தமிழ் +Татарча/tatarça +తెలుగు +ไทย +Тоҷикӣ +Türkçe +Türkmençe +Українська +اردو +ئۇيغۇرچە / Uyghurche +Tiếng Việt +Winaray +ייִדיש +Yorùbá +粵語 +Žemaitėška +中文 +Edit links +This page was last modified on 22 November 2014 at 14:33. +Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Terms of Use and Privacy Policy. Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc., a non-profit organization. +Privacy policyAbout WikipediaDisclaimersContact WikipediaDevelopersMobile viewWikimedia Foundation Powered by MediaWiki \ No newline at end of file diff --git a/vendor/github.com/blevesearch/bleve/search/query/query_string.y b/vendor/github.com/blevesearch/bleve/search/query/query_string.y new file mode 100644 index 0000000000..d3e5ac9d7e --- /dev/null +++ b/vendor/github.com/blevesearch/bleve/search/query/query_string.y @@ -0,0 +1,328 @@ +%{ +package query +import ( + "fmt" + "strconv" + "strings" + "time" +) + +func logDebugGrammar(format string, v ...interface{}) { + if debugParser { + logger.Printf(format, v...) + } +} +%} + +%union { +s string +n int +f float64 +q Query +pf *float64} + +%token tSTRING tPHRASE tPLUS tMINUS tCOLON tBOOST tNUMBER tSTRING tGREATER tLESS +tEQUAL tTILDE + +%type tSTRING +%type tPHRASE +%type tNUMBER +%type posOrNegNumber +%type tTILDE +%type tBOOST +%type searchBase +%type searchSuffix +%type searchPrefix + +%% + +input: +searchParts { + logDebugGrammar("INPUT") +}; + +searchParts: +searchPart searchParts { + logDebugGrammar("SEARCH PARTS") +} +| +searchPart { + logDebugGrammar("SEARCH PART") +}; + +searchPart: +searchPrefix searchBase searchSuffix { + query := $2 + if $3 != nil { + if query, ok := query.(BoostableQuery); ok { + query.SetBoost(*$3) + } + } + switch($1) { + case queryShould: + yylex.(*lexerWrapper).query.AddShould(query) + case queryMust: + yylex.(*lexerWrapper).query.AddMust(query) + case queryMustNot: + yylex.(*lexerWrapper).query.AddMustNot(query) + } +}; + + +searchPrefix: +/* empty */ { + $$ = queryShould +} +| +tPLUS { + logDebugGrammar("PLUS") + $$ = queryMust +} +| +tMINUS { + logDebugGrammar("MINUS") + $$ = queryMustNot +}; + +searchBase: +tSTRING { + str := $1 + logDebugGrammar("STRING - %s", str) + var q FieldableQuery + if strings.HasPrefix(str, "/") && strings.HasSuffix(str, "/") { + q = NewRegexpQuery(str[1:len(str)-1]) + } else if strings.ContainsAny(str, "*?"){ + q = NewWildcardQuery(str) + } else { + q = NewMatchQuery(str) + } + $$ = q +} +| +tSTRING tTILDE { + str := $1 + fuzziness, err := strconv.ParseFloat($2, 64) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid fuzziness value: %v", err)) + } + logDebugGrammar("FUZZY STRING - %s %f", str, fuzziness) + q := NewMatchQuery(str) + q.SetFuzziness(int(fuzziness)) + $$ = q +} +| +tSTRING tCOLON tSTRING tTILDE { + field := $1 + str := $3 + fuzziness, err := strconv.ParseFloat($4, 64) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid fuzziness value: %v", err)) + } + logDebugGrammar("FIELD - %s FUZZY STRING - %s %f", field, str, fuzziness) + q := NewMatchQuery(str) + q.SetFuzziness(int(fuzziness)) + q.SetField(field) + $$ = q +} +| +tNUMBER { + str := $1 + logDebugGrammar("STRING - %s", str) + q1 := NewMatchQuery(str) + val, err := strconv.ParseFloat($1, 64) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err)) + } + inclusive := true + q2 := NewNumericRangeInclusiveQuery(&val, &val, &inclusive, &inclusive) + q := NewDisjunctionQuery([]Query{q1,q2}) + q.queryStringMode = true + $$ = q +} +| +tPHRASE { + phrase := $1 + logDebugGrammar("PHRASE - %s", phrase) + q := NewMatchPhraseQuery(phrase) + $$ = q +} +| +tSTRING tCOLON tSTRING { + field := $1 + str := $3 + logDebugGrammar("FIELD - %s STRING - %s", field, str) + var q FieldableQuery + if strings.HasPrefix(str, "/") && strings.HasSuffix(str, "/") { + q = NewRegexpQuery(str[1:len(str)-1]) + } else if strings.ContainsAny(str, "*?"){ + q = NewWildcardQuery(str) + } else { + q = NewMatchQuery(str) + } + q.SetField(field) + $$ = q +} +| +tSTRING tCOLON posOrNegNumber { + field := $1 + str := $3 + logDebugGrammar("FIELD - %s STRING - %s", field, str) + q1 := NewMatchQuery(str) + q1.SetField(field) + val, err := strconv.ParseFloat($3, 64) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err)) + } + inclusive := true + q2 := NewNumericRangeInclusiveQuery(&val, &val, &inclusive, &inclusive) + q2.SetField(field) + q := NewDisjunctionQuery([]Query{q1,q2}) + q.queryStringMode = true + $$ = q +} +| +tSTRING tCOLON tPHRASE { + field := $1 + phrase := $3 + logDebugGrammar("FIELD - %s PHRASE - %s", field, phrase) + q := NewMatchPhraseQuery(phrase) + q.SetField(field) + $$ = q +} +| +tSTRING tCOLON tGREATER posOrNegNumber { + field := $1 + min, err := strconv.ParseFloat($4, 64) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err)) + } + minInclusive := false + logDebugGrammar("FIELD - GREATER THAN %f", min) + q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil) + q.SetField(field) + $$ = q +} +| +tSTRING tCOLON tGREATER tEQUAL posOrNegNumber { + field := $1 + min, err := strconv.ParseFloat($5, 64) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err)) + } + minInclusive := true + logDebugGrammar("FIELD - GREATER THAN OR EQUAL %f", min) + q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil) + q.SetField(field) + $$ = q +} +| +tSTRING tCOLON tLESS posOrNegNumber { + field := $1 + max, err := strconv.ParseFloat($4, 64) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err)) + } + maxInclusive := false + logDebugGrammar("FIELD - LESS THAN %f", max) + q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive) + q.SetField(field) + $$ = q +} +| +tSTRING tCOLON tLESS tEQUAL posOrNegNumber { + field := $1 + max, err := strconv.ParseFloat($5, 64) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err)) + } + maxInclusive := true + logDebugGrammar("FIELD - LESS THAN OR EQUAL %f", max) + q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive) + q.SetField(field) + $$ = q +} +| +tSTRING tCOLON tGREATER tPHRASE { + field := $1 + minInclusive := false + phrase := $4 + + logDebugGrammar("FIELD - GREATER THAN DATE %s", phrase) + minTime, err := queryTimeFromString(phrase) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid time: %v", err)) + } + q := NewDateRangeInclusiveQuery(minTime, time.Time{}, &minInclusive, nil) + q.SetField(field) + $$ = q +} +| +tSTRING tCOLON tGREATER tEQUAL tPHRASE { + field := $1 + minInclusive := true + phrase := $5 + + logDebugGrammar("FIELD - GREATER THAN OR EQUAL DATE %s", phrase) + minTime, err := queryTimeFromString(phrase) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid time: %v", err)) + } + q := NewDateRangeInclusiveQuery(minTime, time.Time{}, &minInclusive, nil) + q.SetField(field) + $$ = q +} +| +tSTRING tCOLON tLESS tPHRASE { + field := $1 + maxInclusive := false + phrase := $4 + + logDebugGrammar("FIELD - LESS THAN DATE %s", phrase) + maxTime, err := queryTimeFromString(phrase) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid time: %v", err)) + } + q := NewDateRangeInclusiveQuery(time.Time{}, maxTime, nil, &maxInclusive) + q.SetField(field) + $$ = q +} +| +tSTRING tCOLON tLESS tEQUAL tPHRASE { + field := $1 + maxInclusive := true + phrase := $5 + + logDebugGrammar("FIELD - LESS THAN OR EQUAL DATE %s", phrase) + maxTime, err := queryTimeFromString(phrase) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid time: %v", err)) + } + q := NewDateRangeInclusiveQuery(time.Time{}, maxTime, nil, &maxInclusive) + q.SetField(field) + $$ = q +}; + +searchSuffix: +/* empty */ { + $$ = nil +} +| +tBOOST { + $$ = nil + boost, err := strconv.ParseFloat($1, 64) + if err != nil { + yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid boost value: %v", err)) + } else { + $$ = &boost + } + logDebugGrammar("BOOST %f", boost) +}; + +posOrNegNumber: +tNUMBER { + $$ = $1 +} +| +tMINUS tNUMBER { + $$ = "-" + $2 +}; diff --git a/vendor/github.com/blevesearch/go-porterstemmer/.gitignore b/vendor/github.com/blevesearch/go-porterstemmer/.gitignore new file mode 100644 index 0000000000..d1ffcc5dc7 --- /dev/null +++ b/vendor/github.com/blevesearch/go-porterstemmer/.gitignore @@ -0,0 +1,8 @@ +#* +*.sublime-* +*~ +.#* +.project +.settings +.DS_Store +/testdata diff --git a/vendor/github.com/blevesearch/go-porterstemmer/.travis.yml b/vendor/github.com/blevesearch/go-porterstemmer/.travis.yml new file mode 100644 index 0000000000..d032f234ef --- /dev/null +++ b/vendor/github.com/blevesearch/go-porterstemmer/.travis.yml @@ -0,0 +1,16 @@ +language: go + +go: + - 1.4 + +script: + - go get golang.org/x/tools/cmd/vet + - go get golang.org/x/tools/cmd/cover + - go get github.com/mattn/goveralls + - go test -v -covermode=count -coverprofile=profile.out + - go vet + - goveralls -service drone.io -coverprofile=profile.out -repotoken $COVERALLS + +notifications: + email: + - marty.schoch@gmail.com diff --git a/vendor/github.com/blevesearch/go-porterstemmer/README.md b/vendor/github.com/blevesearch/go-porterstemmer/README.md new file mode 100644 index 0000000000..d96911ace5 --- /dev/null +++ b/vendor/github.com/blevesearch/go-porterstemmer/README.md @@ -0,0 +1,118 @@ +# This fork... + +I'm maintaining this fork because the original author was not replying to issues or pull requests. For now I plan on maintaining this fork as necessary. + +## Status + +[![Build Status](https://travis-ci.org/blevesearch/go-porterstemmer.svg?branch=master)](https://travis-ci.org/blevesearch/go-porterstemmer) + +[![Coverage Status](https://coveralls.io/repos/blevesearch/go-porterstemmer/badge.png?branch=HEAD)](https://coveralls.io/r/blevesearch/go-porterstemmer?branch=HEAD) + +# Go Porter Stemmer + +A native Go clean room implementation of the Porter Stemming Algorithm. + +This algorithm is of interest to people doing Machine Learning or +Natural Language Processing (NLP). + +This is NOT a port. This is a native Go implementation from the human-readable +description of the algorithm. + +I've tried to make it (more) efficient by NOT internally using string's, but +instead internally using []rune's and using the same (array) buffer used by +the []rune slice (and sub-slices) at all steps of the algorithm. + +For Porter Stemmer algorithm, see: + +http://tartarus.org/martin/PorterStemmer/def.txt (URL #1) + +http://tartarus.org/martin/PorterStemmer/ (URL #2) + +# Departures + +Also, since when I initially implemented it, it failed the tests at... + +http://tartarus.org/martin/PorterStemmer/voc.txt (URL #3) + +http://tartarus.org/martin/PorterStemmer/output.txt (URL #4) + +... after reading the human-readble text over and over again to try to figure out +what the error I made was (and doing all sorts of things to debug it) I came to the +conclusion that the some of these tests were wrong according to the human-readable +description of the algorithm. + +This led me to wonder if maybe other people's code that was passing these tests had +rules that were not in the human-readable description. Which led me to look at the source +code here... + +http://tartarus.org/martin/PorterStemmer/c.txt (URL #5) + +... When I looked there I noticed that there are some items marked as a "DEPARTURE", +which differ from the original algorithm. (There are 2 of these.) + +I implemented these departures, and the tests at URL #3 and URL #4 all passed. + +## Usage + +To use this Golang library, use with something like: + + package main + + import ( + "fmt" + "github.com/reiver/go-porterstemmer" + ) + + func main() { + + word := "Waxes" + + stem := porterstemmer.StemString(word) + + fmt.Printf("The word [%s] has the stem [%s].\n", word, stem) + } + +Alternatively, if you want to be a bit more efficient, use []rune slices instead, with code like: + + package main + + import ( + "fmt" + "github.com/reiver/go-porterstemmer" + ) + + func main() { + + word := []rune("Waxes") + + stem := porterstemmer.Stem(word) + + fmt.Printf("The word [%s] has the stem [%s].\n", string(word), string(stem)) + } + +Although NOTE that the above code may modify original slice (named "word" in the example) as a side +effect, for efficiency reasons. And that the slice named "stem" in the example above may be a +sub-slice of the slice named "word". + +Also alternatively, if you already know that your word is already lowercase (and you don't need +this library to lowercase your word for you) you can instead use code like: + + package main + + import ( + "fmt" + "github.com/reiver/go-porterstemmer" + ) + + func main() { + + word := []rune("waxes") + + stem := porterstemmer.StemWithoutLowerCasing(word) + + fmt.Printf("The word [%s] has the stem [%s].\n", string(word), string(stem)) + } + +Again NOTE (like with the previous example) that the above code may modify original slice (named +"word" in the example) as a side effect, for efficiency reasons. And that the slice named "stem" +in the example above may be a sub-slice of the slice named "word". diff --git a/vendor/github.com/blevesearch/segment/.gitignore b/vendor/github.com/blevesearch/segment/.gitignore new file mode 100644 index 0000000000..b4ccb07eaf --- /dev/null +++ b/vendor/github.com/blevesearch/segment/.gitignore @@ -0,0 +1,10 @@ +#* +*.sublime-* +*~ +.#* +.project +.settings +.DS_Store +/maketesttables +/workdir +/segment-fuzz.zip \ No newline at end of file diff --git a/vendor/github.com/blevesearch/segment/.travis.yml b/vendor/github.com/blevesearch/segment/.travis.yml new file mode 100644 index 0000000000..d032f234ef --- /dev/null +++ b/vendor/github.com/blevesearch/segment/.travis.yml @@ -0,0 +1,16 @@ +language: go + +go: + - 1.4 + +script: + - go get golang.org/x/tools/cmd/vet + - go get golang.org/x/tools/cmd/cover + - go get github.com/mattn/goveralls + - go test -v -covermode=count -coverprofile=profile.out + - go vet + - goveralls -service drone.io -coverprofile=profile.out -repotoken $COVERALLS + +notifications: + email: + - marty.schoch@gmail.com diff --git a/vendor/github.com/blevesearch/segment/README.md b/vendor/github.com/blevesearch/segment/README.md new file mode 100644 index 0000000000..0840962d05 --- /dev/null +++ b/vendor/github.com/blevesearch/segment/README.md @@ -0,0 +1,92 @@ +# segment + +A Go library for performing Unicode Text Segmentation +as described in [Unicode Standard Annex #29](http://www.unicode.org/reports/tr29/) + +## Features + +* Currently only segmentation at Word Boundaries is supported. + +## License + +Apache License Version 2.0 + +## Usage + +The functionality is exposed in two ways: + +1. You can use a bufio.Scanner with the SplitWords implementation of SplitFunc. +The SplitWords function will identify the appropriate word boundaries in the input +text and the Scanner will return tokens at the appropriate place. + + scanner := bufio.NewScanner(...) + scanner.Split(segment.SplitWords) + for scanner.Scan() { + tokenBytes := scanner.Bytes() + } + if err := scanner.Err(); err != nil { + t.Fatal(err) + } + +2. Sometimes you would also like information returned about the type of token. +To do this we have introduce a new type named Segmenter. It works just like Scanner +but additionally a token type is returned. + + segmenter := segment.NewWordSegmenter(...) + for segmenter.Segment() { + tokenBytes := segmenter.Bytes()) + tokenType := segmenter.Type() + } + if err := segmenter.Err(); err != nil { + t.Fatal(err) + } + +## Choosing Implementation + +By default segment does NOT use the fastest runtime implementation. The reason is that it adds approximately 5s to compilation time and may require more than 1GB of ram on the machine performing compilation. + +However, you can choose to build with the fastest runtime implementation by passing the build tag as follows: + + -tags 'prod' + +## Generating Code + +Several components in this package are generated. + +1. Several Ragel rules files are generated from Unicode properties files. +2. Ragel machine is generated from the Ragel rules. +3. Test tables are generated from the Unicode test files. + +All of these can be generated by running: + + go generate + +## Fuzzing + +There is support for fuzzing the segment library with [go-fuzz](https://github.com/dvyukov/go-fuzz). + +1. Install go-fuzz if you haven't already: + + go get github.com/dvyukov/go-fuzz/go-fuzz + go get github.com/dvyukov/go-fuzz/go-fuzz-build + +2. Build the package with go-fuzz: + + go-fuzz-build github.com/blevesearch/segment + +3. Convert the Unicode provided test cases into the initial corpus for go-fuzz: + + go test -v -run=TestGenerateWordSegmentFuzz -tags gofuzz_generate + +4. Run go-fuzz: + + go-fuzz -bin=segment-fuzz.zip -workdir=workdir + +## Status + + +[![Build Status](https://travis-ci.org/blevesearch/segment.svg?branch=master)](https://travis-ci.org/blevesearch/segment) + +[![Coverage Status](https://img.shields.io/coveralls/blevesearch/segment.svg)](https://coveralls.io/r/blevesearch/segment?branch=master) + +[![GoDoc](https://godoc.org/github.com/blevesearch/segment?status.svg)](https://godoc.org/github.com/blevesearch/segment) \ No newline at end of file diff --git a/vendor/github.com/blevesearch/segment/segment_words.rl b/vendor/github.com/blevesearch/segment/segment_words.rl new file mode 100644 index 0000000000..e69af8b214 --- /dev/null +++ b/vendor/github.com/blevesearch/segment/segment_words.rl @@ -0,0 +1,285 @@ +// Copyright (c) 2015 Couchbase, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the +// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + +// +build BUILDTAGS + +package segment + +import ( + "fmt" + "unicode/utf8" +) + +var RagelFlags = "RAGELFLAGS" + +var ParseError = fmt.Errorf("unicode word segmentation parse error") + +// Word Types +const ( + None = iota + Number + Letter + Kana + Ideo +) + +%%{ + machine s; + write data; +}%% + +func segmentWords(data []byte, maxTokens int, atEOF bool, val [][]byte, types []int) ([][]byte, []int, int, error) { + cs, p, pe := 0, 0, len(data) + cap := maxTokens + if cap < 0 { + cap = 1000 + } + if val == nil { + val = make([][]byte, 0, cap) + } + if types == nil { + types = make([]int, 0, cap) + } + + // added for scanner + ts := 0 + te := 0 + act := 0 + eof := pe + _ = ts // compiler not happy + _ = te + _ = act + + // our state + startPos := 0 + endPos := 0 + totalConsumed := 0 + %%{ + + include SCRIPTS "ragel/uscript.rl"; + include WB "ragel/uwb.rl"; + + action startToken { + startPos = p + } + + action endToken { + endPos = p + } + + action finishNumericToken { + if !atEOF { + return val, types, totalConsumed, nil + } + + val = append(val, data[startPos:endPos+1]) + types = append(types, Number) + totalConsumed = endPos+1 + if maxTokens > 0 && len(val) >= maxTokens { + return val, types, totalConsumed, nil + } + } + + action finishHangulToken { + if endPos+1 == pe && !atEOF { + return val, types, totalConsumed, nil + } else if dr, size := utf8.DecodeRune(data[endPos+1:]); dr == utf8.RuneError && size == 1 { + return val, types, totalConsumed, nil + } + + val = append(val, data[startPos:endPos+1]) + types = append(types, Letter) + totalConsumed = endPos+1 + if maxTokens > 0 && len(val) >= maxTokens { + return val, types, totalConsumed, nil + } + } + + action finishKatakanaToken { + if endPos+1 == pe && !atEOF { + return val, types, totalConsumed, nil + } else if dr, size := utf8.DecodeRune(data[endPos+1:]); dr == utf8.RuneError && size == 1 { + return val, types, totalConsumed, nil + } + + val = append(val, data[startPos:endPos+1]) + types = append(types, Ideo) + totalConsumed = endPos+1 + if maxTokens > 0 && len(val) >= maxTokens { + return val, types, totalConsumed, nil + } + } + + action finishWordToken { + if !atEOF { + return val, types, totalConsumed, nil + } + val = append(val, data[startPos:endPos+1]) + types = append(types, Letter) + totalConsumed = endPos+1 + if maxTokens > 0 && len(val) >= maxTokens { + return val, types, totalConsumed, nil + } + } + + action finishHanToken { + if endPos+1 == pe && !atEOF { + return val, types, totalConsumed, nil + } else if dr, size := utf8.DecodeRune(data[endPos+1:]); dr == utf8.RuneError && size == 1 { + return val, types, totalConsumed, nil + } + + val = append(val, data[startPos:endPos+1]) + types = append(types, Ideo) + totalConsumed = endPos+1 + if maxTokens > 0 && len(val) >= maxTokens { + return val, types, totalConsumed, nil + } + } + + action finishHiraganaToken { + if endPos+1 == pe && !atEOF { + return val, types, totalConsumed, nil + } else if dr, size := utf8.DecodeRune(data[endPos+1:]); dr == utf8.RuneError && size == 1 { + return val, types, totalConsumed, nil + } + + val = append(val, data[startPos:endPos+1]) + types = append(types, Ideo) + totalConsumed = endPos+1 + if maxTokens > 0 && len(val) >= maxTokens { + return val, types, totalConsumed, nil + } + } + + action finishNoneToken { + lastPos := startPos + for lastPos <= endPos { + _, size := utf8.DecodeRune(data[lastPos:]) + lastPos += size + } + endPos = lastPos -1 + p = endPos + + if endPos+1 == pe && !atEOF { + return val, types, totalConsumed, nil + } else if dr, size := utf8.DecodeRune(data[endPos+1:]); dr == utf8.RuneError && size == 1 { + return val, types, totalConsumed, nil + } + // otherwise, consume this as well + val = append(val, data[startPos:endPos+1]) + types = append(types, None) + totalConsumed = endPos+1 + if maxTokens > 0 && len(val) >= maxTokens { + return val, types, totalConsumed, nil + } + } + + HangulEx = Hangul ( Extend | Format )*; + HebrewOrALetterEx = ( Hebrew_Letter | ALetter ) ( Extend | Format )*; + NumericEx = Numeric ( Extend | Format )*; + KatakanaEx = Katakana ( Extend | Format )*; + MidLetterEx = ( MidLetter | MidNumLet | Single_Quote ) ( Extend | Format )*; + MidNumericEx = ( MidNum | MidNumLet | Single_Quote ) ( Extend | Format )*; + ExtendNumLetEx = ExtendNumLet ( Extend | Format )*; + HanEx = Han ( Extend | Format )*; + HiraganaEx = Hiragana ( Extend | Format )*; + SingleQuoteEx = Single_Quote ( Extend | Format )*; + DoubleQuoteEx = Double_Quote ( Extend | Format )*; + HebrewLetterEx = Hebrew_Letter ( Extend | Format )*; + RegionalIndicatorEx = Regional_Indicator ( Extend | Format )*; + NLCRLF = Newline | CR | LF; + OtherEx = ^(NLCRLF) ( Extend | Format )* ; + + # UAX#29 WB8. Numeric × Numeric + # WB11. Numeric (MidNum | MidNumLet | Single_Quote) × Numeric + # WB12. Numeric × (MidNum | MidNumLet | Single_Quote) Numeric + # WB13a. (ALetter | Hebrew_Letter | Numeric | Katakana | ExtendNumLet) × ExtendNumLet + # WB13b. ExtendNumLet × (ALetter | Hebrew_Letter | Numeric | Katakana) + # + WordNumeric = ( ( ExtendNumLetEx )* NumericEx ( ( ( ExtendNumLetEx )* | MidNumericEx ) NumericEx )* ( ExtendNumLetEx )* ) >startToken @endToken; + + # subset of the below for typing purposes only! + WordHangul = ( HangulEx )+ >startToken @endToken; + WordKatakana = ( KatakanaEx )+ >startToken @endToken; + + # UAX#29 WB5. (ALetter | Hebrew_Letter) × (ALetter | Hebrew_Letter) + # WB6. (ALetter | Hebrew_Letter) × (MidLetter | MidNumLet | Single_Quote) (ALetter | Hebrew_Letter) + # WB7. (ALetter | Hebrew_Letter) (MidLetter | MidNumLet | Single_Quote) × (ALetter | Hebrew_Letter) + # WB7a. Hebrew_Letter × Single_Quote + # WB7b. Hebrew_Letter × Double_Quote Hebrew_Letter + # WB7c. Hebrew_Letter Double_Quote × Hebrew_Letter + # WB9. (ALetter | Hebrew_Letter) × Numeric + # WB10. Numeric × (ALetter | Hebrew_Letter) + # WB13. Katakana × Katakana + # WB13a. (ALetter | Hebrew_Letter | Numeric | Katakana | ExtendNumLet) × ExtendNumLet + # WB13b. ExtendNumLet × (ALetter | Hebrew_Letter | Numeric | Katakana) + # + # Marty -deviated here to allow for (ExtendNumLetEx x ExtendNumLetEx) part of 13a + # + Word = ( ( ExtendNumLetEx )* ( KatakanaEx ( ( ExtendNumLetEx )* KatakanaEx )* + | ( HebrewLetterEx ( SingleQuoteEx | DoubleQuoteEx HebrewLetterEx ) + | NumericEx ( ( ( ExtendNumLetEx )* | MidNumericEx ) NumericEx )* + | HebrewOrALetterEx ( ( ( ExtendNumLetEx )* | MidLetterEx ) HebrewOrALetterEx )* + |ExtendNumLetEx + )+ + ) + ( + ( ExtendNumLetEx )+ ( KatakanaEx ( ( ExtendNumLetEx )* KatakanaEx )* + | ( HebrewLetterEx ( SingleQuoteEx | DoubleQuoteEx HebrewLetterEx ) + | NumericEx ( ( ( ExtendNumLetEx )* | MidNumericEx ) NumericEx )* + | HebrewOrALetterEx ( ( ( ExtendNumLetEx )* | MidLetterEx ) HebrewOrALetterEx )* + )+ + ) + )* ExtendNumLetEx*) >startToken @endToken; + + # UAX#29 WB14. Any ÷ Any + WordHan = HanEx >startToken @endToken; + WordHiragana = HiraganaEx >startToken @endToken; + + WordExt = ( ( Extend | Format )* ) >startToken @endToken; # maybe plus not star + + WordCRLF = (CR LF) >startToken @endToken; + + WordCR = CR >startToken @endToken; + + WordLF = LF >startToken @endToken; + + WordNL = Newline >startToken @endToken; + + WordRegional = (RegionalIndicatorEx+) >startToken @endToken; + + Other = OtherEx >startToken @endToken; + + main := |* + WordNumeric => finishNumericToken; + WordHangul => finishHangulToken; + WordKatakana => finishKatakanaToken; + Word => finishWordToken; + WordHan => finishHanToken; + WordHiragana => finishHiraganaToken; + WordRegional =>finishNoneToken; + WordCRLF => finishNoneToken; + WordCR => finishNoneToken; + WordLF => finishNoneToken; + WordNL => finishNoneToken; + WordExt => finishNoneToken; + Other => finishNoneToken; + *|; + + write init; + write exec; + }%% + + if cs < s_first_final { + return val, types, totalConsumed, ParseError + } + + return val, types, totalConsumed, nil +} diff --git a/vendor/github.com/boombuler/barcode/README.md b/vendor/github.com/boombuler/barcode/README.md new file mode 100644 index 0000000000..85c34d6390 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/README.md @@ -0,0 +1,18 @@ +##Introduction## +This is a package for GO which can be used to create different types of barcodes. + +##Supported Barcode Types## +* Aztec Code +* Codabar +* Code 128 +* Code 39 +* EAN 8 +* EAN 13 +* Datamatrix +* QR Codes +* 2 of 5 + +##Documentation## +See [GoDoc](https://godoc.org/github.com/boombuler/barcode) + +To create a barcode use the Encode function from one of the subpackages. diff --git a/vendor/github.com/chaseadamsio/goorgeous/.gitignore b/vendor/github.com/chaseadamsio/goorgeous/.gitignore new file mode 100644 index 0000000000..496ee2ca6a --- /dev/null +++ b/vendor/github.com/chaseadamsio/goorgeous/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/vendor/github.com/chaseadamsio/goorgeous/.travis.yml b/vendor/github.com/chaseadamsio/goorgeous/.travis.yml new file mode 100644 index 0000000000..31dca02817 --- /dev/null +++ b/vendor/github.com/chaseadamsio/goorgeous/.travis.yml @@ -0,0 +1,12 @@ +language: go + +go: + - 1.7 + +before_install: + - go get golang.org/x/tools/cmd/cover + - go get github.com/mattn/goveralls + +script: + - go test -v -covermode=count -coverprofile=coverage.out + - $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci diff --git a/vendor/github.com/chaseadamsio/goorgeous/README.org b/vendor/github.com/chaseadamsio/goorgeous/README.org new file mode 100644 index 0000000000..37e0f2ec73 --- /dev/null +++ b/vendor/github.com/chaseadamsio/goorgeous/README.org @@ -0,0 +1,66 @@ +#+TITLE: chaseadamsio/goorgeous + +[[https://travis-ci.org/chaseadamsio/goorgeous.svg?branch=master]] +[[https://coveralls.io/repos/github/chaseadamsio/goorgeous/badge.svg?branch=master]] + +/goorgeous is a Go Org to HTML Parser./ + +[[file:gopher_small.gif]] + +*Pronounced: Go? Org? Yes!* + +#+BEGIN_QUOTE +"Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system." + +- [[orgmode.org]] +#+END_QUOTE + +The purpose of this package is to come as close as possible as parsing an =*.org= document into HTML, the same way one might publish [[http://orgmode.org/worg/org-tutorials/org-publish-html-tutorial.html][with org-publish-html from Emacs]]. + +* Installation + +#+BEGIN_SRC sh + go get -u github.com/chaseadamsio/goorgeous +#+END_SRC + +* Usage + +** Org Headers + +To retrieve the headers from a =[]byte=, call =OrgHeaders= and it will return a =map[string]interface{}=: + +#+BEGIN_SRC go + input := "#+title: goorgeous\n* Some Headline\n" + out := goorgeous.OrgHeaders(input) +#+END_SRC + +#+BEGIN_SRC go + map[string]interface{}{ + "title": "goorgeous" + } +#+END_SRC + +** Org Content + +After importing =github.com/chaseadamsio/goorgeous=, you can call =Org= with a =[]byte= and it will return an =html= version of the content as a =[]byte= + +#+BEGIN_SRC go + input := "#+TITLE: goorgeous\n* Some Headline\n" + out := goorgeous.Org(input) +#+END_SRC + +=out= will be: + +#+BEGIN_SRC html +

Some Headline

/n +#+END_SRC + +* Why? + +First off, I've become an unapologetic user of Emacs & ever since finding =org-mode= I use it for anything having to do with writing content, organizing my life and keeping documentation of my days/weeks/months. + +Although I like Emacs & =emacs-lisp=, I publish all of my html sites with [[https://gohugo.io][Hugo Static Site Generator]] and wanted to be able to write my content in =org-mode= in Emacs rather than markdown. + +Hugo's implementation of templating and speed are unmatched, so the only way I knew for sure I could continue to use Hugo and write in =org-mode= seamlessly was to write a golang parser for org content and submit a PR for Hugo to use it. +* Acknowledgements +I leaned heavily on russross' [[https://github.com/russross/blackfriday][blackfriday markdown renderer]] as both an example of how to write a parser (with some updates to leverage the go we know today) and reusing the blackfriday HTML Renderer so I didn't have to write my own! diff --git a/vendor/github.com/chaseadamsio/goorgeous/gopher.gif b/vendor/github.com/chaseadamsio/goorgeous/gopher.gif new file mode 100644 index 0000000000..be7567e3cf Binary files /dev/null and b/vendor/github.com/chaseadamsio/goorgeous/gopher.gif differ diff --git a/vendor/github.com/chaseadamsio/goorgeous/gopher_small.gif b/vendor/github.com/chaseadamsio/goorgeous/gopher_small.gif new file mode 100644 index 0000000000..1cd31fdd0c Binary files /dev/null and b/vendor/github.com/chaseadamsio/goorgeous/gopher_small.gif differ diff --git a/vendor/github.com/couchbase/gomemcached/.gitignore b/vendor/github.com/couchbase/gomemcached/.gitignore new file mode 100644 index 0000000000..f75d85a841 --- /dev/null +++ b/vendor/github.com/couchbase/gomemcached/.gitignore @@ -0,0 +1,6 @@ +#* +*.[68] +*~ +*.swp +/gocache/gocache +c.out diff --git a/vendor/github.com/couchbase/gomemcached/README.markdown b/vendor/github.com/couchbase/gomemcached/README.markdown new file mode 100644 index 0000000000..5e9b2de5be --- /dev/null +++ b/vendor/github.com/couchbase/gomemcached/README.markdown @@ -0,0 +1,32 @@ +# gomemcached + +This is a memcached binary protocol toolkit in [go][go]. + +It provides client and server functionality as well as a little sample +server showing how I might make a server if I valued purity over +performance. + +## Server Design + +
+ overview +
+ +The basic design can be seen in [gocache]. A [storage +server][storage] is run as a goroutine that receives a `MCRequest` on +a channel, and then issues an `MCResponse` to a channel contained +within the request. + +Each connection is a separate goroutine, of course, and is responsible +for all IO for that connection until the connection drops or the +`dataServer` decides it's stupid and sends a fatal response back over +the channel. + +There is currently no work at all in making the thing perform (there +are specific areas I know need work). This is just my attempt to +learn the language somewhat. + +[go]: http://golang.org/ +[gocache]: gomemcached/blob/master/gocache/gocache.go +[storage]: gomemcached/blob/master/gocache/mc_storage.go diff --git a/vendor/github.com/couchbase/vellum/.travis.yml b/vendor/github.com/couchbase/vellum/.travis.yml new file mode 100644 index 0000000000..229edf2834 --- /dev/null +++ b/vendor/github.com/couchbase/vellum/.travis.yml @@ -0,0 +1,22 @@ +sudo: false + +language: go + +go: + - "1.9.x" + - "1.10.x" + - "1.11.x" + +script: + - go get github.com/mattn/goveralls + - go get -u github.com/kisielk/errcheck + - go test -v $(go list ./... | grep -v vendor/) + - go test -race + - go vet + - errcheck + - go test -coverprofile=profile.out -covermode=count + - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then goveralls -service=travis-ci -coverprofile=profile.out -repotoken $COVERALLS; fi' + +notifications: + email: + - marty.schoch@gmail.com diff --git a/vendor/github.com/couchbase/vellum/CONTRIBUTING.md b/vendor/github.com/couchbase/vellum/CONTRIBUTING.md new file mode 100644 index 0000000000..b85ec82b6b --- /dev/null +++ b/vendor/github.com/couchbase/vellum/CONTRIBUTING.md @@ -0,0 +1,16 @@ +# Contributing to Vellum + +We look forward to your contributions, but ask that you first review these guidelines. + +### Sign the CLA + +As Vellum is a Couchbase project we require contributors accept the [Couchbase Contributor License Agreement](http://review.couchbase.org/static/individual_agreement.html). To sign this agreement log into the Couchbase [code review tool](http://review.couchbase.org/). The Vellum project does not use this code review tool but it is still used to track acceptance of the contributor license agreements. + +### Submitting a Pull Request + +All types of contributions are welcome, but please keep the following in mind: + +- If you're planning a large change, you should really discuss it in a github issue first. This helps avoid duplicate effort and spending time on something that may not be merged. +- Existing tests should continue to pass, new tests for the contribution are nice to have. +- All code should have gone through `go fmt` +- All code should pass `go vet` diff --git a/vendor/github.com/couchbase/vellum/README.md b/vendor/github.com/couchbase/vellum/README.md new file mode 100644 index 0000000000..907b8b3a8a --- /dev/null +++ b/vendor/github.com/couchbase/vellum/README.md @@ -0,0 +1,183 @@ +# ![vellum](docs/logo.png) vellum + +[![Build Status](https://travis-ci.org/couchbase/vellum.svg?branch=master)](https://travis-ci.org/couchbase/vellum) +[![Coverage Status](https://coveralls.io/repos/github/couchbase/vellum/badge.svg?branch=master)](https://coveralls.io/github/couchbase/vellum?branch=master) +[![GoDoc](https://godoc.org/github.com/couchbase/vellum?status.svg)](https://godoc.org/github.com/couchbase/vellum) +[![Go Report Card](https://goreportcard.com/badge/github.com/couchbase/vellum)](https://goreportcard.com/report/github.com/couchbase/vellum) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) + +A Go library implementing an FST (finite state transducer) capable of: + - mapping between keys ([]byte) and a value (uint64) + - enumerating keys in lexicographic order + +Some additional goals of this implementation: + - bounded memory use while building the FST + - streaming out FST data while building + - mmap FST runtime to support very large FTSs (optional) + +## Usage + +### Building an FST + +To build an FST, create a new builder using the `New()` method. This method takes an `io.Writer` as an argument. As the FST is being built, data will be streamed to the writer as soon as possible. With this builder you **MUST** insert keys in lexicographic order. Inserting keys out of order will result in an error. After inserting the last key into the builder, you **MUST** call `Close()` on the builder. This will flush all remaining data to the underlying writer. + +In memory: +```go + var buf bytes.Buffer + builder, err := vellum.New(&buf, nil) + if err != nil { + log.Fatal(err) + } +``` + +To disk: +```go + f, err := os.Create("/tmp/vellum.fst") + if err != nil { + log.Fatal(err) + } + builder, err := vellum.New(f, nil) + if err != nil { + log.Fatal(err) + } +``` + +**MUST** insert keys in lexicographic order: +```go +err = builder.Insert([]byte("cat"), 1) +if err != nil { + log.Fatal(err) +} + +err = builder.Insert([]byte("dog"), 2) +if err != nil { + log.Fatal(err) +} + +err = builder.Insert([]byte("fish"), 3) +if err != nil { + log.Fatal(err) +} + +err = builder.Close() +if err != nil { + log.Fatal(err) +} +``` + +### Using an FST + +After closing the builder, the data can be used to instantiate an FST. If the data was written to disk, you can use the `Open()` method to mmap the file. If the data is already in memory, or you wish to load/mmap the data yourself, you can instantiate the FST with the `Load()` method. + +Load in memory: +```go + fst, err := vellum.Load(buf.Bytes()) + if err != nil { + log.Fatal(err) + } +``` + +Open from disk: +```go + fst, err := vellum.Open("/tmp/vellum.fst") + if err != nil { + log.Fatal(err) + } +``` + +Get key/value: +```go + val, exists, err = fst.Get([]byte("dog")) + if err != nil { + log.Fatal(err) + } + if exists { + fmt.Printf("contains dog with val: %d\n", val) + } else { + fmt.Printf("does not contain dog") + } +``` + +Iterate key/values: +```go + itr, err := fst.Iterator(startKeyInclusive, endKeyExclusive) + for err == nil { + key, val := itr.Current() + fmt.Printf("contains key: %s val: %d", key, val) + err = itr.Next() + } + if err != nil { + log.Fatal(err) + } +``` + +### How does the FST get built? + +A full example of the implementation is beyond the scope of this README, but let's consider a small example where we want to insert 3 key/value pairs. + +First we insert "are" with the value 4. + +![step1](docs/demo1.png) + +Next, we insert "ate" with the value 2. + +![step2](docs/demo2.png) + +Notice how the values associated with the transitions were adjusted so that by summing them while traversing we still get the expected value. + +At this point, we see that state 5 looks like state 3, and state 4 looks like state 2. But, we cannot yet combine them because future inserts could change this. + +Now, we insert "see" with value 3. Once it has been added, we now know that states 5 and 4 can longer change. Since they are identical to 3 and 2, we replace them. + +![step3](docs/demo3.png) + +Again, we see that states 7 and 8 appear to be identical to 2 and 3. + +Having inserted our last key, we call `Close()` on the builder. + +![step4](docs/demo4.png) + +Now, states 7 and 8 can safely be replaced with 2 and 3. + +For additional information, see the references at the bottom of this document. + +### What does the serialized format look like? + +We've broken out a separate document on the [vellum disk format v1](docs/format.md). + +### What if I want to use this on a system that doesn't have mmap? + +The mmap library itself is guarded with system/architecture build tags, but we've also added an additional build tag in vellum. If you'd like to Open() a file based representation of an FST, but not use mmap, you can build the library with the `nommap` build tag. NOTE: if you do this, the entire FST will be read into memory. + +### Can I use this with Unicode strings? + +Yes, however this implementation is only aware of the byte representation you choose. In order to find matches, you must work with some canonical byte representation of the string. In the future, some encoding-aware traversals may be possible on top of the lower-level byte transitions. + +### How did this library come to be? + +In my work on the [Bleve](https://github.com/blevesearch/bleve) project I became aware of the power of the FST for many search-related tasks. The obvious starting point for such a thing in Go was the [mafsa](https://github.com/smartystreets/mafsa) project. While working with mafsa I encountered some issues. First, it did not stream data to disk while building. Second, it chose to use a rune as the fundamental unit of transition in the FST, but I felt using a byte would be more powerful in the end. My hope is that higher-level encoding-aware traversals will be possible when necessary. Finally, as I reported bugs and submitted PRs I learned that the mafsa project was mainly a research project and no longer being maintained. I wanted to build something that could be used in production. As the project advanced more and more techniques from the [BurntSushi/fst](https://github.com/BurntSushi/fst) were adapted to our implementation. + +### Are there tools to work with vellum files? + +Under the cmd/vellum subdirectory, there's a command-line tool which +features subcommands that can allow you to create, inspect and query +vellum files. + +### How can I generate a state transition diagram from a vellum file? + +The vellum command-line tool has a "dot" subcommand that can emit +graphviz dot output data from an input vellum file. The dot file can +in turn be converted into an image using graphviz tools. Example... + + $ vellum dot myFile.vellum > output.dot + $ dot -Tpng output.dot -o output.png + +## Related Work + +Much credit goes to two existing projects: + - [mafsa](https://github.com/smartystreets/mafsa) + - [BurntSushi/fst](https://github.com/BurntSushi/fst) + +Most of the original implementation here started with my digging into the internals of mafsa. As the implementation progressed, I continued to borrow ideas/approaches from the BurntSushi/fst library as well. + +For a great introduction to this topic, please read the blog post [Index 1,600,000,000 Keys with Automata and Rust](http://blog.burntsushi.net/transducers/) diff --git a/vendor/github.com/couchbase/vellum/levenshtein2/README.md b/vendor/github.com/couchbase/vellum/levenshtein2/README.md new file mode 100644 index 0000000000..582b69c77e --- /dev/null +++ b/vendor/github.com/couchbase/vellum/levenshtein2/README.md @@ -0,0 +1,33 @@ +# levenshtein +levenshtein automaton + +This package makes it fast and simple to build a finite determinic automaton that computes the levenshtein distance from a given string. + +# Sample usage: + +``` +// build a re-usable builder +lb := NewLevenshteinAutomatonBuilder(2, false) + +origTerm := "couchbasefts" +dfa := lb.BuildDfa("couchbases", 2) +ed := dfa.eval([]byte(origTerm)) +if ed.distance() != 2 { + log.Errorf("expected distance 2, actual: %d", ed.distance()) +} + +``` + +This implementation is inspired by [blog post](https://fulmicoton.com/posts/levenshtein/) and is intended to be +a port of original rust implementation: https://github.com/tantivy-search/levenshtein-automata + + +Micro Benchmark Results against the current vellum/levenshtein is as below. + +``` +BenchmarkNewEditDistance1-8 30000 52684 ns/op 89985 B/op 295 allocs/op +BenchmarkOlderEditDistance1-8 10000 132931 ns/op 588892 B/op 363 allocs/op + +BenchmarkNewEditDistance2-8 10000 199127 ns/op 377532 B/op 1019 allocs/op +BenchmarkOlderEditDistance2-8 2000 988109 ns/op 4236609 B/op 1898 allocs/op +``` diff --git a/vendor/github.com/couchbaselabs/go-couchbase/.gitignore b/vendor/github.com/couchbaselabs/go-couchbase/.gitignore new file mode 100644 index 0000000000..eda885ce8d --- /dev/null +++ b/vendor/github.com/couchbaselabs/go-couchbase/.gitignore @@ -0,0 +1,14 @@ +#* +*.6 +*.a +*~ +*.swp +/examples/basic/basic +/hello/hello +/populate/populate +/tools/view2go/view2go +/tools/loadfile/loadfile +gotags.files +TAGS +6.out +_* diff --git a/vendor/github.com/couchbaselabs/go-couchbase/.travis.yml b/vendor/github.com/couchbaselabs/go-couchbase/.travis.yml new file mode 100644 index 0000000000..4ecafb1894 --- /dev/null +++ b/vendor/github.com/couchbaselabs/go-couchbase/.travis.yml @@ -0,0 +1,5 @@ +language: go +install: go get -v -d ./... && go build -v ./... +script: go test -v ./... + +go: 1.1.1 diff --git a/vendor/github.com/couchbaselabs/go-couchbase/README.markdown b/vendor/github.com/couchbaselabs/go-couchbase/README.markdown new file mode 100644 index 0000000000..bf5fe49421 --- /dev/null +++ b/vendor/github.com/couchbaselabs/go-couchbase/README.markdown @@ -0,0 +1,37 @@ +# A smart client for couchbase in go + +This is a *unoffical* version of a Couchbase Golang client. If you are +looking for the *Offical* Couchbase Golang client please see + [CB-go])[https://github.com/couchbaselabs/gocb]. + +This is an evolving package, but does provide a useful interface to a +[couchbase](http://www.couchbase.com/) server including all of the +pool/bucket discovery features, compatible key distribution with other +clients, and vbucket motion awareness so application can continue to +operate during rebalances. + +It also supports view querying with source node randomization so you +don't bang on all one node to do all the work. + +## Install + + go get github.com/couchbase/go-couchbase + +## Example + + c, err := couchbase.Connect("http://dev-couchbase.example.com:8091/") + if err != nil { + log.Fatalf("Error connecting: %v", err) + } + + pool, err := c.GetPool("default") + if err != nil { + log.Fatalf("Error getting pool: %v", err) + } + + bucket, err := pool.GetBucket("default") + if err != nil { + log.Fatalf("Error getting bucket: %v", err) + } + + bucket.Set("someKey", 0, []string{"an", "example", "list"}) diff --git a/vendor/github.com/davecgh/go-spew/LICENSE b/vendor/github.com/davecgh/go-spew/LICENSE index c836416192..bc52e96f2b 100644 --- a/vendor/github.com/davecgh/go-spew/LICENSE +++ b/vendor/github.com/davecgh/go-spew/LICENSE @@ -2,7 +2,7 @@ ISC License Copyright (c) 2012-2016 Dave Collins -Permission to use, copy, modify, and distribute this software for any +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. diff --git a/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/davecgh/go-spew/spew/bypass.go index 8a4a6589a2..792994785e 100644 --- a/vendor/github.com/davecgh/go-spew/spew/bypass.go +++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go @@ -16,7 +16,9 @@ // when the code is not running on Google App Engine, compiled by GopherJS, and // "-tags safe" is not added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. -// +build !js,!appengine,!safe,!disableunsafe +// Go versions prior to 1.4 are disabled because they use a different layout +// for interfaces which make the implementation of unsafeReflectValue more complex. +// +build !js,!appengine,!safe,!disableunsafe,go1.4 package spew @@ -34,80 +36,49 @@ const ( ptrSize = unsafe.Sizeof((*byte)(nil)) ) -var ( - // offsetPtr, offsetScalar, and offsetFlag are the offsets for the - // internal reflect.Value fields. These values are valid before golang - // commit ecccf07e7f9d which changed the format. The are also valid - // after commit 82f48826c6c7 which changed the format again to mirror - // the original format. Code in the init function updates these offsets - // as necessary. - offsetPtr = uintptr(ptrSize) - offsetScalar = uintptr(0) - offsetFlag = uintptr(ptrSize * 2) +type flag uintptr - // flagKindWidth and flagKindShift indicate various bits that the - // reflect package uses internally to track kind information. - // - // flagRO indicates whether or not the value field of a reflect.Value is - // read-only. - // - // flagIndir indicates whether the value field of a reflect.Value is - // the actual data or a pointer to the data. - // - // These values are valid before golang commit 90a7c3c86944 which - // changed their positions. Code in the init function updates these - // flags as necessary. - flagKindWidth = uintptr(5) - flagKindShift = uintptr(flagKindWidth - 1) - flagRO = uintptr(1 << 0) - flagIndir = uintptr(1 << 1) +var ( + // flagRO indicates whether the value field of a reflect.Value + // is read-only. + flagRO flag + + // flagAddr indicates whether the address of the reflect.Value's + // value may be taken. + flagAddr flag ) -func init() { - // Older versions of reflect.Value stored small integers directly in the - // ptr field (which is named val in the older versions). Versions - // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named - // scalar for this purpose which unfortunately came before the flag - // field, so the offset of the flag field is different for those - // versions. - // - // This code constructs a new reflect.Value from a known small integer - // and checks if the size of the reflect.Value struct indicates it has - // the scalar field. When it does, the offsets are updated accordingly. - vv := reflect.ValueOf(0xf00) - if unsafe.Sizeof(vv) == (ptrSize * 4) { - offsetScalar = ptrSize * 2 - offsetFlag = ptrSize * 3 - } +// flagKindMask holds the bits that make up the kind +// part of the flags field. In all the supported versions, +// it is in the lower 5 bits. +const flagKindMask = flag(0x1f) - // Commit 90a7c3c86944 changed the flag positions such that the low - // order bits are the kind. This code extracts the kind from the flags - // field and ensures it's the correct type. When it's not, the flag - // order has been changed to the newer format, so the flags are updated - // accordingly. - upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) - upfv := *(*uintptr)(upf) - flagKindMask := uintptr((1<>flagKindShift != uintptr(reflect.Int) { - flagKindShift = 0 - flagRO = 1 << 5 - flagIndir = 1 << 6 +// Different versions of Go have used different +// bit layouts for the flags type. This table +// records the known combinations. +var okFlags = []struct { + ro, addr flag +}{{ + // From Go 1.4 to 1.5 + ro: 1 << 5, + addr: 1 << 7, +}, { + // Up to Go tip. + ro: 1<<5 | 1<<6, + addr: 1 << 8, +}} - // Commit adf9b30e5594 modified the flags to separate the - // flagRO flag into two bits which specifies whether or not the - // field is embedded. This causes flagIndir to move over a bit - // and means that flagRO is the combination of either of the - // original flagRO bit and the new bit. - // - // This code detects the change by extracting what used to be - // the indirect bit to ensure it's set. When it's not, the flag - // order has been changed to the newer format, so the flags are - // updated accordingly. - if upfv&flagIndir == 0 { - flagRO = 3 << 5 - flagIndir = 1 << 7 - } +var flagValOffset = func() uintptr { + field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") + if !ok { + panic("reflect.Value has no flag field") } + return field.Offset +}() + +// flagField returns a pointer to the flag field of a reflect.Value. +func flagField(v *reflect.Value) *flag { + return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset)) } // unsafeReflectValue converts the passed reflect.Value into a one that bypasses @@ -119,34 +90,56 @@ func init() { // This allows us to check for implementations of the Stringer and error // interfaces to be used for pretty printing ordinarily unaddressable and // inaccessible values such as unexported struct fields. -func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { - indirects := 1 - vt := v.Type() - upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) - rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) - if rvf&flagIndir != 0 { - vt = reflect.PtrTo(v.Type()) - indirects++ - } else if offsetScalar != 0 { - // The value is in the scalar field when it's not one of the - // reference types. - switch vt.Kind() { - case reflect.Uintptr: - case reflect.Chan: - case reflect.Func: - case reflect.Map: - case reflect.Ptr: - case reflect.UnsafePointer: - default: - upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + - offsetScalar) +func unsafeReflectValue(v reflect.Value) reflect.Value { + if !v.IsValid() || (v.CanInterface() && v.CanAddr()) { + return v + } + flagFieldPtr := flagField(&v) + *flagFieldPtr &^= flagRO + *flagFieldPtr |= flagAddr + return v +} + +// Sanity checks against future reflect package changes +// to the type or semantics of the Value.flag field. +func init() { + field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") + if !ok { + panic("reflect.Value has no flag field") + } + if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() { + panic("reflect.Value flag field has changed kind") + } + type t0 int + var t struct { + A t0 + // t0 will have flagEmbedRO set. + t0 + // a will have flagStickyRO set + a t0 + } + vA := reflect.ValueOf(t).FieldByName("A") + va := reflect.ValueOf(t).FieldByName("a") + vt0 := reflect.ValueOf(t).FieldByName("t0") + + // Infer flagRO from the difference between the flags + // for the (otherwise identical) fields in t. + flagPublic := *flagField(&vA) + flagWithRO := *flagField(&va) | *flagField(&vt0) + flagRO = flagPublic ^ flagWithRO + + // Infer flagAddr from the difference between a value + // taken from a pointer and not. + vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A") + flagNoPtr := *flagField(&vA) + flagPtr := *flagField(&vPtrA) + flagAddr = flagNoPtr ^ flagPtr + + // Check that the inferred flags tally with one of the known versions. + for _, f := range okFlags { + if flagRO == f.ro && flagAddr == f.addr { + return } } - - pv := reflect.NewAt(vt, upv) - rv = pv - for i := 0; i < indirects; i++ { - rv = rv.Elem() - } - return rv + panic("reflect.Value read-only flag has changed semantics") } diff --git a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go index 1fe3cf3d5d..205c28d68c 100644 --- a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go +++ b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go @@ -16,7 +16,7 @@ // when the code is running on Google App Engine, compiled by GopherJS, or // "-tags safe" is added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. -// +build js appengine safe disableunsafe +// +build js appengine safe disableunsafe !go1.4 package spew diff --git a/vendor/github.com/davecgh/go-spew/spew/common.go b/vendor/github.com/davecgh/go-spew/spew/common.go index 7c519ff47a..1be8ce9457 100644 --- a/vendor/github.com/davecgh/go-spew/spew/common.go +++ b/vendor/github.com/davecgh/go-spew/spew/common.go @@ -180,7 +180,7 @@ func printComplex(w io.Writer, c complex128, floatPrecision int) { w.Write(closeParenBytes) } -// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x' +// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x' // prefix to Writer w. func printHexPtr(w io.Writer, p uintptr) { // Null pointer. diff --git a/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/davecgh/go-spew/spew/dump.go index df1d582a72..f78d89fc1f 100644 --- a/vendor/github.com/davecgh/go-spew/spew/dump.go +++ b/vendor/github.com/davecgh/go-spew/spew/dump.go @@ -35,16 +35,16 @@ var ( // cCharRE is a regular expression that matches a cgo char. // It is used to detect character arrays to hexdump them. - cCharRE = regexp.MustCompile("^.*\\._Ctype_char$") + cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`) // cUnsignedCharRE is a regular expression that matches a cgo unsigned // char. It is used to detect unsigned character arrays to hexdump // them. - cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$") + cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`) // cUint8tCharRE is a regular expression that matches a cgo uint8_t. // It is used to detect uint8_t arrays to hexdump them. - cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$") + cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`) ) // dumpState contains information about the state of a dump operation. @@ -143,10 +143,10 @@ func (d *dumpState) dumpPtr(v reflect.Value) { // Display dereferenced value. d.w.Write(openParenBytes) switch { - case nilFound == true: + case nilFound: d.w.Write(nilAngleBytes) - case cycleFound == true: + case cycleFound: d.w.Write(circularBytes) default: diff --git a/vendor/github.com/davecgh/go-spew/spew/format.go b/vendor/github.com/davecgh/go-spew/spew/format.go index c49875bacb..b04edb7d7a 100644 --- a/vendor/github.com/davecgh/go-spew/spew/format.go +++ b/vendor/github.com/davecgh/go-spew/spew/format.go @@ -182,10 +182,10 @@ func (f *formatState) formatPtr(v reflect.Value) { // Display dereferenced value. switch { - case nilFound == true: + case nilFound: f.fs.Write(nilAngleBytes) - case cycleFound == true: + case cycleFound: f.fs.Write(circularShortBytes) default: diff --git a/vendor/github.com/denisenkom/go-mssqldb/README.md b/vendor/github.com/denisenkom/go-mssqldb/README.md new file mode 100644 index 0000000000..8570ae9f61 --- /dev/null +++ b/vendor/github.com/denisenkom/go-mssqldb/README.md @@ -0,0 +1,95 @@ +# A pure Go MSSQL driver for Go's database/sql package + +## Install + + go get github.com/denisenkom/go-mssqldb + +## Tests + +`go test` is used for testing. A running instance of MSSQL server is required. +Environment variables are used to pass login information. + +Example: + + env HOST=localhost SQLUSER=sa SQLPASSWORD=sa DATABASE=test go test + +## Connection Parameters + +* "server" - host or host\instance (default localhost) +* "port" - used only when there is no instance in server (default 1433) +* "failoverpartner" - host or host\instance (default is no partner). +* "failoverport" - used only when there is no instance in failoverpartner (default 1433) +* "user id" - enter the SQL Server Authentication user id or the Windows Authentication user id in the DOMAIN\User format. On Windows, if user id is empty or missing Single-Sign-On is used. +* "password" +* "database" +* "connection timeout" - in seconds (default is 30) +* "dial timeout" - in seconds (default is 5) +* "keepAlive" - in seconds; 0 to disable (default is 0) +* "log" - logging flags (default 0/no logging, 63 for full logging) + * 1 log errors + * 2 log messages + * 4 log rows affected + * 8 trace sql statements + * 16 log statement parameters + * 32 log transaction begin/end +* "encrypt" + * disable - Data send between client and server is not encrypted. + * false - Data sent between client and server is not encrypted beyond the login packet. (Default) + * true - Data sent between client and server is encrypted. +* "TrustServerCertificate" + * false - Server certificate is checked. Default is false if encypt is specified. + * true - Server certificate is not checked. Default is true if encrypt is not specified. If trust server certificate is true, driver accepts any certificate presented by the server and any host name in that certificate. In this mode, TLS is susceptible to man-in-the-middle attacks. This should be used only for testing. +* "certificate" - The file that contains the public key certificate of the CA that signed the SQL Server certificate. The specified certificate overrides the go platform specific CA certificates. +* "hostNameInCertificate" - Specifies the Common Name (CN) in the server certificate. Default value is the server host. +* "ServerSPN" - The kerberos SPN (Service Principal Name) for the server. Default is MSSQLSvc/host:port. +* "Workstation ID" - The workstation name (default is the host name) +* "app name" - The application name (default is go-mssqldb) +* "ApplicationIntent" - Can be given the value "ReadOnly" to initiate a read-only connection to an Availability Group listener. + +Example: + +```go + db, err := sql.Open("mssql", "server=localhost;user id=sa") +``` + +## Statement Parameters + +In the SQL statement text, literals may be replaced by a parameter that matches one of the following: + +* ? +* ?nnn +* :nnn +* $nnn + +where nnn represents an integer that specifies a 1-indexed positional parameter. Ex: + +```go +db.Query("SELECT * FROM t WHERE a = ?3, b = ?2, c = ?1", "x", "y", "z") +``` + +will expand to roughly + +```sql +SELECT * FROM t WHERE a = 'z', b = 'y', c = 'x' +``` + + +## Features + +* Can be used with SQL Server 2005 or newer +* Can be used with Microsoft Azure SQL Database +* Can be used on all go supported platforms (e.g. Linux, Mac OS X and Windows) +* Supports new date/time types: date, time, datetime2, datetimeoffset +* Supports string parameters longer than 8000 characters +* Supports encryption using SSL/TLS +* Supports SQL Server and Windows Authentication +* Supports Single-Sign-On on Windows +* Supports connections to AlwaysOn Availability Group listeners, including re-direction to read-only replicas. +* Supports query notifications + +## Known Issues + +* SQL Server 2008 and 2008 R2 engine cannot handle login records when SSL encryption is not disabled. +To fix SQL Server 2008 R2 issue, install SQL Server 2008 R2 Service Pack 2. +To fix SQL Server 2008 issue, install Microsoft SQL Server 2008 Service Pack 3 and Cumulative update package 3 for SQL Server 2008 SP3. +More information: http://support.microsoft.com/kb/2653857 diff --git a/vendor/github.com/dgrijalva/jwt-go/.gitignore b/vendor/github.com/dgrijalva/jwt-go/.gitignore new file mode 100644 index 0000000000..80bed650ec --- /dev/null +++ b/vendor/github.com/dgrijalva/jwt-go/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +bin + + diff --git a/vendor/github.com/dgrijalva/jwt-go/.travis.yml b/vendor/github.com/dgrijalva/jwt-go/.travis.yml new file mode 100644 index 0000000000..1027f56cd9 --- /dev/null +++ b/vendor/github.com/dgrijalva/jwt-go/.travis.yml @@ -0,0 +1,13 @@ +language: go + +script: + - go vet ./... + - go test -v ./... + +go: + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - 1.7 + - tip diff --git a/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md b/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md new file mode 100644 index 0000000000..7fc1f793cb --- /dev/null +++ b/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md @@ -0,0 +1,97 @@ +## Migration Guide from v2 -> v3 + +Version 3 adds several new, frequently requested features. To do so, it introduces a few breaking changes. We've worked to keep these as minimal as possible. This guide explains the breaking changes and how you can quickly update your code. + +### `Token.Claims` is now an interface type + +The most requested feature from the 2.0 verison of this library was the ability to provide a custom type to the JSON parser for claims. This was implemented by introducing a new interface, `Claims`, to replace `map[string]interface{}`. We also included two concrete implementations of `Claims`: `MapClaims` and `StandardClaims`. + +`MapClaims` is an alias for `map[string]interface{}` with built in validation behavior. It is the default claims type when using `Parse`. The usage is unchanged except you must type cast the claims property. + +The old example for parsing a token looked like this.. + +```go + if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil { + fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"]) + } +``` + +is now directly mapped to... + +```go + if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil { + claims := token.Claims.(jwt.MapClaims) + fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"]) + } +``` + +`StandardClaims` is designed to be embedded in your custom type. You can supply a custom claims type with the new `ParseWithClaims` function. Here's an example of using a custom claims type. + +```go + type MyCustomClaims struct { + User string + *StandardClaims + } + + if token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, keyLookupFunc); err == nil { + claims := token.Claims.(*MyCustomClaims) + fmt.Printf("Token for user %v expires %v", claims.User, claims.StandardClaims.ExpiresAt) + } +``` + +### `ParseFromRequest` has been moved + +To keep this library focused on the tokens without becoming overburdened with complex request processing logic, `ParseFromRequest` and its new companion `ParseFromRequestWithClaims` have been moved to a subpackage, `request`. The method signatues have also been augmented to receive a new argument: `Extractor`. + +`Extractors` do the work of picking the token string out of a request. The interface is simple and composable. + +This simple parsing example: + +```go + if token, err := jwt.ParseFromRequest(tokenString, req, keyLookupFunc); err == nil { + fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"]) + } +``` + +is directly mapped to: + +```go + if token, err := request.ParseFromRequest(req, request.OAuth2Extractor, keyLookupFunc); err == nil { + claims := token.Claims.(jwt.MapClaims) + fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"]) + } +``` + +There are several concrete `Extractor` types provided for your convenience: + +* `HeaderExtractor` will search a list of headers until one contains content. +* `ArgumentExtractor` will search a list of keys in request query and form arguments until one contains content. +* `MultiExtractor` will try a list of `Extractors` in order until one returns content. +* `AuthorizationHeaderExtractor` will look in the `Authorization` header for a `Bearer` token. +* `OAuth2Extractor` searches the places an OAuth2 token would be specified (per the spec): `Authorization` header and `access_token` argument +* `PostExtractionFilter` wraps an `Extractor`, allowing you to process the content before it's parsed. A simple example is stripping the `Bearer ` text from a header + + +### RSA signing methods no longer accept `[]byte` keys + +Due to a [critical vulnerability](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/), we've decided the convenience of accepting `[]byte` instead of `rsa.PublicKey` or `rsa.PrivateKey` isn't worth the risk of misuse. + +To replace this behavior, we've added two helper methods: `ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error)` and `ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error)`. These are just simple helpers for unpacking PEM encoded PKCS1 and PKCS8 keys. If your keys are encoded any other way, all you need to do is convert them to the `crypto/rsa` package's types. + +```go + func keyLookupFunc(*Token) (interface{}, error) { + // Don't forget to validate the alg is what you expect: + if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { + return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) + } + + // Look up key + key, err := lookupPublicKey(token.Header["kid"]) + if err != nil { + return nil, err + } + + // Unpack key from PEM encoded PKCS8 + return jwt.ParseRSAPublicKeyFromPEM(key) + } +``` diff --git a/vendor/github.com/dgrijalva/jwt-go/README.md b/vendor/github.com/dgrijalva/jwt-go/README.md new file mode 100644 index 0000000000..f48365fafb --- /dev/null +++ b/vendor/github.com/dgrijalva/jwt-go/README.md @@ -0,0 +1,85 @@ +A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html) + +[![Build Status](https://travis-ci.org/dgrijalva/jwt-go.svg?branch=master)](https://travis-ci.org/dgrijalva/jwt-go) + +**BREAKING CHANGES:*** Version 3.0.0 is here. It includes _a lot_ of changes including a few that break the API. We've tried to break as few things as possible, so there should just be a few type signature changes. A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code. + +**NOTICE:** A vulnerability in JWT was [recently published](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/). As this library doesn't force users to validate the `alg` is what they expected, it's possible your usage is effected. There will be an update soon to remedy this, and it will likey require backwards-incompatible changes to the API. In the short term, please make sure your implementation verifies the `alg` is what you expect. + + +## What the heck is a JWT? + +JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens. + +In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](http://tools.ietf.org/html/rfc4648) encoded. The last part is the signature, encoded the same way. + +The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used. + +The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [the RFC](http://self-issued.info/docs/draft-jones-json-web-token.html) for information about reserved keys and the proper way to add your own. + +## What's in the box? + +This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own. + +## Examples + +See [the project documentation](https://godoc.org/github.com/dgrijalva/jwt-go) for examples of usage: + +* [Simple example of parsing and validating a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse--Hmac) +* [Simple example of building and signing a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-New--Hmac) +* [Directory of Examples](https://godoc.org/github.com/dgrijalva/jwt-go#pkg-examples) + +## Extensions + +This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`. + +Here's an example of an extension that integrates with the Google App Engine signing tools: https://github.com/someone1/gcp-jwt-go + +## Compliance + +This library was last reviewed to comply with [RTF 7519](http://www.rfc-editor.org/info/rfc7519) dated May 2015 with a few notable differences: + +* In order to protect against accidental use of [Unsecured JWTs](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#UnsecuredJWT), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key. + +## Project Status & Versioning + +This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason). + +This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `master`. Periodically, versions will be tagged from `master`. You can find all the releases on [the project releases page](https://github.com/dgrijalva/jwt-go/releases). + +While we try to make it obvious when we make breaking changes, there isn't a great mechanism for pushing announcements out to users. You may want to use this alternative package include: `gopkg.in/dgrijalva/jwt-go.v2`. It will do the right thing WRT semantic versioning. + +## Usage Tips + +### Signing vs Encryption + +A token is simply a JSON object that is signed by its author. this tells you exactly two things about the data: + +* The author of the token was in the possession of the signing secret +* The data has not been modified since it was signed + +It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. JWE is currently outside the scope of this library. + +### Choosing a Signing Method + +There are several signing methods available, and you should probably take the time to learn about the various options before choosing one. The principal design decision is most likely going to be symmetric vs asymmetric. + +Symmetric signing methods, such as HSA, use only a single secret. This is probably the simplest signing method to use since any `[]byte` can be used as a valid secret. They are also slightly computationally faster to use, though this rarely is enough to matter. Symmetric signing methods work the best when both producers and consumers of tokens are trusted, or even the same system. Since the same secret is used to both sign and validate tokens, you can't easily distribute the key for validation. + +Asymmetric signing methods, such as RSA, use different keys for signing and verifying tokens. This makes it possible to produce tokens with a private key, and allow any consumer to access the public key for verification. + +### JWT and OAuth + +It's worth mentioning that OAuth and JWT are not the same thing. A JWT token is simply a signed JSON object. It can be used anywhere such a thing is useful. There is some confusion, though, as JWT is the most common type of bearer token used in OAuth2 authentication. + +Without going too far down the rabbit hole, here's a description of the interaction of these technologies: + +* OAuth is a protocol for allowing an identity provider to be separate from the service a user is logging in to. For example, whenever you use Facebook to log into a different service (Yelp, Spotify, etc), you are using OAuth. +* OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token. +* Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL. + +## More + +Documentation can be found [on godoc.org](http://godoc.org/github.com/dgrijalva/jwt-go). + +The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in to documentation. diff --git a/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md b/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md new file mode 100644 index 0000000000..b605b45093 --- /dev/null +++ b/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md @@ -0,0 +1,105 @@ +## `jwt-go` Version History + +#### 3.0.0 + +* **Compatibility Breaking Changes**: See MIGRATION_GUIDE.md for tips on updating your code + * Dropped support for `[]byte` keys when using RSA signing methods. This convenience feature could contribute to security vulnerabilities involving mismatched key types with signing methods. + * `ParseFromRequest` has been moved to `request` subpackage and usage has changed + * The `Claims` property on `Token` is now type `Claims` instead of `map[string]interface{}`. The default value is type `MapClaims`, which is an alias to `map[string]interface{}`. This makes it possible to use a custom type when decoding claims. +* Other Additions and Changes + * Added `Claims` interface type to allow users to decode the claims into a custom type + * Added `ParseWithClaims`, which takes a third argument of type `Claims`. Use this function instead of `Parse` if you have a custom type you'd like to decode into. + * Dramatically improved the functionality and flexibility of `ParseFromRequest`, which is now in the `request` subpackage + * Added `ParseFromRequestWithClaims` which is the `FromRequest` equivalent of `ParseWithClaims` + * Added new interface type `Extractor`, which is used for extracting JWT strings from http requests. Used with `ParseFromRequest` and `ParseFromRequestWithClaims`. + * Added several new, more specific, validation errors to error type bitmask + * Moved examples from README to executable example files + * Signing method registry is now thread safe + * Added new property to `ValidationError`, which contains the raw error returned by calls made by parse/verify (such as those returned by keyfunc or json parser) + +#### 2.7.0 + +This will likely be the last backwards compatible release before 3.0.0, excluding essential bug fixes. + +* Added new option `-show` to the `jwt` command that will just output the decoded token without verifying +* Error text for expired tokens includes how long it's been expired +* Fixed incorrect error returned from `ParseRSAPublicKeyFromPEM` +* Documentation updates + +#### 2.6.0 + +* Exposed inner error within ValidationError +* Fixed validation errors when using UseJSONNumber flag +* Added several unit tests + +#### 2.5.0 + +* Added support for signing method none. You shouldn't use this. The API tries to make this clear. +* Updated/fixed some documentation +* Added more helpful error message when trying to parse tokens that begin with `BEARER ` + +#### 2.4.0 + +* Added new type, Parser, to allow for configuration of various parsing parameters + * You can now specify a list of valid signing methods. Anything outside this set will be rejected. + * You can now opt to use the `json.Number` type instead of `float64` when parsing token JSON +* Added support for [Travis CI](https://travis-ci.org/dgrijalva/jwt-go) +* Fixed some bugs with ECDSA parsing + +#### 2.3.0 + +* Added support for ECDSA signing methods +* Added support for RSA PSS signing methods (requires go v1.4) + +#### 2.2.0 + +* Gracefully handle a `nil` `Keyfunc` being passed to `Parse`. Result will now be the parsed token and an error, instead of a panic. + +#### 2.1.0 + +Backwards compatible API change that was missed in 2.0.0. + +* The `SignedString` method on `Token` now takes `interface{}` instead of `[]byte` + +#### 2.0.0 + +There were two major reasons for breaking backwards compatibility with this update. The first was a refactor required to expand the width of the RSA and HMAC-SHA signing implementations. There will likely be no required code changes to support this change. + +The second update, while unfortunately requiring a small change in integration, is required to open up this library to other signing methods. Not all keys used for all signing methods have a single standard on-disk representation. Requiring `[]byte` as the type for all keys proved too limiting. Additionally, this implementation allows for pre-parsed tokens to be reused, which might matter in an application that parses a high volume of tokens with a small set of keys. Backwards compatibilty has been maintained for passing `[]byte` to the RSA signing methods, but they will also accept `*rsa.PublicKey` and `*rsa.PrivateKey`. + +It is likely the only integration change required here will be to change `func(t *jwt.Token) ([]byte, error)` to `func(t *jwt.Token) (interface{}, error)` when calling `Parse`. + +* **Compatibility Breaking Changes** + * `SigningMethodHS256` is now `*SigningMethodHMAC` instead of `type struct` + * `SigningMethodRS256` is now `*SigningMethodRSA` instead of `type struct` + * `KeyFunc` now returns `interface{}` instead of `[]byte` + * `SigningMethod.Sign` now takes `interface{}` instead of `[]byte` for the key + * `SigningMethod.Verify` now takes `interface{}` instead of `[]byte` for the key +* Renamed type `SigningMethodHS256` to `SigningMethodHMAC`. Specific sizes are now just instances of this type. + * Added public package global `SigningMethodHS256` + * Added public package global `SigningMethodHS384` + * Added public package global `SigningMethodHS512` +* Renamed type `SigningMethodRS256` to `SigningMethodRSA`. Specific sizes are now just instances of this type. + * Added public package global `SigningMethodRS256` + * Added public package global `SigningMethodRS384` + * Added public package global `SigningMethodRS512` +* Moved sample private key for HMAC tests from an inline value to a file on disk. Value is unchanged. +* Refactored the RSA implementation to be easier to read +* Exposed helper methods `ParseRSAPrivateKeyFromPEM` and `ParseRSAPublicKeyFromPEM` + +#### 1.0.2 + +* Fixed bug in parsing public keys from certificates +* Added more tests around the parsing of keys for RS256 +* Code refactoring in RS256 implementation. No functional changes + +#### 1.0.1 + +* Fixed panic if RS256 signing method was passed an invalid key + +#### 1.0.0 + +* First versioned release +* API stabilized +* Supports creating, signing, parsing, and validating JWT tokens +* Supports RS256 and HS256 signing methods \ No newline at end of file diff --git a/vendor/github.com/edsrzf/mmap-go/.gitignore b/vendor/github.com/edsrzf/mmap-go/.gitignore new file mode 100644 index 0000000000..9aa02c1ed3 --- /dev/null +++ b/vendor/github.com/edsrzf/mmap-go/.gitignore @@ -0,0 +1,8 @@ +*.out +*.5 +*.6 +*.8 +*.swp +_obj +_test +testdata diff --git a/vendor/github.com/edsrzf/mmap-go/README.md b/vendor/github.com/edsrzf/mmap-go/README.md new file mode 100644 index 0000000000..4cc2bfe1c8 --- /dev/null +++ b/vendor/github.com/edsrzf/mmap-go/README.md @@ -0,0 +1,12 @@ +mmap-go +======= + +mmap-go is a portable mmap package for the [Go programming language](http://golang.org). +It has been tested on Linux (386, amd64), OS X, and Windows (386). It should also +work on other Unix-like platforms, but hasn't been tested with them. I'm interested +to hear about the results. + +I haven't been able to add more features without adding significant complexity, +so mmap-go doesn't support mprotect, mincore, and maybe a few other things. +If you're running on a Unix-like platform and need some of these features, +I suggest Gustavo Niemeyer's [gommap](http://labix.org/gommap). diff --git a/vendor/github.com/elazarl/go-bindata-assetfs/README.md b/vendor/github.com/elazarl/go-bindata-assetfs/README.md new file mode 100644 index 0000000000..27ee48f09d --- /dev/null +++ b/vendor/github.com/elazarl/go-bindata-assetfs/README.md @@ -0,0 +1,46 @@ +# go-bindata-assetfs + +Serve embedded files from [jteeuwen/go-bindata](https://github.com/jteeuwen/go-bindata) with `net/http`. + +[GoDoc](http://godoc.org/github.com/elazarl/go-bindata-assetfs) + +### Installation + +Install with + + $ go get github.com/jteeuwen/go-bindata/... + $ go get github.com/elazarl/go-bindata-assetfs/... + +### Creating embedded data + +Usage is identical to [jteeuwen/go-bindata](https://github.com/jteeuwen/go-bindata) usage, +instead of running `go-bindata` run `go-bindata-assetfs`. + +The tool will create a `bindata_assetfs.go` file, which contains the embedded data. + +A typical use case is + + $ go-bindata-assetfs data/... + +### Using assetFS in your code + +The generated file provides an `assetFS()` function that returns a `http.Filesystem` +wrapping the embedded files. What you usually want to do is: + + http.Handle("/", http.FileServer(assetFS())) + +This would run an HTTP server serving the embedded files. + +## Without running binary tool + +You can always just run the `go-bindata` tool, and then + +use + + import "github.com/elazarl/go-bindata-assetfs" + ... + http.Handle("/", + http.FileServer( + &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, AssetInfo: AssetInfo, Prefix: "data"})) + +to serve files embedded from the `data` directory. diff --git a/vendor/github.com/etcd-io/bbolt/.gitignore b/vendor/github.com/etcd-io/bbolt/.gitignore new file mode 100644 index 0000000000..3bcd8cbaf0 --- /dev/null +++ b/vendor/github.com/etcd-io/bbolt/.gitignore @@ -0,0 +1,5 @@ +*.prof +*.test +*.swp +/bin/ +cover.out diff --git a/vendor/github.com/etcd-io/bbolt/.travis.yml b/vendor/github.com/etcd-io/bbolt/.travis.yml new file mode 100644 index 0000000000..a60300c558 --- /dev/null +++ b/vendor/github.com/etcd-io/bbolt/.travis.yml @@ -0,0 +1,17 @@ +language: go +go_import_path: go.etcd.io/bbolt + +sudo: false + +go: +- 1.11 + +before_install: +- go get -v honnef.co/go/tools/... +- go get -v github.com/kisielk/errcheck + +script: +- make fmt +- make test +- make race +# - make errcheck diff --git a/vendor/github.com/etcd-io/bbolt/Makefile b/vendor/github.com/etcd-io/bbolt/Makefile new file mode 100644 index 0000000000..2968aaa61d --- /dev/null +++ b/vendor/github.com/etcd-io/bbolt/Makefile @@ -0,0 +1,38 @@ +BRANCH=`git rev-parse --abbrev-ref HEAD` +COMMIT=`git rev-parse --short HEAD` +GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)" + +default: build + +race: + @TEST_FREELIST_TYPE=hashmap go test -v -race -test.run="TestSimulate_(100op|1000op)" + @echo "array freelist test" + @TEST_FREELIST_TYPE=array go test -v -race -test.run="TestSimulate_(100op|1000op)" + +fmt: + !(gofmt -l -s -d $(shell find . -name \*.go) | grep '[a-z]') + +# go get honnef.co/go/tools/simple +gosimple: + gosimple ./... + +# go get honnef.co/go/tools/unused +unused: + unused ./... + +# go get github.com/kisielk/errcheck +errcheck: + @errcheck -ignorepkg=bytes -ignore=os:Remove go.etcd.io/bbolt + +test: + TEST_FREELIST_TYPE=hashmap go test -timeout 20m -v -coverprofile cover.out -covermode atomic + # Note: gets "program not an importable package" in out of path builds + TEST_FREELIST_TYPE=hashmap go test -v ./cmd/bbolt + + @echo "array freelist test" + + @TEST_FREELIST_TYPE=array go test -timeout 20m -v -coverprofile cover.out -covermode atomic + # Note: gets "program not an importable package" in out of path builds + @TEST_FREELIST_TYPE=array go test -v ./cmd/bbolt + +.PHONY: race fmt errcheck test gosimple unused diff --git a/vendor/github.com/etcd-io/bbolt/README.md b/vendor/github.com/etcd-io/bbolt/README.md new file mode 100644 index 0000000000..e9989efc50 --- /dev/null +++ b/vendor/github.com/etcd-io/bbolt/README.md @@ -0,0 +1,954 @@ +bbolt +===== + +[![Go Report Card](https://goreportcard.com/badge/github.com/etcd-io/bbolt?style=flat-square)](https://goreportcard.com/report/github.com/etcd-io/bbolt) +[![Coverage](https://codecov.io/gh/etcd-io/bbolt/branch/master/graph/badge.svg)](https://codecov.io/gh/etcd-io/bbolt) +[![Build Status Travis](https://img.shields.io/travis/etcd-io/bboltlabs.svg?style=flat-square&&branch=master)](https://travis-ci.com/etcd-io/bbolt) +[![Godoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://godoc.org/github.com/etcd-io/bbolt) +[![Releases](https://img.shields.io/github/release/etcd-io/bbolt/all.svg?style=flat-square)](https://github.com/etcd-io/bbolt/releases) +[![LICENSE](https://img.shields.io/github/license/etcd-io/bbolt.svg?style=flat-square)](https://github.com/etcd-io/bbolt/blob/master/LICENSE) + +bbolt is a fork of [Ben Johnson's][gh_ben] [Bolt][bolt] key/value +store. The purpose of this fork is to provide the Go community with an active +maintenance and development target for Bolt; the goal is improved reliability +and stability. bbolt includes bug fixes, performance enhancements, and features +not found in Bolt while preserving backwards compatibility with the Bolt API. + +Bolt is a pure Go key/value store inspired by [Howard Chu's][hyc_symas] +[LMDB project][lmdb]. The goal of the project is to provide a simple, +fast, and reliable database for projects that don't require a full database +server such as Postgres or MySQL. + +Since Bolt is meant to be used as such a low-level piece of functionality, +simplicity is key. The API will be small and only focus on getting values +and setting values. That's it. + +[gh_ben]: https://github.com/benbjohnson +[bolt]: https://github.com/boltdb/bolt +[hyc_symas]: https://twitter.com/hyc_symas +[lmdb]: http://symas.com/mdb/ + +## Project Status + +Bolt is stable, the API is fixed, and the file format is fixed. Full unit +test coverage and randomized black box testing are used to ensure database +consistency and thread safety. Bolt is currently used in high-load production +environments serving databases as large as 1TB. Many companies such as +Shopify and Heroku use Bolt-backed services every day. + +## Project versioning + +bbolt uses [semantic versioning](http://semver.org). +API should not change between patch and minor releases. +New minor versions may add additional features to the API. + +## Table of Contents + + - [Getting Started](#getting-started) + - [Installing](#installing) + - [Opening a database](#opening-a-database) + - [Transactions](#transactions) + - [Read-write transactions](#read-write-transactions) + - [Read-only transactions](#read-only-transactions) + - [Batch read-write transactions](#batch-read-write-transactions) + - [Managing transactions manually](#managing-transactions-manually) + - [Using buckets](#using-buckets) + - [Using key/value pairs](#using-keyvalue-pairs) + - [Autoincrementing integer for the bucket](#autoincrementing-integer-for-the-bucket) + - [Iterating over keys](#iterating-over-keys) + - [Prefix scans](#prefix-scans) + - [Range scans](#range-scans) + - [ForEach()](#foreach) + - [Nested buckets](#nested-buckets) + - [Database backups](#database-backups) + - [Statistics](#statistics) + - [Read-Only Mode](#read-only-mode) + - [Mobile Use (iOS/Android)](#mobile-use-iosandroid) + - [Resources](#resources) + - [Comparison with other databases](#comparison-with-other-databases) + - [Postgres, MySQL, & other relational databases](#postgres-mysql--other-relational-databases) + - [LevelDB, RocksDB](#leveldb-rocksdb) + - [LMDB](#lmdb) + - [Caveats & Limitations](#caveats--limitations) + - [Reading the Source](#reading-the-source) + - [Other Projects Using Bolt](#other-projects-using-bolt) + +## Getting Started + +### Installing + +To start using Bolt, install Go and run `go get`: + +```sh +$ go get go.etcd.io/bbolt/... +``` + +This will retrieve the library and install the `bolt` command line utility into +your `$GOBIN` path. + + +### Importing bbolt + +To use bbolt as an embedded key-value store, import as: + +```go +import bolt "go.etcd.io/bbolt" + +db, err := bolt.Open(path, 0666, nil) +if err != nil { + return err +} +defer db.Close() +``` + + +### Opening a database + +The top-level object in Bolt is a `DB`. It is represented as a single file on +your disk and represents a consistent snapshot of your data. + +To open your database, simply use the `bolt.Open()` function: + +```go +package main + +import ( + "log" + + bolt "go.etcd.io/bbolt" +) + +func main() { + // Open the my.db data file in your current directory. + // It will be created if it doesn't exist. + db, err := bolt.Open("my.db", 0600, nil) + if err != nil { + log.Fatal(err) + } + defer db.Close() + + ... +} +``` + +Please note that Bolt obtains a file lock on the data file so multiple processes +cannot open the same database at the same time. Opening an already open Bolt +database will cause it to hang until the other process closes it. To prevent +an indefinite wait you can pass a timeout option to the `Open()` function: + +```go +db, err := bolt.Open("my.db", 0600, &bolt.Options{Timeout: 1 * time.Second}) +``` + + +### Transactions + +Bolt allows only one read-write transaction at a time but allows as many +read-only transactions as you want at a time. Each transaction has a consistent +view of the data as it existed when the transaction started. + +Individual transactions and all objects created from them (e.g. buckets, keys) +are not thread safe. To work with data in multiple goroutines you must start +a transaction for each one or use locking to ensure only one goroutine accesses +a transaction at a time. Creating transaction from the `DB` is thread safe. + +Read-only transactions and read-write transactions should not depend on one +another and generally shouldn't be opened simultaneously in the same goroutine. +This can cause a deadlock as the read-write transaction needs to periodically +re-map the data file but it cannot do so while a read-only transaction is open. + + +#### Read-write transactions + +To start a read-write transaction, you can use the `DB.Update()` function: + +```go +err := db.Update(func(tx *bolt.Tx) error { + ... + return nil +}) +``` + +Inside the closure, you have a consistent view of the database. You commit the +transaction by returning `nil` at the end. You can also rollback the transaction +at any point by returning an error. All database operations are allowed inside +a read-write transaction. + +Always check the return error as it will report any disk failures that can cause +your transaction to not complete. If you return an error within your closure +it will be passed through. + + +#### Read-only transactions + +To start a read-only transaction, you can use the `DB.View()` function: + +```go +err := db.View(func(tx *bolt.Tx) error { + ... + return nil +}) +``` + +You also get a consistent view of the database within this closure, however, +no mutating operations are allowed within a read-only transaction. You can only +retrieve buckets, retrieve values, and copy the database within a read-only +transaction. + + +#### Batch read-write transactions + +Each `DB.Update()` waits for disk to commit the writes. This overhead +can be minimized by combining multiple updates with the `DB.Batch()` +function: + +```go +err := db.Batch(func(tx *bolt.Tx) error { + ... + return nil +}) +``` + +Concurrent Batch calls are opportunistically combined into larger +transactions. Batch is only useful when there are multiple goroutines +calling it. + +The trade-off is that `Batch` can call the given +function multiple times, if parts of the transaction fail. The +function must be idempotent and side effects must take effect only +after a successful return from `DB.Batch()`. + +For example: don't display messages from inside the function, instead +set variables in the enclosing scope: + +```go +var id uint64 +err := db.Batch(func(tx *bolt.Tx) error { + // Find last key in bucket, decode as bigendian uint64, increment + // by one, encode back to []byte, and add new key. + ... + id = newValue + return nil +}) +if err != nil { + return ... +} +fmt.Println("Allocated ID %d", id) +``` + + +#### Managing transactions manually + +The `DB.View()` and `DB.Update()` functions are wrappers around the `DB.Begin()` +function. These helper functions will start the transaction, execute a function, +and then safely close your transaction if an error is returned. This is the +recommended way to use Bolt transactions. + +However, sometimes you may want to manually start and end your transactions. +You can use the `DB.Begin()` function directly but **please** be sure to close +the transaction. + +```go +// Start a writable transaction. +tx, err := db.Begin(true) +if err != nil { + return err +} +defer tx.Rollback() + +// Use the transaction... +_, err := tx.CreateBucket([]byte("MyBucket")) +if err != nil { + return err +} + +// Commit the transaction and check for error. +if err := tx.Commit(); err != nil { + return err +} +``` + +The first argument to `DB.Begin()` is a boolean stating if the transaction +should be writable. + + +### Using buckets + +Buckets are collections of key/value pairs within the database. All keys in a +bucket must be unique. You can create a bucket using the `DB.CreateBucket()` +function: + +```go +db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("MyBucket")) + if err != nil { + return fmt.Errorf("create bucket: %s", err) + } + return nil +}) +``` + +You can also create a bucket only if it doesn't exist by using the +`Tx.CreateBucketIfNotExists()` function. It's a common pattern to call this +function for all your top-level buckets after you open your database so you can +guarantee that they exist for future transactions. + +To delete a bucket, simply call the `Tx.DeleteBucket()` function. + + +### Using key/value pairs + +To save a key/value pair to a bucket, use the `Bucket.Put()` function: + +```go +db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("MyBucket")) + err := b.Put([]byte("answer"), []byte("42")) + return err +}) +``` + +This will set the value of the `"answer"` key to `"42"` in the `MyBucket` +bucket. To retrieve this value, we can use the `Bucket.Get()` function: + +```go +db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("MyBucket")) + v := b.Get([]byte("answer")) + fmt.Printf("The answer is: %s\n", v) + return nil +}) +``` + +The `Get()` function does not return an error because its operation is +guaranteed to work (unless there is some kind of system failure). If the key +exists then it will return its byte slice value. If it doesn't exist then it +will return `nil`. It's important to note that you can have a zero-length value +set to a key which is different than the key not existing. + +Use the `Bucket.Delete()` function to delete a key from the bucket. + +Please note that values returned from `Get()` are only valid while the +transaction is open. If you need to use a value outside of the transaction +then you must use `copy()` to copy it to another byte slice. + + +### Autoincrementing integer for the bucket +By using the `NextSequence()` function, you can let Bolt determine a sequence +which can be used as the unique identifier for your key/value pairs. See the +example below. + +```go +// CreateUser saves u to the store. The new user ID is set on u once the data is persisted. +func (s *Store) CreateUser(u *User) error { + return s.db.Update(func(tx *bolt.Tx) error { + // Retrieve the users bucket. + // This should be created when the DB is first opened. + b := tx.Bucket([]byte("users")) + + // Generate ID for the user. + // This returns an error only if the Tx is closed or not writeable. + // That can't happen in an Update() call so I ignore the error check. + id, _ := b.NextSequence() + u.ID = int(id) + + // Marshal user data into bytes. + buf, err := json.Marshal(u) + if err != nil { + return err + } + + // Persist bytes to users bucket. + return b.Put(itob(u.ID), buf) + }) +} + +// itob returns an 8-byte big endian representation of v. +func itob(v int) []byte { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, uint64(v)) + return b +} + +type User struct { + ID int + ... +} +``` + +### Iterating over keys + +Bolt stores its keys in byte-sorted order within a bucket. This makes sequential +iteration over these keys extremely fast. To iterate over keys we'll use a +`Cursor`: + +```go +db.View(func(tx *bolt.Tx) error { + // Assume bucket exists and has keys + b := tx.Bucket([]byte("MyBucket")) + + c := b.Cursor() + + for k, v := c.First(); k != nil; k, v = c.Next() { + fmt.Printf("key=%s, value=%s\n", k, v) + } + + return nil +}) +``` + +The cursor allows you to move to a specific point in the list of keys and move +forward or backward through the keys one at a time. + +The following functions are available on the cursor: + +``` +First() Move to the first key. +Last() Move to the last key. +Seek() Move to a specific key. +Next() Move to the next key. +Prev() Move to the previous key. +``` + +Each of those functions has a return signature of `(key []byte, value []byte)`. +When you have iterated to the end of the cursor then `Next()` will return a +`nil` key. You must seek to a position using `First()`, `Last()`, or `Seek()` +before calling `Next()` or `Prev()`. If you do not seek to a position then +these functions will return a `nil` key. + +During iteration, if the key is non-`nil` but the value is `nil`, that means +the key refers to a bucket rather than a value. Use `Bucket.Bucket()` to +access the sub-bucket. + + +#### Prefix scans + +To iterate over a key prefix, you can combine `Seek()` and `bytes.HasPrefix()`: + +```go +db.View(func(tx *bolt.Tx) error { + // Assume bucket exists and has keys + c := tx.Bucket([]byte("MyBucket")).Cursor() + + prefix := []byte("1234") + for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() { + fmt.Printf("key=%s, value=%s\n", k, v) + } + + return nil +}) +``` + +#### Range scans + +Another common use case is scanning over a range such as a time range. If you +use a sortable time encoding such as RFC3339 then you can query a specific +date range like this: + +```go +db.View(func(tx *bolt.Tx) error { + // Assume our events bucket exists and has RFC3339 encoded time keys. + c := tx.Bucket([]byte("Events")).Cursor() + + // Our time range spans the 90's decade. + min := []byte("1990-01-01T00:00:00Z") + max := []byte("2000-01-01T00:00:00Z") + + // Iterate over the 90's. + for k, v := c.Seek(min); k != nil && bytes.Compare(k, max) <= 0; k, v = c.Next() { + fmt.Printf("%s: %s\n", k, v) + } + + return nil +}) +``` + +Note that, while RFC3339 is sortable, the Golang implementation of RFC3339Nano does not use a fixed number of digits after the decimal point and is therefore not sortable. + + +#### ForEach() + +You can also use the function `ForEach()` if you know you'll be iterating over +all the keys in a bucket: + +```go +db.View(func(tx *bolt.Tx) error { + // Assume bucket exists and has keys + b := tx.Bucket([]byte("MyBucket")) + + b.ForEach(func(k, v []byte) error { + fmt.Printf("key=%s, value=%s\n", k, v) + return nil + }) + return nil +}) +``` + +Please note that keys and values in `ForEach()` are only valid while +the transaction is open. If you need to use a key or value outside of +the transaction, you must use `copy()` to copy it to another byte +slice. + +### Nested buckets + +You can also store a bucket in a key to create nested buckets. The API is the +same as the bucket management API on the `DB` object: + +```go +func (*Bucket) CreateBucket(key []byte) (*Bucket, error) +func (*Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) +func (*Bucket) DeleteBucket(key []byte) error +``` + +Say you had a multi-tenant application where the root level bucket was the account bucket. Inside of this bucket was a sequence of accounts which themselves are buckets. And inside the sequence bucket you could have many buckets pertaining to the Account itself (Users, Notes, etc) isolating the information into logical groupings. + +```go + +// createUser creates a new user in the given account. +func createUser(accountID int, u *User) error { + // Start the transaction. + tx, err := db.Begin(true) + if err != nil { + return err + } + defer tx.Rollback() + + // Retrieve the root bucket for the account. + // Assume this has already been created when the account was set up. + root := tx.Bucket([]byte(strconv.FormatUint(accountID, 10))) + + // Setup the users bucket. + bkt, err := root.CreateBucketIfNotExists([]byte("USERS")) + if err != nil { + return err + } + + // Generate an ID for the new user. + userID, err := bkt.NextSequence() + if err != nil { + return err + } + u.ID = userID + + // Marshal and save the encoded user. + if buf, err := json.Marshal(u); err != nil { + return err + } else if err := bkt.Put([]byte(strconv.FormatUint(u.ID, 10)), buf); err != nil { + return err + } + + // Commit the transaction. + if err := tx.Commit(); err != nil { + return err + } + + return nil +} + +``` + + + + +### Database backups + +Bolt is a single file so it's easy to backup. You can use the `Tx.WriteTo()` +function to write a consistent view of the database to a writer. If you call +this from a read-only transaction, it will perform a hot backup and not block +your other database reads and writes. + +By default, it will use a regular file handle which will utilize the operating +system's page cache. See the [`Tx`](https://godoc.org/go.etcd.io/bbolt#Tx) +documentation for information about optimizing for larger-than-RAM datasets. + +One common use case is to backup over HTTP so you can use tools like `cURL` to +do database backups: + +```go +func BackupHandleFunc(w http.ResponseWriter, req *http.Request) { + err := db.View(func(tx *bolt.Tx) error { + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Disposition", `attachment; filename="my.db"`) + w.Header().Set("Content-Length", strconv.Itoa(int(tx.Size()))) + _, err := tx.WriteTo(w) + return err + }) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} +``` + +Then you can backup using this command: + +```sh +$ curl http://localhost/backup > my.db +``` + +Or you can open your browser to `http://localhost/backup` and it will download +automatically. + +If you want to backup to another file you can use the `Tx.CopyFile()` helper +function. + + +### Statistics + +The database keeps a running count of many of the internal operations it +performs so you can better understand what's going on. By grabbing a snapshot +of these stats at two points in time we can see what operations were performed +in that time range. + +For example, we could start a goroutine to log stats every 10 seconds: + +```go +go func() { + // Grab the initial stats. + prev := db.Stats() + + for { + // Wait for 10s. + time.Sleep(10 * time.Second) + + // Grab the current stats and diff them. + stats := db.Stats() + diff := stats.Sub(&prev) + + // Encode stats to JSON and print to STDERR. + json.NewEncoder(os.Stderr).Encode(diff) + + // Save stats for the next loop. + prev = stats + } +}() +``` + +It's also useful to pipe these stats to a service such as statsd for monitoring +or to provide an HTTP endpoint that will perform a fixed-length sample. + + +### Read-Only Mode + +Sometimes it is useful to create a shared, read-only Bolt database. To this, +set the `Options.ReadOnly` flag when opening your database. Read-only mode +uses a shared lock to allow multiple processes to read from the database but +it will block any processes from opening the database in read-write mode. + +```go +db, err := bolt.Open("my.db", 0666, &bolt.Options{ReadOnly: true}) +if err != nil { + log.Fatal(err) +} +``` + +### Mobile Use (iOS/Android) + +Bolt is able to run on mobile devices by leveraging the binding feature of the +[gomobile](https://github.com/golang/mobile) tool. Create a struct that will +contain your database logic and a reference to a `*bolt.DB` with a initializing +constructor that takes in a filepath where the database file will be stored. +Neither Android nor iOS require extra permissions or cleanup from using this method. + +```go +func NewBoltDB(filepath string) *BoltDB { + db, err := bolt.Open(filepath+"/demo.db", 0600, nil) + if err != nil { + log.Fatal(err) + } + + return &BoltDB{db} +} + +type BoltDB struct { + db *bolt.DB + ... +} + +func (b *BoltDB) Path() string { + return b.db.Path() +} + +func (b *BoltDB) Close() { + b.db.Close() +} +``` + +Database logic should be defined as methods on this wrapper struct. + +To initialize this struct from the native language (both platforms now sync +their local storage to the cloud. These snippets disable that functionality for the +database file): + +#### Android + +```java +String path; +if (android.os.Build.VERSION.SDK_INT >=android.os.Build.VERSION_CODES.LOLLIPOP){ + path = getNoBackupFilesDir().getAbsolutePath(); +} else{ + path = getFilesDir().getAbsolutePath(); +} +Boltmobiledemo.BoltDB boltDB = Boltmobiledemo.NewBoltDB(path) +``` + +#### iOS + +```objc +- (void)demo { + NSString* path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, + NSUserDomainMask, + YES) objectAtIndex:0]; + GoBoltmobiledemoBoltDB * demo = GoBoltmobiledemoNewBoltDB(path); + [self addSkipBackupAttributeToItemAtPath:demo.path]; + //Some DB Logic would go here + [demo close]; +} + +- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString +{ + NSURL* URL= [NSURL fileURLWithPath: filePathString]; + assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]); + + NSError *error = nil; + BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES] + forKey: NSURLIsExcludedFromBackupKey error: &error]; + if(!success){ + NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error); + } + return success; +} + +``` + +## Resources + +For more information on getting started with Bolt, check out the following articles: + +* [Intro to BoltDB: Painless Performant Persistence](http://npf.io/2014/07/intro-to-boltdb-painless-performant-persistence/) by [Nate Finch](https://github.com/natefinch). +* [Bolt -- an embedded key/value database for Go](https://www.progville.com/go/bolt-embedded-db-golang/) by Progville + + +## Comparison with other databases + +### Postgres, MySQL, & other relational databases + +Relational databases structure data into rows and are only accessible through +the use of SQL. This approach provides flexibility in how you store and query +your data but also incurs overhead in parsing and planning SQL statements. Bolt +accesses all data by a byte slice key. This makes Bolt fast to read and write +data by key but provides no built-in support for joining values together. + +Most relational databases (with the exception of SQLite) are standalone servers +that run separately from your application. This gives your systems +flexibility to connect multiple application servers to a single database +server but also adds overhead in serializing and transporting data over the +network. Bolt runs as a library included in your application so all data access +has to go through your application's process. This brings data closer to your +application but limits multi-process access to the data. + + +### LevelDB, RocksDB + +LevelDB and its derivatives (RocksDB, HyperLevelDB) are similar to Bolt in that +they are libraries bundled into the application, however, their underlying +structure is a log-structured merge-tree (LSM tree). An LSM tree optimizes +random writes by using a write ahead log and multi-tiered, sorted files called +SSTables. Bolt uses a B+tree internally and only a single file. Both approaches +have trade-offs. + +If you require a high random write throughput (>10,000 w/sec) or you need to use +spinning disks then LevelDB could be a good choice. If your application is +read-heavy or does a lot of range scans then Bolt could be a good choice. + +One other important consideration is that LevelDB does not have transactions. +It supports batch writing of key/values pairs and it supports read snapshots +but it will not give you the ability to do a compare-and-swap operation safely. +Bolt supports fully serializable ACID transactions. + + +### LMDB + +Bolt was originally a port of LMDB so it is architecturally similar. Both use +a B+tree, have ACID semantics with fully serializable transactions, and support +lock-free MVCC using a single writer and multiple readers. + +The two projects have somewhat diverged. LMDB heavily focuses on raw performance +while Bolt has focused on simplicity and ease of use. For example, LMDB allows +several unsafe actions such as direct writes for the sake of performance. Bolt +opts to disallow actions which can leave the database in a corrupted state. The +only exception to this in Bolt is `DB.NoSync`. + +There are also a few differences in API. LMDB requires a maximum mmap size when +opening an `mdb_env` whereas Bolt will handle incremental mmap resizing +automatically. LMDB overloads the getter and setter functions with multiple +flags whereas Bolt splits these specialized cases into their own functions. + + +## Caveats & Limitations + +It's important to pick the right tool for the job and Bolt is no exception. +Here are a few things to note when evaluating and using Bolt: + +* Bolt is good for read intensive workloads. Sequential write performance is + also fast but random writes can be slow. You can use `DB.Batch()` or add a + write-ahead log to help mitigate this issue. + +* Bolt uses a B+tree internally so there can be a lot of random page access. + SSDs provide a significant performance boost over spinning disks. + +* Try to avoid long running read transactions. Bolt uses copy-on-write so + old pages cannot be reclaimed while an old transaction is using them. + +* Byte slices returned from Bolt are only valid during a transaction. Once the + transaction has been committed or rolled back then the memory they point to + can be reused by a new page or can be unmapped from virtual memory and you'll + see an `unexpected fault address` panic when accessing it. + +* Bolt uses an exclusive write lock on the database file so it cannot be + shared by multiple processes. + +* Be careful when using `Bucket.FillPercent`. Setting a high fill percent for + buckets that have random inserts will cause your database to have very poor + page utilization. + +* Use larger buckets in general. Smaller buckets causes poor page utilization + once they become larger than the page size (typically 4KB). + +* Bulk loading a lot of random writes into a new bucket can be slow as the + page will not split until the transaction is committed. Randomly inserting + more than 100,000 key/value pairs into a single new bucket in a single + transaction is not advised. + +* Bolt uses a memory-mapped file so the underlying operating system handles the + caching of the data. Typically, the OS will cache as much of the file as it + can in memory and will release memory as needed to other processes. This means + that Bolt can show very high memory usage when working with large databases. + However, this is expected and the OS will release memory as needed. Bolt can + handle databases much larger than the available physical RAM, provided its + memory-map fits in the process virtual address space. It may be problematic + on 32-bits systems. + +* The data structures in the Bolt database are memory mapped so the data file + will be endian specific. This means that you cannot copy a Bolt file from a + little endian machine to a big endian machine and have it work. For most + users this is not a concern since most modern CPUs are little endian. + +* Because of the way pages are laid out on disk, Bolt cannot truncate data files + and return free pages back to the disk. Instead, Bolt maintains a free list + of unused pages within its data file. These free pages can be reused by later + transactions. This works well for many use cases as databases generally tend + to grow. However, it's important to note that deleting large chunks of data + will not allow you to reclaim that space on disk. + + For more information on page allocation, [see this comment][page-allocation]. + +[page-allocation]: https://github.com/boltdb/bolt/issues/308#issuecomment-74811638 + + +## Reading the Source + +Bolt is a relatively small code base (<5KLOC) for an embedded, serializable, +transactional key/value database so it can be a good starting point for people +interested in how databases work. + +The best places to start are the main entry points into Bolt: + +- `Open()` - Initializes the reference to the database. It's responsible for + creating the database if it doesn't exist, obtaining an exclusive lock on the + file, reading the meta pages, & memory-mapping the file. + +- `DB.Begin()` - Starts a read-only or read-write transaction depending on the + value of the `writable` argument. This requires briefly obtaining the "meta" + lock to keep track of open transactions. Only one read-write transaction can + exist at a time so the "rwlock" is acquired during the life of a read-write + transaction. + +- `Bucket.Put()` - Writes a key/value pair into a bucket. After validating the + arguments, a cursor is used to traverse the B+tree to the page and position + where they key & value will be written. Once the position is found, the bucket + materializes the underlying page and the page's parent pages into memory as + "nodes". These nodes are where mutations occur during read-write transactions. + These changes get flushed to disk during commit. + +- `Bucket.Get()` - Retrieves a key/value pair from a bucket. This uses a cursor + to move to the page & position of a key/value pair. During a read-only + transaction, the key and value data is returned as a direct reference to the + underlying mmap file so there's no allocation overhead. For read-write + transactions, this data may reference the mmap file or one of the in-memory + node values. + +- `Cursor` - This object is simply for traversing the B+tree of on-disk pages + or in-memory nodes. It can seek to a specific key, move to the first or last + value, or it can move forward or backward. The cursor handles the movement up + and down the B+tree transparently to the end user. + +- `Tx.Commit()` - Converts the in-memory dirty nodes and the list of free pages + into pages to be written to disk. Writing to disk then occurs in two phases. + First, the dirty pages are written to disk and an `fsync()` occurs. Second, a + new meta page with an incremented transaction ID is written and another + `fsync()` occurs. This two phase write ensures that partially written data + pages are ignored in the event of a crash since the meta page pointing to them + is never written. Partially written meta pages are invalidated because they + are written with a checksum. + +If you have additional notes that could be helpful for others, please submit +them via pull request. + + +## Other Projects Using Bolt + +Below is a list of public, open source projects that use Bolt: + +* [Algernon](https://github.com/xyproto/algernon) - A HTTP/2 web server with built-in support for Lua. Uses BoltDB as the default database backend. +* [Bazil](https://bazil.org/) - A file system that lets your data reside where it is most convenient for it to reside. +* [bolter](https://github.com/hasit/bolter) - Command-line app for viewing BoltDB file in your terminal. +* [boltcli](https://github.com/spacewander/boltcli) - the redis-cli for boltdb with Lua script support. +* [BoltHold](https://github.com/timshannon/bolthold) - An embeddable NoSQL store for Go types built on BoltDB +* [BoltStore](https://github.com/yosssi/boltstore) - Session store using Bolt. +* [Boltdb Boilerplate](https://github.com/bobintornado/boltdb-boilerplate) - Boilerplate wrapper around bolt aiming to make simple calls one-liners. +* [BoltDbWeb](https://github.com/evnix/boltdbweb) - A web based GUI for BoltDB files. +* [bleve](http://www.blevesearch.com/) - A pure Go search engine similar to ElasticSearch that uses Bolt as the default storage backend. +* [btcwallet](https://github.com/btcsuite/btcwallet) - A bitcoin wallet. +* [buckets](https://github.com/joyrexus/buckets) - a bolt wrapper streamlining + simple tx and key scans. +* [cayley](https://github.com/google/cayley) - Cayley is an open-source graph database using Bolt as optional backend. +* [ChainStore](https://github.com/pressly/chainstore) - Simple key-value interface to a variety of storage engines organized as a chain of operations. +* [Consul](https://github.com/hashicorp/consul) - Consul is service discovery and configuration made easy. Distributed, highly available, and datacenter-aware. +* [DVID](https://github.com/janelia-flyem/dvid) - Added Bolt as optional storage engine and testing it against Basho-tuned leveldb. +* [dcrwallet](https://github.com/decred/dcrwallet) - A wallet for the Decred cryptocurrency. +* [drive](https://github.com/odeke-em/drive) - drive is an unofficial Google Drive command line client for \*NIX operating systems. +* [event-shuttle](https://github.com/sclasen/event-shuttle) - A Unix system service to collect and reliably deliver messages to Kafka. +* [Freehold](http://tshannon.bitbucket.org/freehold/) - An open, secure, and lightweight platform for your files and data. +* [Go Report Card](https://goreportcard.com/) - Go code quality report cards as a (free and open source) service. +* [GoWebApp](https://github.com/josephspurrier/gowebapp) - A basic MVC web application in Go using BoltDB. +* [GoShort](https://github.com/pankajkhairnar/goShort) - GoShort is a URL shortener written in Golang and BoltDB for persistent key/value storage and for routing it's using high performent HTTPRouter. +* [gopherpit](https://github.com/gopherpit/gopherpit) - A web service to manage Go remote import paths with custom domains +* [Gitchain](https://github.com/gitchain/gitchain) - Decentralized, peer-to-peer Git repositories aka "Git meets Bitcoin". +* [InfluxDB](https://influxdata.com) - Scalable datastore for metrics, events, and real-time analytics. +* [ipLocator](https://github.com/AndreasBriese/ipLocator) - A fast ip-geo-location-server using bolt with bloom filters. +* [ipxed](https://github.com/kelseyhightower/ipxed) - Web interface and api for ipxed. +* [Ironsmith](https://github.com/timshannon/ironsmith) - A simple, script-driven continuous integration (build - > test -> release) tool, with no external dependencies +* [Kala](https://github.com/ajvb/kala) - Kala is a modern job scheduler optimized to run on a single node. It is persistent, JSON over HTTP API, ISO 8601 duration notation, and dependent jobs. +* [Key Value Access Langusge (KVAL)](https://github.com/kval-access-language) - A proposed grammar for key-value datastores offering a bbolt binding. +* [LedisDB](https://github.com/siddontang/ledisdb) - A high performance NoSQL, using Bolt as optional storage. +* [lru](https://github.com/crowdriff/lru) - Easy to use Bolt-backed Least-Recently-Used (LRU) read-through cache with chainable remote stores. +* [mbuckets](https://github.com/abhigupta912/mbuckets) - A Bolt wrapper that allows easy operations on multi level (nested) buckets. +* [MetricBase](https://github.com/msiebuhr/MetricBase) - Single-binary version of Graphite. +* [MuLiFS](https://github.com/dankomiocevic/mulifs) - Music Library Filesystem creates a filesystem to organise your music files. +* [Operation Go: A Routine Mission](http://gocode.io) - An online programming game for Golang using Bolt for user accounts and a leaderboard. +* [photosite/session](https://godoc.org/bitbucket.org/kardianos/photosite/session) - Sessions for a photo viewing site. +* [Prometheus Annotation Server](https://github.com/oliver006/prom_annotation_server) - Annotation server for PromDash & Prometheus service monitoring system. +* [reef-pi](https://github.com/reef-pi/reef-pi) - reef-pi is an award winning, modular, DIY reef tank controller using easy to learn electronics based on a Raspberry Pi. +* [Request Baskets](https://github.com/darklynx/request-baskets) - A web service to collect arbitrary HTTP requests and inspect them via REST API or simple web UI, similar to [RequestBin](http://requestb.in/) service +* [Seaweed File System](https://github.com/chrislusf/seaweedfs) - Highly scalable distributed key~file system with O(1) disk read. +* [stow](https://github.com/djherbis/stow) - a persistence manager for objects + backed by boltdb. +* [Storm](https://github.com/asdine/storm) - Simple and powerful ORM for BoltDB. +* [SimpleBolt](https://github.com/xyproto/simplebolt) - A simple way to use BoltDB. Deals mainly with strings. +* [Skybox Analytics](https://github.com/skybox/skybox) - A standalone funnel analysis tool for web analytics. +* [Scuttlebutt](https://github.com/benbjohnson/scuttlebutt) - Uses Bolt to store and process all Twitter mentions of GitHub projects. +* [tentacool](https://github.com/optiflows/tentacool) - REST api server to manage system stuff (IP, DNS, Gateway...) on a linux server. +* [torrent](https://github.com/anacrolix/torrent) - Full-featured BitTorrent client package and utilities in Go. BoltDB is a storage backend in development. +* [Wiki](https://github.com/peterhellberg/wiki) - A tiny wiki using Goji, BoltDB and Blackfriday. + +If you are using Bolt in a project please send a pull request to add it to the list. diff --git a/vendor/github.com/ethantkoenig/rupture/.gitignore b/vendor/github.com/ethantkoenig/rupture/.gitignore new file mode 100644 index 0000000000..f3d79deb11 --- /dev/null +++ b/vendor/github.com/ethantkoenig/rupture/.gitignore @@ -0,0 +1,17 @@ +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 +.glide/ + +# vendor dependencies +vendor/ diff --git a/vendor/github.com/ethantkoenig/rupture/.travis.yml b/vendor/github.com/ethantkoenig/rupture/.travis.yml new file mode 100644 index 0000000000..6d007525fb --- /dev/null +++ b/vendor/github.com/ethantkoenig/rupture/.travis.yml @@ -0,0 +1,14 @@ +language: go + +go: + - 1.8.x + - 1.9.x + +before_script: + - go get -u github.com/golang/lint/golint + +script: + - go vet + - golint -set_exit_status + - go build + - go test diff --git a/vendor/github.com/ethantkoenig/rupture/Gopkg.lock b/vendor/github.com/ethantkoenig/rupture/Gopkg.lock new file mode 100644 index 0000000000..86e495e783 --- /dev/null +++ b/vendor/github.com/ethantkoenig/rupture/Gopkg.lock @@ -0,0 +1,173 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/RoaringBitmap/roaring" + packages = ["."] + revision = "84551f0e309d6f9bafa428ef39b31ab7f16ff7b8" + version = "v0.4.1" + +[[projects]] + branch = "master" + name = "github.com/Smerity/govarint" + packages = ["."] + revision = "7265e41f48f15fd61751e16da866af3c704bb3ab" + +[[projects]] + name = "github.com/blevesearch/bleve" + packages = [ + ".", + "analysis", + "analysis/analyzer/standard", + "analysis/datetime/flexible", + "analysis/datetime/optional", + "analysis/lang/en", + "analysis/token/lowercase", + "analysis/token/porter", + "analysis/token/stop", + "analysis/tokenizer/unicode", + "document", + "geo", + "index", + "index/scorch", + "index/scorch/mergeplan", + "index/scorch/segment", + "index/scorch/segment/mem", + "index/scorch/segment/zap", + "index/store", + "index/store/boltdb", + "index/store/gtreap", + "index/upsidedown", + "mapping", + "numeric", + "registry", + "search", + "search/collector", + "search/facet", + "search/highlight", + "search/highlight/format/html", + "search/highlight/fragmenter/simple", + "search/highlight/highlighter/html", + "search/highlight/highlighter/simple", + "search/query", + "search/scorer", + "search/searcher" + ] + revision = "a3b125508b4443344b596888ca58467b6c9310b9" + +[[projects]] + branch = "master" + name = "github.com/blevesearch/go-porterstemmer" + packages = ["."] + revision = "23a2c8e5cf1f380f27722c6d2ae8896431dc7d0e" + +[[projects]] + branch = "master" + name = "github.com/blevesearch/segment" + packages = ["."] + revision = "762005e7a34fd909a84586299f1dd457371d36ee" + +[[projects]] + branch = "master" + name = "github.com/boltdb/bolt" + packages = ["."] + revision = "9da31745363232bc1e27dbab3569e77383a51585" + +[[projects]] + branch = "master" + name = "github.com/couchbase/vellum" + packages = [ + ".", + "regexp", + "utf8" + ] + revision = "ed84a675e24ed0a0bf6859b1ddec7e7c858354bd" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + branch = "master" + name = "github.com/edsrzf/mmap-go" + packages = ["."] + revision = "0bce6a6887123b67a60366d2c9fe2dfb74289d2e" + +[[projects]] + branch = "master" + name = "github.com/glycerine/go-unsnap-stream" + packages = ["."] + revision = "62a9a9eb44fd8932157b1a8ace2149eff5971af6" + +[[projects]] + name = "github.com/golang/protobuf" + packages = ["proto"] + revision = "925541529c1fa6821df4e44ce2723319eb2be768" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/golang/snappy" + packages = ["."] + revision = "553a641470496b2327abcac10b36396bd98e45c9" + +[[projects]] + branch = "master" + name = "github.com/mschoch/smat" + packages = ["."] + revision = "90eadee771aeab36e8bf796039b8c261bebebe4f" + +[[projects]] + name = "github.com/philhofer/fwd" + packages = ["."] + revision = "bb6d471dc95d4fe11e432687f8b70ff496cf3136" + version = "v1.0.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/steveyen/gtreap" + packages = ["."] + revision = "0abe01ef9be25c4aedc174758ec2d917314d6d70" + +[[projects]] + name = "github.com/stretchr/testify" + packages = ["assert"] + revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" + version = "v1.2.1" + +[[projects]] + branch = "master" + name = "github.com/tinylib/msgp" + packages = ["msgp"] + revision = "03a79185462ad029a6e7e05b2f3f3e0498d0a6c0" + +[[projects]] + branch = "master" + name = "github.com/willf/bitset" + packages = ["."] + revision = "1a37ad96e8c1a11b20900a232874843b5174221f" + +[[projects]] + name = "golang.org/x/net" + packages = ["context"] + revision = "309822c5b9b9f80db67f016069a12628d94fad34" + +[[projects]] + name = "golang.org/x/sys" + packages = ["unix"] + revision = "3dbebcf8efb6a5011a60c2b4591c1022a759af8a" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "61c759f0c1136cadf86ae8a30bb78edf33fc844cdcb2316469b4ae14a8d051b0" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/ethantkoenig/rupture/Gopkg.toml b/vendor/github.com/ethantkoenig/rupture/Gopkg.toml new file mode 100644 index 0000000000..55dbd3b239 --- /dev/null +++ b/vendor/github.com/ethantkoenig/rupture/Gopkg.toml @@ -0,0 +1,34 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.1" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/ethantkoenig/rupture/README.md b/vendor/github.com/ethantkoenig/rupture/README.md new file mode 100644 index 0000000000..da76681e38 --- /dev/null +++ b/vendor/github.com/ethantkoenig/rupture/README.md @@ -0,0 +1,13 @@ +# rupture + +[![Build Status](https://travis-ci.org/ethantkoenig/rupture.svg?branch=master)](https://travis-ci.org/ethantkoenig/rupture) [![GoDoc](https://godoc.org/github.com/ethantkoenig/rupture?status.svg)](https://godoc.org/github.com/ethantkoenig/rupture) [![Go Report Card](https://goreportcard.com/badge/blevesearch/bleve)](https://goreportcard.com/report/blevesearch/bleve) + +An explosive companion to the [bleve indexing library](https://www.github.com/blevesearch/bleve) + +## Features + +`rupture` includes the following additions to `bleve`: + +- __Flushing batches__: Batches of operation which automatically flush to the underlying bleve index. +- __Sharded indices__: An index-like abstraction built on top of several underlying indices. Sharded indices provide lower write latencies for indices with large amounts of data. +- __Index metadata__: Track index version for easily managing migrations and schema changes. diff --git a/vendor/github.com/facebookgo/clock/README.md b/vendor/github.com/facebookgo/clock/README.md new file mode 100644 index 0000000000..5d4f4fe72e --- /dev/null +++ b/vendor/github.com/facebookgo/clock/README.md @@ -0,0 +1,104 @@ +clock [![Build Status](https://drone.io/github.com/benbjohnson/clock/status.png)](https://drone.io/github.com/benbjohnson/clock/latest) [![Coverage Status](https://coveralls.io/repos/benbjohnson/clock/badge.png?branch=master)](https://coveralls.io/r/benbjohnson/clock?branch=master) [![GoDoc](https://godoc.org/github.com/benbjohnson/clock?status.png)](https://godoc.org/github.com/benbjohnson/clock) ![Project status](http://img.shields.io/status/experimental.png?color=red) +===== + +Clock is a small library for mocking time in Go. It provides an interface +around the standard library's [`time`][time] package so that the application +can use the realtime clock while tests can use the mock clock. + +[time]: http://golang.org/pkg/time/ + + +## Usage + +### Realtime Clock + +Your application can maintain a `Clock` variable that will allow realtime and +mock clocks to be interchangable. For example, if you had an `Application` type: + +```go +import "github.com/benbjohnson/clock" + +type Application struct { + Clock clock.Clock +} +``` + +You could initialize it to use the realtime clock like this: + +```go +var app Application +app.Clock = clock.New() +... +``` + +Then all timers and time-related functionality should be performed from the +`Clock` variable. + + +### Mocking time + +In your tests, you will want to use a `Mock` clock: + +```go +import ( + "testing" + + "github.com/benbjohnson/clock" +) + +func TestApplication_DoSomething(t *testing.T) { + mock := clock.NewMock() + app := Application{Clock: mock} + ... +} +``` + +Now that you've initialized your application to use the mock clock, you can +adjust the time programmatically. The mock clock always starts from the Unix +epoch (midnight, Jan 1, 1970 UTC). + + +### Controlling time + +The mock clock provides the same functions that the standard library's `time` +package provides. For example, to find the current time, you use the `Now()` +function: + +```go +mock := clock.NewMock() + +// Find the current time. +mock.Now().UTC() // 1970-01-01 00:00:00 +0000 UTC + +// Move the clock forward. +mock.Add(2 * time.Hour) + +// Check the time again. It's 2 hours later! +mock.Now().UTC() // 1970-01-01 02:00:00 +0000 UTC +``` + +Timers and Tickers are also controlled by this same mock clock. They will only +execute when the clock is moved forward: + +``` +mock := clock.NewMock() +count := 0 + +// Kick off a timer to increment every 1 mock second. +go func() { + ticker := clock.Ticker(1 * time.Second) + for { + <-ticker.C + count++ + } +}() +runtime.Gosched() + +// Move the clock forward 10 second. +mock.Add(10 * time.Second) + +// This prints 10. +fmt.Println(count) +``` + + diff --git a/vendor/github.com/facebookgo/grace/license b/vendor/github.com/facebookgo/grace/license deleted file mode 100644 index 3aea875328..0000000000 --- a/vendor/github.com/facebookgo/grace/license +++ /dev/null @@ -1,30 +0,0 @@ -BSD License - -For grace software - -Copyright (c) 2015, Facebook, Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/facebookgo/grace/patents b/vendor/github.com/facebookgo/grace/patents deleted file mode 100644 index 11940a803c..0000000000 --- a/vendor/github.com/facebookgo/grace/patents +++ /dev/null @@ -1,33 +0,0 @@ -Additional Grant of Patent Rights Version 2 - -"Software" means the grace software distributed by Facebook, Inc. - -Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software -("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable -(subject to the termination provision below) license under any Necessary -Claims, to make, have made, use, sell, offer to sell, import, and otherwise -transfer the Software. For avoidance of doubt, no license is granted under -Facebook’s rights in any patent claims that are infringed by (i) modifications -to the Software made by you or any third party or (ii) the Software in -combination with any software or other technology. - -The license granted hereunder will terminate, automatically and without notice, -if you (or any of your subsidiaries, corporate affiliates or agents) initiate -directly or indirectly, or take a direct financial interest in, any Patent -Assertion: (i) against Facebook or any of its subsidiaries or corporate -affiliates, (ii) against any party if such Patent Assertion arises in whole or -in part from any software, technology, product or service of Facebook or any of -its subsidiaries or corporate affiliates, or (iii) against any party relating -to the Software. Notwithstanding the foregoing, if Facebook or any of its -subsidiaries or corporate affiliates files a lawsuit alleging patent -infringement against you in the first instance, and you respond by filing a -patent infringement counterclaim in that lawsuit against that party that is -unrelated to the Software, the license granted hereunder will not terminate -under section (i) of this paragraph due to such counterclaim. - -A "Necessary Claim" is a claim of a patent owned by Facebook that is -necessarily infringed by the Software standing alone. - -A "Patent Assertion" is any lawsuit or other action alleging direct, indirect, -or contributory infringement or inducement to infringe any patent, including a -cross-claim or counterclaim. diff --git a/vendor/github.com/facebookgo/httpdown/.travis.yml b/vendor/github.com/facebookgo/httpdown/.travis.yml new file mode 100644 index 0000000000..ea316cfe50 --- /dev/null +++ b/vendor/github.com/facebookgo/httpdown/.travis.yml @@ -0,0 +1,23 @@ +language: go + +go: + - 1.6 + +before_install: + - go get -v golang.org/x/tools/cmd/vet + - go get -v golang.org/x/tools/cmd/cover + - go get -v github.com/golang/lint/golint + +install: + - go install -race -v std + - go get -race -t -v ./... + - go install -race -v ./... + +script: + - go vet ./... + - $HOME/gopath/bin/golint . + - go test -cpu=2 -race -v ./... + - go test -cpu=2 -covermode=atomic -coverprofile=coverage.txt ./ + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/facebookgo/httpdown/readme.md b/vendor/github.com/facebookgo/httpdown/readme.md new file mode 100644 index 0000000000..d5fa245dbc --- /dev/null +++ b/vendor/github.com/facebookgo/httpdown/readme.md @@ -0,0 +1,41 @@ +httpdown [![Build Status](https://secure.travis-ci.org/facebookgo/httpdown.png)](https://travis-ci.org/facebookgo/httpdown) +======== + +Documentation: https://godoc.org/github.com/facebookgo/httpdown + +Package httpdown provides a library that makes it easy to build a HTTP server +that can be shutdown gracefully (that is, without dropping any connections). + +If you want graceful restart and not just graceful shutdown, look at the +[grace](https://github.com/facebookgo/grace) package which uses this package +underneath but also provides graceful restart. + +Usage +----- + +Demo HTTP Server with graceful termination: +https://github.com/facebookgo/httpdown/blob/master/httpdown_example/main.go + +1. Install the demo application + + go get github.com/facebookgo/httpdown/httpdown_example + +1. Start it in the first terminal + + httpdown_example + + This will output something like: + + 2014/11/18 21:57:50 serving on http://127.0.0.1:8080/ with pid 17 + +1. In a second terminal start a slow HTTP request + + curl 'http://localhost:8080/?duration=20s' + +1. In a third terminal trigger a graceful shutdown (using the pid from your output): + + kill -TERM 17 + +This will demonstrate that the slow request was served before the server was +shutdown. You could also have used `Ctrl-C` instead of `kill` as the example +application triggers graceful shutdown on TERM or INT signals. diff --git a/vendor/github.com/facebookgo/stats/.travis.yml b/vendor/github.com/facebookgo/stats/.travis.yml new file mode 100644 index 0000000000..9c9f036ae3 --- /dev/null +++ b/vendor/github.com/facebookgo/stats/.travis.yml @@ -0,0 +1,20 @@ +language: go + +go: + - 1.5 + +before_install: + - go get -v golang.org/x/tools/cmd/vet + - go get -v golang.org/x/tools/cmd/cover + - go get -v github.com/golang/lint/golint + +install: + - go install -race -v std + - go get -race -t -v ./... + - go install -race -v ./... + +script: + - go vet ./... + - $HOME/gopath/bin/golint . + - go test -cpu=2 -race -v ./... + - go test -cpu=2 -covermode=atomic ./... diff --git a/vendor/github.com/facebookgo/stats/readme.md b/vendor/github.com/facebookgo/stats/readme.md new file mode 100644 index 0000000000..f268ed307b --- /dev/null +++ b/vendor/github.com/facebookgo/stats/readme.md @@ -0,0 +1,4 @@ +stats [![Build Status](https://secure.travis-ci.org/facebookgo/stats.png)](https://travis-ci.org/facebookgo/stats) +===== + +Documentation: https://godoc.org/github.com/facebookgo/stats diff --git a/vendor/github.com/glycerine/go-unsnap-stream/.gitignore b/vendor/github.com/glycerine/go-unsnap-stream/.gitignore new file mode 100644 index 0000000000..00268614f0 --- /dev/null +++ b/vendor/github.com/glycerine/go-unsnap-stream/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/glycerine/go-unsnap-stream/README.md b/vendor/github.com/glycerine/go-unsnap-stream/README.md new file mode 100644 index 0000000000..b1b8c74751 --- /dev/null +++ b/vendor/github.com/glycerine/go-unsnap-stream/README.md @@ -0,0 +1,20 @@ +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]. + +For binary compatibility with the python implementation, 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 \ No newline at end of file diff --git a/vendor/github.com/glycerine/go-unsnap-stream/binary.dat b/vendor/github.com/glycerine/go-unsnap-stream/binary.dat new file mode 100644 index 0000000000..f31eee2e24 Binary files /dev/null and b/vendor/github.com/glycerine/go-unsnap-stream/binary.dat differ diff --git a/vendor/github.com/glycerine/go-unsnap-stream/binary.dat.snappy b/vendor/github.com/glycerine/go-unsnap-stream/binary.dat.snappy new file mode 100644 index 0000000000..ed37024293 Binary files /dev/null and b/vendor/github.com/glycerine/go-unsnap-stream/binary.dat.snappy differ diff --git a/vendor/github.com/glycerine/go-unsnap-stream/unenc.txt b/vendor/github.com/glycerine/go-unsnap-stream/unenc.txt new file mode 100644 index 0000000000..5f50279394 --- /dev/null +++ b/vendor/github.com/glycerine/go-unsnap-stream/unenc.txt @@ -0,0 +1 @@ +hello_snappy diff --git a/vendor/github.com/glycerine/go-unsnap-stream/unenc.txt.snappy b/vendor/github.com/glycerine/go-unsnap-stream/unenc.txt.snappy new file mode 100644 index 0000000000..ba45ecd426 Binary files /dev/null and b/vendor/github.com/glycerine/go-unsnap-stream/unenc.txt.snappy differ diff --git a/vendor/github.com/go-macaron/bindata/.travis.yml b/vendor/github.com/go-macaron/bindata/.travis.yml new file mode 100644 index 0000000000..2774fb35d5 --- /dev/null +++ b/vendor/github.com/go-macaron/bindata/.travis.yml @@ -0,0 +1,14 @@ +sudo: false +language: go + +go: + - 1.3 + - 1.4 + - 1.5 + - tip + +script: go test -v -cover -race + +notifications: + email: + - u@gogs.io diff --git a/vendor/github.com/go-macaron/bindata/README.md b/vendor/github.com/go-macaron/bindata/README.md new file mode 100644 index 0000000000..fd32bf3fb5 --- /dev/null +++ b/vendor/github.com/go-macaron/bindata/README.md @@ -0,0 +1,16 @@ +# bindata [![Build Status](https://travis-ci.org/go-macaron/bindata.svg?branch=master)](https://travis-ci.org/go-macaron/bindata) [![](http://gocover.io/_badge/github.com/go-macaron/bindata)](http://gocover.io/github.com/go-macaron/bindata) + +Package bindata is a helper module that allows to use in-memory static and template files for Macaron via [go-bindata](https://github.com/jteeuwen/go-bindata). + +### Installation + + go get github.com/go-macaron/bindata + +## Getting Help + +- [API Reference](https://gowalker.org/github.com/go-macaron/bindata) +- [Documentation](http://go-macaron.com/docs/middlewares/bindata) + +## License + +This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text. \ No newline at end of file diff --git a/vendor/github.com/go-macaron/binding/.gitignore b/vendor/github.com/go-macaron/binding/.gitignore new file mode 100644 index 0000000000..485dee64bc --- /dev/null +++ b/vendor/github.com/go-macaron/binding/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/vendor/github.com/go-macaron/binding/.travis.yml b/vendor/github.com/go-macaron/binding/.travis.yml new file mode 100644 index 0000000000..2462c6e19d --- /dev/null +++ b/vendor/github.com/go-macaron/binding/.travis.yml @@ -0,0 +1,15 @@ +sudo: false +language: go + +go: + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - tip + +script: go test -v -cover -race + +notifications: + email: + - u@gogs.io diff --git a/vendor/github.com/go-macaron/binding/README.md b/vendor/github.com/go-macaron/binding/README.md new file mode 100644 index 0000000000..a6748b57a1 --- /dev/null +++ b/vendor/github.com/go-macaron/binding/README.md @@ -0,0 +1,20 @@ +# binding [![Build Status](https://travis-ci.org/go-macaron/binding.svg?branch=master)](https://travis-ci.org/go-macaron/binding) [![](http://gocover.io/_badge/github.com/go-macaron/binding)](http://gocover.io/github.com/go-macaron/binding) + +Middleware binding provides request data binding and validation for [Macaron](https://github.com/go-macaron/macaron). + +### Installation + + go get github.com/go-macaron/binding + +## Getting Help + +- [API Reference](https://gowalker.org/github.com/go-macaron/binding) +- [Documentation](http://go-macaron.com/docs/middlewares/binding) + +## Credits + +This package is a modified version of [martini-contrib/binding](https://github.com/martini-contrib/binding). + +## License + +This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text. \ No newline at end of file diff --git a/vendor/github.com/go-macaron/cache/.gitignore b/vendor/github.com/go-macaron/cache/.gitignore new file mode 100644 index 0000000000..69067d55d5 --- /dev/null +++ b/vendor/github.com/go-macaron/cache/.gitignore @@ -0,0 +1,3 @@ +nodb/cache +ledis/tmp.db/ +nodb/tmp.db/ \ No newline at end of file diff --git a/vendor/github.com/go-macaron/cache/.travis.yml b/vendor/github.com/go-macaron/cache/.travis.yml new file mode 100644 index 0000000000..2774fb35d5 --- /dev/null +++ b/vendor/github.com/go-macaron/cache/.travis.yml @@ -0,0 +1,14 @@ +sudo: false +language: go + +go: + - 1.3 + - 1.4 + - 1.5 + - tip + +script: go test -v -cover -race + +notifications: + email: + - u@gogs.io diff --git a/vendor/github.com/go-macaron/cache/README.md b/vendor/github.com/go-macaron/cache/README.md new file mode 100644 index 0000000000..d27aa93b67 --- /dev/null +++ b/vendor/github.com/go-macaron/cache/README.md @@ -0,0 +1,20 @@ +# cache [![Build Status](https://travis-ci.org/go-macaron/cache.svg?branch=master)](https://travis-ci.org/go-macaron/cache) [![](http://gocover.io/_badge/github.com/go-macaron/cache)](http://gocover.io/github.com/go-macaron/cache) + +Middleware cache provides cache management for [Macaron](https://github.com/go-macaron/macaron). It can use many cache adapters, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Ledis and Nodb. + +### Installation + + go get github.com/go-macaron/cache + +## Getting Help + +- [API Reference](https://gowalker.org/github.com/go-macaron/cache) +- [Documentation](http://go-macaron.com/docs/middlewares/cache) + +## Credits + +This package is a modified version of [beego/cache](https://github.com/astaxie/beego/tree/master/cache). + +## License + +This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text. \ No newline at end of file diff --git a/vendor/github.com/go-macaron/cache/memcache/memcache.goconvey b/vendor/github.com/go-macaron/cache/memcache/memcache.goconvey new file mode 100644 index 0000000000..8485e986e4 --- /dev/null +++ b/vendor/github.com/go-macaron/cache/memcache/memcache.goconvey @@ -0,0 +1 @@ +ignore \ No newline at end of file diff --git a/vendor/github.com/go-macaron/cache/redis/redis.goconvey b/vendor/github.com/go-macaron/cache/redis/redis.goconvey new file mode 100644 index 0000000000..8485e986e4 --- /dev/null +++ b/vendor/github.com/go-macaron/cache/redis/redis.goconvey @@ -0,0 +1 @@ +ignore \ No newline at end of file diff --git a/vendor/github.com/go-macaron/captcha/.travis.yml b/vendor/github.com/go-macaron/captcha/.travis.yml new file mode 100644 index 0000000000..2774fb35d5 --- /dev/null +++ b/vendor/github.com/go-macaron/captcha/.travis.yml @@ -0,0 +1,14 @@ +sudo: false +language: go + +go: + - 1.3 + - 1.4 + - 1.5 + - tip + +script: go test -v -cover -race + +notifications: + email: + - u@gogs.io diff --git a/vendor/github.com/go-macaron/captcha/README.md b/vendor/github.com/go-macaron/captcha/README.md new file mode 100644 index 0000000000..5eab6f3feb --- /dev/null +++ b/vendor/github.com/go-macaron/captcha/README.md @@ -0,0 +1,16 @@ +# captcha [![Build Status](https://travis-ci.org/go-macaron/captcha.svg?branch=master)](https://travis-ci.org/go-macaron/captcha) + +Middleware captcha provides captcha service for [Macaron](https://github.com/go-macaron/macaron). + +### Installation + + go get github.com/go-macaron/captcha + +## Getting Help + +- [API Reference](https://gowalker.org/github.com/go-macaron/captcha) +- [Documentation](http://go-macaron.com/docs/middlewares/captcha) + +## License + +This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text. \ No newline at end of file diff --git a/vendor/github.com/go-macaron/csrf/.travis.yml b/vendor/github.com/go-macaron/csrf/.travis.yml new file mode 100644 index 0000000000..8d6a90868c --- /dev/null +++ b/vendor/github.com/go-macaron/csrf/.travis.yml @@ -0,0 +1,11 @@ +sudo: false +language: go +go: + - 1.5.x + - 1.6.x + - 1.7.x + - 1.8.x + - 1.9.x + - 1.10.x + +script: go test -v -cover -race diff --git a/vendor/github.com/go-macaron/csrf/README.md b/vendor/github.com/go-macaron/csrf/README.md new file mode 100644 index 0000000000..ff3e10a013 --- /dev/null +++ b/vendor/github.com/go-macaron/csrf/README.md @@ -0,0 +1,18 @@ +# csrf [![Build Status](https://travis-ci.org/go-macaron/csrf.svg?branch=master)](https://travis-ci.org/go-macaron/csrf) [![](http://gocover.io/_badge/github.com/go-macaron/csrf)](http://gocover.io/github.com/go-macaron/csrf) + +Middleware csrf generates and validates CSRF tokens for [Macaron](https://github.com/go-macaron/macaron). + +[API Reference](https://gowalker.org/github.com/go-macaron/csrf) + +### Installation + + go get github.com/go-macaron/csrf + +## Getting Help + +- [API Reference](https://gowalker.org/github.com/go-macaron/csrf) +- [Documentation](http://go-macaron.com/docs/middlewares/csrf) + +## License + +This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text. \ No newline at end of file diff --git a/vendor/github.com/go-macaron/i18n/.travis.yml b/vendor/github.com/go-macaron/i18n/.travis.yml new file mode 100644 index 0000000000..2774fb35d5 --- /dev/null +++ b/vendor/github.com/go-macaron/i18n/.travis.yml @@ -0,0 +1,14 @@ +sudo: false +language: go + +go: + - 1.3 + - 1.4 + - 1.5 + - tip + +script: go test -v -cover -race + +notifications: + email: + - u@gogs.io diff --git a/vendor/github.com/go-macaron/i18n/README.md b/vendor/github.com/go-macaron/i18n/README.md new file mode 100644 index 0000000000..737c0b9950 --- /dev/null +++ b/vendor/github.com/go-macaron/i18n/README.md @@ -0,0 +1,16 @@ +# i18n [![Build Status](https://travis-ci.org/go-macaron/i18n.svg?branch=master)](https://travis-ci.org/go-macaron/i18n) [![](http://gocover.io/_badge/github.com/go-macaron/i18n)](http://gocover.io/github.com/go-macaron/i18n) + +Middleware i18n provides app Internationalization and Localization for [Macaron](https://github.com/go-macaron/macaron). + +### Installation + + go get github.com/go-macaron/i18n + +## Getting Help + +- [API Reference](https://gowalker.org/github.com/go-macaron/i18n) +- [Documentation](http://go-macaron.com/docs/middlewares/i18n) + +## License + +This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text. \ No newline at end of file diff --git a/vendor/github.com/go-macaron/inject/.travis.yml b/vendor/github.com/go-macaron/inject/.travis.yml new file mode 100644 index 0000000000..2774fb35d5 --- /dev/null +++ b/vendor/github.com/go-macaron/inject/.travis.yml @@ -0,0 +1,14 @@ +sudo: false +language: go + +go: + - 1.3 + - 1.4 + - 1.5 + - tip + +script: go test -v -cover -race + +notifications: + email: + - u@gogs.io diff --git a/vendor/github.com/go-macaron/inject/README.md b/vendor/github.com/go-macaron/inject/README.md new file mode 100644 index 0000000000..c65c76955d --- /dev/null +++ b/vendor/github.com/go-macaron/inject/README.md @@ -0,0 +1,11 @@ +# inject [![Build Status](https://travis-ci.org/go-macaron/inject.svg?branch=master)](https://travis-ci.org/go-macaron/inject) [![](http://gocover.io/_badge/github.com/go-macaron/inject)](http://gocover.io/github.com/go-macaron/inject) + +Package inject provides utilities for mapping and injecting dependencies in various ways. + +**This a modified version of [codegangsta/inject](https://github.com/codegangsta/inject) for special purpose of Macaron** + +**Please use the original version if you need dependency injection feature** + +## License + +This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text. \ No newline at end of file diff --git a/vendor/github.com/go-macaron/session/.gitignore b/vendor/github.com/go-macaron/session/.gitignore new file mode 100644 index 0000000000..9297dbcd7c --- /dev/null +++ b/vendor/github.com/go-macaron/session/.gitignore @@ -0,0 +1,2 @@ +ledis/tmp.db +nodb/tmp.db \ No newline at end of file diff --git a/vendor/github.com/go-macaron/session/.travis.yml b/vendor/github.com/go-macaron/session/.travis.yml new file mode 100644 index 0000000000..bc978bae7f --- /dev/null +++ b/vendor/github.com/go-macaron/session/.travis.yml @@ -0,0 +1,9 @@ +sudo: false +language: go +go: + - 1.8.x + - 1.9.x + - 1.10.x + - 1.11.x + +script: go test -v -cover -race diff --git a/vendor/github.com/go-macaron/session/README.md b/vendor/github.com/go-macaron/session/README.md new file mode 100644 index 0000000000..fe4f4ba1b3 --- /dev/null +++ b/vendor/github.com/go-macaron/session/README.md @@ -0,0 +1,22 @@ +# session [![Build Status](https://travis-ci.org/go-macaron/session.svg?branch=master)](https://travis-ci.org/go-macaron/session) + +Middleware session provides session management for [Macaron](https://github.com/go-macaron/macaron). It can use many session providers, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Couchbase, Ledis and Nodb. + +### Installation + +The minimum requirement of Go is 1.6 (*1.7 if using Redis, 1.8 if using MySQL*). + + go get github.com/go-macaron/session + +## Getting Help + +- [API Reference](https://gowalker.org/github.com/go-macaron/session) +- [Documentation](https://go-macaron.com/docs/middlewares/session) + +## Credits + +This package is a modified version of [beego/session](https://github.com/astaxie/beego/tree/master/session). + +## License + +This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text. \ No newline at end of file diff --git a/vendor/github.com/go-macaron/session/memcache/memcache.goconvey b/vendor/github.com/go-macaron/session/memcache/memcache.goconvey new file mode 100644 index 0000000000..8485e986e4 --- /dev/null +++ b/vendor/github.com/go-macaron/session/memcache/memcache.goconvey @@ -0,0 +1 @@ +ignore \ No newline at end of file diff --git a/vendor/github.com/go-macaron/session/mysql/mysql.goconvey b/vendor/github.com/go-macaron/session/mysql/mysql.goconvey new file mode 100644 index 0000000000..8485e986e4 --- /dev/null +++ b/vendor/github.com/go-macaron/session/mysql/mysql.goconvey @@ -0,0 +1 @@ +ignore \ No newline at end of file diff --git a/vendor/github.com/go-macaron/session/nodb/nodb.goconvey b/vendor/github.com/go-macaron/session/nodb/nodb.goconvey new file mode 100644 index 0000000000..8485e986e4 --- /dev/null +++ b/vendor/github.com/go-macaron/session/nodb/nodb.goconvey @@ -0,0 +1 @@ +ignore \ No newline at end of file diff --git a/vendor/github.com/go-macaron/session/postgres/postgres.goconvey b/vendor/github.com/go-macaron/session/postgres/postgres.goconvey new file mode 100644 index 0000000000..8485e986e4 --- /dev/null +++ b/vendor/github.com/go-macaron/session/postgres/postgres.goconvey @@ -0,0 +1 @@ +ignore \ No newline at end of file diff --git a/vendor/github.com/go-macaron/session/redis/redis.goconvey b/vendor/github.com/go-macaron/session/redis/redis.goconvey new file mode 100644 index 0000000000..8485e986e4 --- /dev/null +++ b/vendor/github.com/go-macaron/session/redis/redis.goconvey @@ -0,0 +1 @@ +ignore \ No newline at end of file diff --git a/vendor/github.com/go-macaron/toolbox/.gitignore b/vendor/github.com/go-macaron/toolbox/.gitignore new file mode 100644 index 0000000000..c3265c1186 --- /dev/null +++ b/vendor/github.com/go-macaron/toolbox/.gitignore @@ -0,0 +1,2 @@ +profile/ +/.idea diff --git a/vendor/github.com/go-macaron/toolbox/README.md b/vendor/github.com/go-macaron/toolbox/README.md new file mode 100644 index 0000000000..72769a06ea --- /dev/null +++ b/vendor/github.com/go-macaron/toolbox/README.md @@ -0,0 +1,111 @@ +toolbox +======= + +Middleware toolbox provides health chcek, pprof, profile and statistic services for [Macaron](https://github.com/go-macaron/macaron). + +[API Reference](https://gowalker.org/github.com/go-macaron/toolbox) + +### Installation + + go get github.com/go-macaron/toolbox + +## Usage + +```go +// main.go +import ( + "gopkg.in/macaron.v1" + "github.com/go-macaron/toolbox" +) + +func main() { + m := macaron.Classic() + m.Use(toolbox.Toolboxer(m)) + m.Run() +} +``` + +Open your browser and visit `http://localhost:4000/debug` to see the effects. + +## Options + +`toolbox.Toolboxer` comes with a variety of configuration options: + +```go +type dummyChecker struct { +} + +func (dc *dummyChecker) Desc() string { + return "Dummy checker" +} + +func (dc *dummyChecker) Check() error { + return nil +} + +// ... +m.Use(toolbox.Toolboxer(m, toolbox.Options{ + URLPrefix: "/debug", // URL prefix for toolbox dashboard + HealthCheckURL: "/healthcheck", // URL for health check request + HealthCheckers: []HealthChecker{ + new(dummyChecker), + }, // Health checkers + HealthCheckFuncs: []*toolbox.HealthCheckFuncDesc{ + &toolbox.HealthCheckFuncDesc{ + Desc: "Database connection", + Func: func() error { return "OK" }, + }, + }, // Health check functions + DisableDebug: false, // Turns off all debug functionality when true + PprofURLPrefix: "/debug/pprof/", // URL prefix of pprof + ProfileURLPrefix: "/debug/profile/", // URL prefix of profile + ProfilePath: "profile", // Path store profile files +})) +// ... +``` + +## Route Statistic + +Toolbox also comes with a route call statistic functionality: + +```go +import ( + "os" + "time" + //... + "github.com/go-macaron/toolbox" +) + +func main() { + //... + m.Get("/", func(t toolbox.Toolbox) { + start := time.Now() + + // Other operations. + + t.AddStatistics("GET", "/", time.Since(start)) + }) + + m.Get("/dump", func(t toolbox.Toolbox) { + t.GetMap(os.Stdout) + }) +} +``` + +Output take from test: + +``` ++---------------------------------------------------+------------+------------------+------------------+------------------+------------------+------------------+ +| Request URL | Method | Times | Total Used(s) | Max Used(μs) | Min Used(μs) | Avg Used(μs) | ++---------------------------------------------------+------------+------------------+------------------+------------------+------------------+------------------+ +| /api/user | POST | 2 | 0.000122 | 120.000000 | 2.000000 | 61.000000 | +| /api/user | GET | 1 | 0.000013 | 13.000000 | 13.000000 | 13.000000 | +| /api/user | DELETE | 1 | 0.000001 | 1.400000 | 1.400000 | 1.400000 | +| /api/admin | POST | 1 | 0.000014 | 14.000000 | 14.000000 | 14.000000 | +| /api/user/unknwon | POST | 1 | 0.000012 | 12.000000 | 12.000000 | 12.000000 | ++---------------------------------------------------+------------+------------------+------------------+------------------+------------------+------------------+ +``` + +## License + +This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text. \ No newline at end of file diff --git a/vendor/github.com/go-sql-driver/mysql/.gitignore b/vendor/github.com/go-sql-driver/mysql/.gitignore new file mode 100644 index 0000000000..2de28da166 --- /dev/null +++ b/vendor/github.com/go-sql-driver/mysql/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +Icon? +ehthumbs.db +Thumbs.db +.idea diff --git a/vendor/github.com/go-sql-driver/mysql/.travis.yml b/vendor/github.com/go-sql-driver/mysql/.travis.yml new file mode 100644 index 0000000000..75505f1440 --- /dev/null +++ b/vendor/github.com/go-sql-driver/mysql/.travis.yml @@ -0,0 +1,107 @@ +sudo: false +language: go +go: + - 1.8.x + - 1.9.x + - 1.10.x + - 1.11.x + - master + +before_install: + - go get golang.org/x/tools/cmd/cover + - go get github.com/mattn/goveralls + +before_script: + - echo -e "[server]\ninnodb_log_file_size=256MB\ninnodb_buffer_pool_size=512MB\nmax_allowed_packet=16MB" | sudo tee -a /etc/mysql/my.cnf + - sudo service mysql restart + - .travis/wait_mysql.sh + - mysql -e 'create database gotest;' + +matrix: + include: + - env: DB=MYSQL8 + sudo: required + dist: trusty + go: 1.10.x + services: + - docker + before_install: + - go get golang.org/x/tools/cmd/cover + - go get github.com/mattn/goveralls + - docker pull mysql:8.0 + - docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret + mysql:8.0 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB --local-infile=1 + - cp .travis/docker.cnf ~/.my.cnf + - .travis/wait_mysql.sh + before_script: + - export MYSQL_TEST_USER=gotest + - export MYSQL_TEST_PASS=secret + - export MYSQL_TEST_ADDR=127.0.0.1:3307 + - export MYSQL_TEST_CONCURRENT=1 + + - env: DB=MYSQL57 + sudo: required + dist: trusty + go: 1.10.x + services: + - docker + before_install: + - go get golang.org/x/tools/cmd/cover + - go get github.com/mattn/goveralls + - docker pull mysql:5.7 + - docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret + mysql:5.7 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB --local-infile=1 + - cp .travis/docker.cnf ~/.my.cnf + - .travis/wait_mysql.sh + before_script: + - export MYSQL_TEST_USER=gotest + - export MYSQL_TEST_PASS=secret + - export MYSQL_TEST_ADDR=127.0.0.1:3307 + - export MYSQL_TEST_CONCURRENT=1 + + - env: DB=MARIA55 + sudo: required + dist: trusty + go: 1.10.x + services: + - docker + before_install: + - go get golang.org/x/tools/cmd/cover + - go get github.com/mattn/goveralls + - docker pull mariadb:5.5 + - docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret + mariadb:5.5 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB --local-infile=1 + - cp .travis/docker.cnf ~/.my.cnf + - .travis/wait_mysql.sh + before_script: + - export MYSQL_TEST_USER=gotest + - export MYSQL_TEST_PASS=secret + - export MYSQL_TEST_ADDR=127.0.0.1:3307 + - export MYSQL_TEST_CONCURRENT=1 + + - env: DB=MARIA10_1 + sudo: required + dist: trusty + go: 1.10.x + services: + - docker + before_install: + - go get golang.org/x/tools/cmd/cover + - go get github.com/mattn/goveralls + - docker pull mariadb:10.1 + - docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret + mariadb:10.1 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB --local-infile=1 + - cp .travis/docker.cnf ~/.my.cnf + - .travis/wait_mysql.sh + before_script: + - export MYSQL_TEST_USER=gotest + - export MYSQL_TEST_PASS=secret + - export MYSQL_TEST_ADDR=127.0.0.1:3307 + - export MYSQL_TEST_CONCURRENT=1 + +script: + - go test -v -covermode=count -coverprofile=coverage.out + - go vet ./... + - .travis/gofmt.sh +after_script: + - $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci diff --git a/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md b/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md new file mode 100644 index 0000000000..2d87d74c97 --- /dev/null +++ b/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md @@ -0,0 +1,167 @@ +## Version 1.4 (2018-06-03) + +Changes: + + - Documentation fixes (#530, #535, #567) + - Refactoring (#575, #579, #580, #581, #603, #615, #704) + - Cache column names (#444) + - Sort the DSN parameters in DSNs generated from a config (#637) + - Allow native password authentication by default (#644) + - Use the default port if it is missing in the DSN (#668) + - Removed the `strict` mode (#676) + - Do not query `max_allowed_packet` by default (#680) + - Dropped support Go 1.6 and lower (#696) + - Updated `ConvertValue()` to match the database/sql/driver implementation (#760) + - Document the usage of `0000-00-00T00:00:00` as the time.Time zero value (#783) + - Improved the compatibility of the authentication system (#807) + +New Features: + + - Multi-Results support (#537) + - `rejectReadOnly` DSN option (#604) + - `context.Context` support (#608, #612, #627, #761) + - Transaction isolation level support (#619, #744) + - Read-Only transactions support (#618, #634) + - `NewConfig` function which initializes a config with default values (#679) + - Implemented the `ColumnType` interfaces (#667, #724) + - Support for custom string types in `ConvertValue` (#623) + - Implemented `NamedValueChecker`, improving support for uint64 with high bit set (#690, #709, #710) + - `caching_sha2_password` authentication plugin support (#794, #800, #801, #802) + - Implemented `driver.SessionResetter` (#779) + - `sha256_password` authentication plugin support (#808) + +Bugfixes: + + - Use the DSN hostname as TLS default ServerName if `tls=true` (#564, #718) + - Fixed LOAD LOCAL DATA INFILE for empty files (#590) + - Removed columns definition cache since it sometimes cached invalid data (#592) + - Don't mutate registered TLS configs (#600) + - Make RegisterTLSConfig concurrency-safe (#613) + - Handle missing auth data in the handshake packet correctly (#646) + - Do not retry queries when data was written to avoid data corruption (#302, #736) + - Cache the connection pointer for error handling before invalidating it (#678) + - Fixed imports for appengine/cloudsql (#700) + - Fix sending STMT_LONG_DATA for 0 byte data (#734) + - Set correct capacity for []bytes read from length-encoded strings (#766) + - Make RegisterDial concurrency-safe (#773) + + +## Version 1.3 (2016-12-01) + +Changes: + + - Go 1.1 is no longer supported + - Use decimals fields in MySQL to format time types (#249) + - Buffer optimizations (#269) + - TLS ServerName defaults to the host (#283) + - Refactoring (#400, #410, #437) + - Adjusted documentation for second generation CloudSQL (#485) + - Documented DSN system var quoting rules (#502) + - Made statement.Close() calls idempotent to avoid errors in Go 1.6+ (#512) + +New Features: + + - Enable microsecond resolution on TIME, DATETIME and TIMESTAMP (#249) + - Support for returning table alias on Columns() (#289, #359, #382) + - Placeholder interpolation, can be actived with the DSN parameter `interpolateParams=true` (#309, #318, #490) + - Support for uint64 parameters with high bit set (#332, #345) + - Cleartext authentication plugin support (#327) + - Exported ParseDSN function and the Config struct (#403, #419, #429) + - Read / Write timeouts (#401) + - Support for JSON field type (#414) + - Support for multi-statements and multi-results (#411, #431) + - DSN parameter to set the driver-side max_allowed_packet value manually (#489) + - Native password authentication plugin support (#494, #524) + +Bugfixes: + + - Fixed handling of queries without columns and rows (#255) + - Fixed a panic when SetKeepAlive() failed (#298) + - Handle ERR packets while reading rows (#321) + - Fixed reading NULL length-encoded integers in MySQL 5.6+ (#349) + - Fixed absolute paths support in LOAD LOCAL DATA INFILE (#356) + - Actually zero out bytes in handshake response (#378) + - Fixed race condition in registering LOAD DATA INFILE handler (#383) + - Fixed tests with MySQL 5.7.9+ (#380) + - QueryUnescape TLS config names (#397) + - Fixed "broken pipe" error by writing to closed socket (#390) + - Fixed LOAD LOCAL DATA INFILE buffering (#424) + - Fixed parsing of floats into float64 when placeholders are used (#434) + - Fixed DSN tests with Go 1.7+ (#459) + - Handle ERR packets while waiting for EOF (#473) + - Invalidate connection on error while discarding additional results (#513) + - Allow terminating packets of length 0 (#516) + + +## Version 1.2 (2014-06-03) + +Changes: + + - We switched back to a "rolling release". `go get` installs the current master branch again + - Version v1 of the driver will not be maintained anymore. Go 1.0 is no longer supported by this driver + - Exported errors to allow easy checking from application code + - Enabled TCP Keepalives on TCP connections + - Optimized INFILE handling (better buffer size calculation, lazy init, ...) + - The DSN parser also checks for a missing separating slash + - Faster binary date / datetime to string formatting + - Also exported the MySQLWarning type + - mysqlConn.Close returns the first error encountered instead of ignoring all errors + - writePacket() automatically writes the packet size to the header + - readPacket() uses an iterative approach instead of the recursive approach to merge splitted packets + +New Features: + + - `RegisterDial` allows the usage of a custom dial function to establish the network connection + - Setting the connection collation is possible with the `collation` DSN parameter. This parameter should be preferred over the `charset` parameter + - Logging of critical errors is configurable with `SetLogger` + - Google CloudSQL support + +Bugfixes: + + - Allow more than 32 parameters in prepared statements + - Various old_password fixes + - Fixed TestConcurrent test to pass Go's race detection + - Fixed appendLengthEncodedInteger for large numbers + - Renamed readLengthEnodedString to readLengthEncodedString and skipLengthEnodedString to skipLengthEncodedString (fixed typo) + + +## Version 1.1 (2013-11-02) + +Changes: + + - Go-MySQL-Driver now requires Go 1.1 + - Connections now use the collation `utf8_general_ci` by default. Adding `&charset=UTF8` to the DSN should not be necessary anymore + - Made closing rows and connections error tolerant. This allows for example deferring rows.Close() without checking for errors + - `[]byte(nil)` is now treated as a NULL value. Before, it was treated like an empty string / `[]byte("")` + - DSN parameter values must now be url.QueryEscape'ed. This allows text values to contain special characters, such as '&'. + - Use the IO buffer also for writing. This results in zero allocations (by the driver) for most queries + - Optimized the buffer for reading + - stmt.Query now caches column metadata + - New Logo + - Changed the copyright header to include all contributors + - Improved the LOAD INFILE documentation + - The driver struct is now exported to make the driver directly accessible + - Refactored the driver tests + - Added more benchmarks and moved all to a separate file + - Other small refactoring + +New Features: + + - Added *old_passwords* support: Required in some cases, but must be enabled by adding `allowOldPasswords=true` to the DSN since it is insecure + - Added a `clientFoundRows` parameter: Return the number of matching rows instead of the number of rows changed on UPDATEs + - Added TLS/SSL support: Use a TLS/SSL encrypted connection to the server. Custom TLS configs can be registered and used + +Bugfixes: + + - Fixed MySQL 4.1 support: MySQL 4.1 sends packets with lengths which differ from the specification + - Convert to DB timezone when inserting `time.Time` + - Splitted packets (more than 16MB) are now merged correctly + - Fixed false positive `io.EOF` errors when the data was fully read + - Avoid panics on reuse of closed connections + - Fixed empty string producing false nil values + - Fixed sign byte for positive TIME fields + + +## Version 1.0 (2013-05-14) + +Initial Release diff --git a/vendor/github.com/go-sql-driver/mysql/CONTRIBUTING.md b/vendor/github.com/go-sql-driver/mysql/CONTRIBUTING.md new file mode 100644 index 0000000000..8fe16bcb49 --- /dev/null +++ b/vendor/github.com/go-sql-driver/mysql/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# Contributing Guidelines + +## Reporting Issues + +Before creating a new Issue, please check first if a similar Issue [already exists](https://github.com/go-sql-driver/mysql/issues?state=open) or was [recently closed](https://github.com/go-sql-driver/mysql/issues?direction=desc&page=1&sort=updated&state=closed). + +## Contributing Code + +By contributing to this project, you share your code under the Mozilla Public License 2, as specified in the LICENSE file. +Don't forget to add yourself to the AUTHORS file. + +### Code Review + +Everyone is invited to review and comment on pull requests. +If it looks fine to you, comment with "LGTM" (Looks good to me). + +If changes are required, notice the reviewers with "PTAL" (Please take another look) after committing the fixes. + +Before merging the Pull Request, at least one [team member](https://github.com/go-sql-driver?tab=members) must have commented with "LGTM". + +## Development Ideas + +If you are looking for ideas for code contributions, please check our [Development Ideas](https://github.com/go-sql-driver/mysql/wiki/Development-Ideas) Wiki page. diff --git a/vendor/github.com/go-sql-driver/mysql/README.md b/vendor/github.com/go-sql-driver/mysql/README.md new file mode 100644 index 0000000000..341d9194c1 --- /dev/null +++ b/vendor/github.com/go-sql-driver/mysql/README.md @@ -0,0 +1,490 @@ +# Go-MySQL-Driver + +A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) package + +![Go-MySQL-Driver logo](https://raw.github.com/wiki/go-sql-driver/mysql/gomysql_m.png "Golang Gopher holding the MySQL Dolphin") + +--------------------------------------- + * [Features](#features) + * [Requirements](#requirements) + * [Installation](#installation) + * [Usage](#usage) + * [DSN (Data Source Name)](#dsn-data-source-name) + * [Password](#password) + * [Protocol](#protocol) + * [Address](#address) + * [Parameters](#parameters) + * [Examples](#examples) + * [Connection pool and timeouts](#connection-pool-and-timeouts) + * [context.Context Support](#contextcontext-support) + * [ColumnType Support](#columntype-support) + * [LOAD DATA LOCAL INFILE support](#load-data-local-infile-support) + * [time.Time support](#timetime-support) + * [Unicode support](#unicode-support) + * [Testing / Development](#testing--development) + * [License](#license) + +--------------------------------------- + +## Features + * Lightweight and [fast](https://github.com/go-sql-driver/sql-benchmark "golang MySQL-Driver performance") + * Native Go implementation. No C-bindings, just pure Go + * Connections over TCP/IPv4, TCP/IPv6, Unix domain sockets or [custom protocols](https://godoc.org/github.com/go-sql-driver/mysql#DialFunc) + * Automatic handling of broken connections + * Automatic Connection Pooling *(by database/sql package)* + * Supports queries larger than 16MB + * Full [`sql.RawBytes`](https://golang.org/pkg/database/sql/#RawBytes) support. + * Intelligent `LONG DATA` handling in prepared statements + * Secure `LOAD DATA LOCAL INFILE` support with file Whitelisting and `io.Reader` support + * Optional `time.Time` parsing + * Optional placeholder interpolation + +## Requirements + * Go 1.8 or higher. We aim to support the 3 latest versions of Go. + * MySQL (4.1+), MariaDB, Percona Server, Google CloudSQL or Sphinx (2.2.3+) + +--------------------------------------- + +## Installation +Simple install the package to your [$GOPATH](https://github.com/golang/go/wiki/GOPATH "GOPATH") with the [go tool](https://golang.org/cmd/go/ "go command") from shell: +```bash +$ go get -u github.com/go-sql-driver/mysql +``` +Make sure [Git is installed](https://git-scm.com/downloads) on your machine and in your system's `PATH`. + +## Usage +_Go MySQL Driver_ is an implementation of Go's `database/sql/driver` interface. You only need to import the driver and can use the full [`database/sql`](https://golang.org/pkg/database/sql/) API then. + +Use `mysql` as `driverName` and a valid [DSN](#dsn-data-source-name) as `dataSourceName`: +```go +import "database/sql" +import _ "github.com/go-sql-driver/mysql" + +db, err := sql.Open("mysql", "user:password@/dbname") +``` + +[Examples are available in our Wiki](https://github.com/go-sql-driver/mysql/wiki/Examples "Go-MySQL-Driver Examples"). + + +### DSN (Data Source Name) + +The Data Source Name has a common format, like e.g. [PEAR DB](http://pear.php.net/manual/en/package.database.db.intro-dsn.php) uses it, but without type-prefix (optional parts marked by squared brackets): +``` +[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN] +``` + +A DSN in its fullest form: +``` +username:password@protocol(address)/dbname?param=value +``` + +Except for the databasename, all values are optional. So the minimal DSN is: +``` +/dbname +``` + +If you do not want to preselect a database, leave `dbname` empty: +``` +/ +``` +This has the same effect as an empty DSN string: +``` + +``` + +Alternatively, [Config.FormatDSN](https://godoc.org/github.com/go-sql-driver/mysql#Config.FormatDSN) can be used to create a DSN string by filling a struct. + +#### Password +Passwords can consist of any character. Escaping is **not** necessary. + +#### Protocol +See [net.Dial](https://golang.org/pkg/net/#Dial) for more information which networks are available. +In general you should use an Unix domain socket if available and TCP otherwise for best performance. + +#### Address +For TCP and UDP networks, addresses have the form `host[:port]`. +If `port` is omitted, the default port will be used. +If `host` is a literal IPv6 address, it must be enclosed in square brackets. +The functions [net.JoinHostPort](https://golang.org/pkg/net/#JoinHostPort) and [net.SplitHostPort](https://golang.org/pkg/net/#SplitHostPort) manipulate addresses in this form. + +For Unix domain sockets the address is the absolute path to the MySQL-Server-socket, e.g. `/var/run/mysqld/mysqld.sock` or `/tmp/mysql.sock`. + +#### Parameters +*Parameters are case-sensitive!* + +Notice that any of `true`, `TRUE`, `True` or `1` is accepted to stand for a true boolean value. Not surprisingly, false can be specified as any of: `false`, `FALSE`, `False` or `0`. + +##### `allowAllFiles` + +``` +Type: bool +Valid Values: true, false +Default: false +``` + +`allowAllFiles=true` disables the file Whitelist for `LOAD DATA LOCAL INFILE` and allows *all* files. +[*Might be insecure!*](http://dev.mysql.com/doc/refman/5.7/en/load-data-local.html) + +##### `allowCleartextPasswords` + +``` +Type: bool +Valid Values: true, false +Default: false +``` + +`allowCleartextPasswords=true` allows using the [cleartext client side plugin](http://dev.mysql.com/doc/en/cleartext-authentication-plugin.html) if required by an account, such as one defined with the [PAM authentication plugin](http://dev.mysql.com/doc/en/pam-authentication-plugin.html). Sending passwords in clear text may be a security problem in some configurations. To avoid problems if there is any possibility that the password would be intercepted, clients should connect to MySQL Server using a method that protects the password. Possibilities include [TLS / SSL](#tls), IPsec, or a private network. + +##### `allowNativePasswords` + +``` +Type: bool +Valid Values: true, false +Default: true +``` +`allowNativePasswords=false` disallows the usage of MySQL native password method. + +##### `allowOldPasswords` + +``` +Type: bool +Valid Values: true, false +Default: false +``` +`allowOldPasswords=true` allows the usage of the insecure old password method. This should be avoided, but is necessary in some cases. See also [the old_passwords wiki page](https://github.com/go-sql-driver/mysql/wiki/old_passwords). + +##### `charset` + +``` +Type: string +Valid Values: +Default: none +``` + +Sets the charset used for client-server interaction (`"SET NAMES "`). If multiple charsets are set (separated by a comma), the following charset is used if setting the charset failes. This enables for example support for `utf8mb4` ([introduced in MySQL 5.5.3](http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html)) with fallback to `utf8` for older servers (`charset=utf8mb4,utf8`). + +Usage of the `charset` parameter is discouraged because it issues additional queries to the server. +Unless you need the fallback behavior, please use `collation` instead. + +##### `collation` + +``` +Type: string +Valid Values: +Default: utf8_general_ci +``` + +Sets the collation used for client-server interaction on connection. In contrast to `charset`, `collation` does not issue additional queries. If the specified collation is unavailable on the target server, the connection will fail. + +A list of valid charsets for a server is retrievable with `SHOW COLLATION`. + +##### `clientFoundRows` + +``` +Type: bool +Valid Values: true, false +Default: false +``` + +`clientFoundRows=true` causes an UPDATE to return the number of matching rows instead of the number of rows changed. + +##### `columnsWithAlias` + +``` +Type: bool +Valid Values: true, false +Default: false +``` + +When `columnsWithAlias` is true, calls to `sql.Rows.Columns()` will return the table alias and the column name separated by a dot. For example: + +``` +SELECT u.id FROM users as u +``` + +will return `u.id` instead of just `id` if `columnsWithAlias=true`. + +##### `interpolateParams` + +``` +Type: bool +Valid Values: true, false +Default: false +``` + +If `interpolateParams` is true, placeholders (`?`) in calls to `db.Query()` and `db.Exec()` are interpolated into a single query string with given parameters. This reduces the number of roundtrips, since the driver has to prepare a statement, execute it with given parameters and close the statement again with `interpolateParams=false`. + +*This can not be used together with the multibyte encodings BIG5, CP932, GB2312, GBK or SJIS. These are blacklisted as they may [introduce a SQL injection vulnerability](http://stackoverflow.com/a/12118602/3430118)!* + +##### `loc` + +``` +Type: string +Valid Values: +Default: UTC +``` + +Sets the location for time.Time values (when using `parseTime=true`). *"Local"* sets the system's location. See [time.LoadLocation](https://golang.org/pkg/time/#LoadLocation) for details. + +Note that this sets the location for time.Time values but does not change MySQL's [time_zone setting](https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html). For that see the [time_zone system variable](#system-variables), which can also be set as a DSN parameter. + +Please keep in mind, that param values must be [url.QueryEscape](https://golang.org/pkg/net/url/#QueryEscape)'ed. Alternatively you can manually replace the `/` with `%2F`. For example `US/Pacific` would be `loc=US%2FPacific`. + +##### `maxAllowedPacket` +``` +Type: decimal number +Default: 4194304 +``` + +Max packet size allowed in bytes. The default value is 4 MiB and should be adjusted to match the server settings. `maxAllowedPacket=0` can be used to automatically fetch the `max_allowed_packet` variable from server *on every connection*. + +##### `multiStatements` + +``` +Type: bool +Valid Values: true, false +Default: false +``` + +Allow multiple statements in one query. While this allows batch queries, it also greatly increases the risk of SQL injections. Only the result of the first query is returned, all other results are silently discarded. + +When `multiStatements` is used, `?` parameters must only be used in the first statement. + +##### `parseTime` + +``` +Type: bool +Valid Values: true, false +Default: false +``` + +`parseTime=true` changes the output type of `DATE` and `DATETIME` values to `time.Time` instead of `[]byte` / `string` +The date or datetime like `0000-00-00 00:00:00` is converted into zero value of `time.Time`. + + +##### `readTimeout` + +``` +Type: duration +Default: 0 +``` + +I/O read timeout. The value must be a decimal number with a unit suffix (*"ms"*, *"s"*, *"m"*, *"h"*), such as *"30s"*, *"0.5m"* or *"1m30s"*. + +##### `rejectReadOnly` + +``` +Type: bool +Valid Values: true, false +Default: false +``` + + +`rejectReadOnly=true` causes the driver to reject read-only connections. This +is for a possible race condition during an automatic failover, where the mysql +client gets connected to a read-only replica after the failover. + +Note that this should be a fairly rare case, as an automatic failover normally +happens when the primary is down, and the race condition shouldn't happen +unless it comes back up online as soon as the failover is kicked off. On the +other hand, when this happens, a MySQL application can get stuck on a +read-only connection until restarted. It is however fairly easy to reproduce, +for example, using a manual failover on AWS Aurora's MySQL-compatible cluster. + +If you are not relying on read-only transactions to reject writes that aren't +supposed to happen, setting this on some MySQL providers (such as AWS Aurora) +is safer for failovers. + +Note that ERROR 1290 can be returned for a `read-only` server and this option will +cause a retry for that error. However the same error number is used for some +other cases. You should ensure your application will never cause an ERROR 1290 +except for `read-only` mode when enabling this option. + + +##### `serverPubKey` + +``` +Type: string +Valid Values: +Default: none +``` + +Server public keys can be registered with [`mysql.RegisterServerPubKey`](https://godoc.org/github.com/go-sql-driver/mysql#RegisterServerPubKey), which can then be used by the assigned name in the DSN. +Public keys are used to transmit encrypted data, e.g. for authentication. +If the server's public key is known, it should be set manually to avoid expensive and potentially insecure transmissions of the public key from the server to the client each time it is required. + + +##### `timeout` + +``` +Type: duration +Default: OS default +``` + +Timeout for establishing connections, aka dial timeout. The value must be a decimal number with a unit suffix (*"ms"*, *"s"*, *"m"*, *"h"*), such as *"30s"*, *"0.5m"* or *"1m30s"*. + + +##### `tls` + +``` +Type: bool / string +Valid Values: true, false, skip-verify, preferred, +Default: false +``` + +`tls=true` enables TLS / SSL encrypted connection to the server. Use `skip-verify` if you want to use a self-signed or invalid certificate (server side) or use `preferred` to use TLS only when advertised by the server. This is similar to `skip-verify`, but additionally allows a fallback to a connection which is not encrypted. Neither `skip-verify` nor `preferred` add any reliable security. You can use a custom TLS config after registering it with [`mysql.RegisterTLSConfig`](https://godoc.org/github.com/go-sql-driver/mysql#RegisterTLSConfig). + + +##### `writeTimeout` + +``` +Type: duration +Default: 0 +``` + +I/O write timeout. The value must be a decimal number with a unit suffix (*"ms"*, *"s"*, *"m"*, *"h"*), such as *"30s"*, *"0.5m"* or *"1m30s"*. + + +##### System Variables + +Any other parameters are interpreted as system variables: + * `=`: `SET =` + * `=`: `SET =` + * `=%27%27`: `SET =''` + +Rules: +* The values for string variables must be quoted with `'`. +* The values must also be [url.QueryEscape](http://golang.org/pkg/net/url/#QueryEscape)'ed! + (which implies values of string variables must be wrapped with `%27`). + +Examples: + * `autocommit=1`: `SET autocommit=1` + * [`time_zone=%27Europe%2FParis%27`](https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html): `SET time_zone='Europe/Paris'` + * [`tx_isolation=%27REPEATABLE-READ%27`](https://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_tx_isolation): `SET tx_isolation='REPEATABLE-READ'` + + +#### Examples +``` +user@unix(/path/to/socket)/dbname +``` + +``` +root:pw@unix(/tmp/mysql.sock)/myDatabase?loc=Local +``` + +``` +user:password@tcp(localhost:5555)/dbname?tls=skip-verify&autocommit=true +``` + +Treat warnings as errors by setting the system variable [`sql_mode`](https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html): +``` +user:password@/dbname?sql_mode=TRADITIONAL +``` + +TCP via IPv6: +``` +user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?timeout=90s&collation=utf8mb4_unicode_ci +``` + +TCP on a remote host, e.g. Amazon RDS: +``` +id:password@tcp(your-amazonaws-uri.com:3306)/dbname +``` + +Google Cloud SQL on App Engine (First Generation MySQL Server): +``` +user@cloudsql(project-id:instance-name)/dbname +``` + +Google Cloud SQL on App Engine (Second Generation MySQL Server): +``` +user@cloudsql(project-id:regionname:instance-name)/dbname +``` + +TCP using default port (3306) on localhost: +``` +user:password@tcp/dbname?charset=utf8mb4,utf8&sys_var=esc%40ped +``` + +Use the default protocol (tcp) and host (localhost:3306): +``` +user:password@/dbname +``` + +No Database preselected: +``` +user:password@/ +``` + + +### Connection pool and timeouts +The connection pool is managed by Go's database/sql package. For details on how to configure the size of the pool and how long connections stay in the pool see `*DB.SetMaxOpenConns`, `*DB.SetMaxIdleConns`, and `*DB.SetConnMaxLifetime` in the [database/sql documentation](https://golang.org/pkg/database/sql/). The read, write, and dial timeouts for each individual connection are configured with the DSN parameters [`readTimeout`](#readtimeout), [`writeTimeout`](#writetimeout), and [`timeout`](#timeout), respectively. + +## `ColumnType` Support +This driver supports the [`ColumnType` interface](https://golang.org/pkg/database/sql/#ColumnType) introduced in Go 1.8, with the exception of [`ColumnType.Length()`](https://golang.org/pkg/database/sql/#ColumnType.Length), which is currently not supported. + +## `context.Context` Support +Go 1.8 added `database/sql` support for `context.Context`. This driver supports query timeouts and cancellation via contexts. +See [context support in the database/sql package](https://golang.org/doc/go1.8#database_sql) for more details. + + +### `LOAD DATA LOCAL INFILE` support +For this feature you need direct access to the package. Therefore you must change the import path (no `_`): +```go +import "github.com/go-sql-driver/mysql" +``` + +Files must be whitelisted by registering them with `mysql.RegisterLocalFile(filepath)` (recommended) or the Whitelist check must be deactivated by using the DSN parameter `allowAllFiles=true` ([*Might be insecure!*](http://dev.mysql.com/doc/refman/5.7/en/load-data-local.html)). + +To use a `io.Reader` a handler function must be registered with `mysql.RegisterReaderHandler(name, handler)` which returns a `io.Reader` or `io.ReadCloser`. The Reader is available with the filepath `Reader::` then. Choose different names for different handlers and `DeregisterReaderHandler` when you don't need it anymore. + +See the [godoc of Go-MySQL-Driver](https://godoc.org/github.com/go-sql-driver/mysql "golang mysql driver documentation") for details. + + +### `time.Time` support +The default internal output type of MySQL `DATE` and `DATETIME` values is `[]byte` which allows you to scan the value into a `[]byte`, `string` or `sql.RawBytes` variable in your program. + +However, many want to scan MySQL `DATE` and `DATETIME` values into `time.Time` variables, which is the logical opposite in Go to `DATE` and `DATETIME` in MySQL. You can do that by changing the internal output type from `[]byte` to `time.Time` with the DSN parameter `parseTime=true`. You can set the default [`time.Time` location](https://golang.org/pkg/time/#Location) with the `loc` DSN parameter. + +**Caution:** As of Go 1.1, this makes `time.Time` the only variable type you can scan `DATE` and `DATETIME` values into. This breaks for example [`sql.RawBytes` support](https://github.com/go-sql-driver/mysql/wiki/Examples#rawbytes). + +Alternatively you can use the [`NullTime`](https://godoc.org/github.com/go-sql-driver/mysql#NullTime) type as the scan destination, which works with both `time.Time` and `string` / `[]byte`. + + +### Unicode support +Since version 1.1 Go-MySQL-Driver automatically uses the collation `utf8_general_ci` by default. + +Other collations / charsets can be set using the [`collation`](#collation) DSN parameter. + +Version 1.0 of the driver recommended adding `&charset=utf8` (alias for `SET NAMES utf8`) to the DSN to enable proper UTF-8 support. This is not necessary anymore. The [`collation`](#collation) parameter should be preferred to set another collation / charset than the default. + +See http://dev.mysql.com/doc/refman/5.7/en/charset-unicode.html for more details on MySQL's Unicode support. + +## Testing / Development +To run the driver tests you may need to adjust the configuration. See the [Testing Wiki-Page](https://github.com/go-sql-driver/mysql/wiki/Testing "Testing") for details. + +Go-MySQL-Driver is not feature-complete yet. Your help is very appreciated. +If you want to contribute, you can work on an [open issue](https://github.com/go-sql-driver/mysql/issues?state=open) or review a [pull request](https://github.com/go-sql-driver/mysql/pulls). + +See the [Contribution Guidelines](https://github.com/go-sql-driver/mysql/blob/master/CONTRIBUTING.md) for details. + +--------------------------------------- + +## License +Go-MySQL-Driver is licensed under the [Mozilla Public License Version 2.0](https://raw.github.com/go-sql-driver/mysql/master/LICENSE) + +Mozilla summarizes the license scope as follows: +> MPL: The copyleft applies to any files containing MPLed code. + + +That means: + * You can **use** the **unchanged** source code both in private and commercially. + * When distributing, you **must publish** the source code of any **changed files** licensed under the MPL 2.0 under a) the MPL 2.0 itself or b) a compatible license (e.g. GPL 3.0 or Apache License 2.0). + * You **needn't publish** the source code of your library as long as the files licensed under the MPL 2.0 are **unchanged**. + +Please read the [MPL 2.0 FAQ](https://www.mozilla.org/en-US/MPL/2.0/FAQ/) if you have further questions regarding the license. + +You can read the full terms here: [LICENSE](https://raw.github.com/go-sql-driver/mysql/master/LICENSE). + +![Go Gopher and MySQL Dolphin](https://raw.github.com/wiki/go-sql-driver/mysql/go-mysql-driver_m.jpg "Golang Gopher transporting the MySQL Dolphin in a wheelbarrow") + diff --git a/vendor/github.com/go-xorm/builder/.drone.yml b/vendor/github.com/go-xorm/builder/.drone.yml new file mode 100644 index 0000000000..ca40377721 --- /dev/null +++ b/vendor/github.com/go-xorm/builder/.drone.yml @@ -0,0 +1,37 @@ +workspace: + base: /go + path: src/github.com/go-xorm/builder + +clone: + git: + image: plugins/git:next + depth: 50 + tags: true + +matrix: + GO_VERSION: + - 1.8 + - 1.9 + - 1.10 + - 1.11 + +pipeline: + test: + image: golang:${GO_VERSION} + commands: + - go get -u github.com/golang/lint/golint + - go get -u github.com/stretchr/testify/assert + - go get -u github.com/go-xorm/sqlfiddle + - golint ./... + - go test -v -race -coverprofile=coverage.txt -covermode=atomic + when: + event: [ push, tag, pull_request ] + +codecov: + image: robertstettner/drone-codecov + group: build + secrets: [ codecov_token ] + files: + - coverage.txt + when: + event: [ push, pull_request ] \ No newline at end of file diff --git a/vendor/github.com/go-xorm/builder/README.md b/vendor/github.com/go-xorm/builder/README.md new file mode 100644 index 0000000000..cf516d1fd5 --- /dev/null +++ b/vendor/github.com/go-xorm/builder/README.md @@ -0,0 +1,206 @@ +# SQL builder + +[![GitCI.cn](https://gitci.cn/api/badges/go-xorm/builder/status.svg)](https://gitci.cn/go-xorm/builder) [![codecov](https://codecov.io/gh/go-xorm/builder/branch/master/graph/badge.svg)](https://codecov.io/gh/go-xorm/builder) +[![](https://goreportcard.com/badge/github.com/go-xorm/builder)](https://goreportcard.com/report/github.com/go-xorm/builder) + +Package builder is a lightweight and fast SQL builder for Go and XORM. + +Make sure you have installed Go 1.8+ and then: + + go get github.com/go-xorm/builder + +# Insert + +```Go +sql, args, err := builder.Insert(Eq{"c": 1, "d": 2}).Into("table1").ToSQL() + +// INSERT INTO table1 SELECT * FROM table2 +sql, err := builder.Insert().Into("table1").Select().From("table2").ToBoundSQL() + +// INSERT INTO table1 (a, b) SELECT b, c FROM table2 +sql, err = builder.Insert("a, b").Into("table1").Select("b, c").From("table2").ToBoundSQL() +``` + +# Select + +```Go +// Simple Query +sql, args, err := Select("c, d").From("table1").Where(Eq{"a": 1}).ToSQL() +// With join +sql, args, err = Select("c, d").From("table1").LeftJoin("table2", Eq{"table1.id": 1}.And(Lt{"table2.id": 3})). + RightJoin("table3", "table2.id = table3.tid").Where(Eq{"a": 1}).ToSQL() +// From sub query +sql, args, err := Select("sub.id").From(Select("c").From("table1").Where(Eq{"a": 1}), "sub").Where(Eq{"b": 1}).ToSQL() +// From union query +sql, args, err = Select("sub.id").From( + Select("id").From("table1").Where(Eq{"a": 1}).Union("all", Select("id").From("table1").Where(Eq{"a": 2})),"sub"). + Where(Eq{"b": 1}).ToSQL() +// With order by +sql, args, err = Select("a", "b", "c").From("table1").Where(Eq{"f1": "v1", "f2": "v2"}). + OrderBy("a ASC").ToSQL() +// With limit. +// Be careful! You should set up specific dialect for builder before performing a query with LIMIT +sql, args, err = Dialect(MYSQL).Select("a", "b", "c").From("table1").OrderBy("a ASC"). + Limit(5, 10).ToSQL() +``` + +# Update + +```Go +sql, args, err := Update(Eq{"a": 2}).From("table1").Where(Eq{"a": 1}).ToSQL() +``` + +# Delete + +```Go +sql, args, err := Delete(Eq{"a": 1}).From("table1").ToSQL() +``` + +# Union + +```Go +sql, args, err := Select("*").From("a").Where(Eq{"status": "1"}). + Union("all", Select("*").From("a").Where(Eq{"status": "2"})). + Union("distinct", Select("*").From("a").Where(Eq{"status": "3"})). + Union("", Select("*").From("a").Where(Eq{"status": "4"})). + ToSQL() +``` + +# Conditions + +* `Eq` is a redefine of a map, you can give one or more conditions to `Eq` + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(Eq{"a":1}) +// a=? [1] +sql, args, _ := ToSQL(Eq{"b":"c"}.And(Eq{"c": 0})) +// b=? AND c=? ["c", 0] +sql, args, _ := ToSQL(Eq{"b":"c", "c":0}) +// b=? AND c=? ["c", 0] +sql, args, _ := ToSQL(Eq{"b":"c"}.Or(Eq{"b":"d"})) +// b=? OR b=? ["c", "d"] +sql, args, _ := ToSQL(Eq{"b": []string{"c", "d"}}) +// b IN (?,?) ["c", "d"] +sql, args, _ := ToSQL(Eq{"b": 1, "c":[]int{2, 3}}) +// b=? AND c IN (?,?) [1, 2, 3] +``` + +* `Neq` is the same to `Eq` + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(Neq{"a":1}) +// a<>? [1] +sql, args, _ := ToSQL(Neq{"b":"c"}.And(Neq{"c": 0})) +// b<>? AND c<>? ["c", 0] +sql, args, _ := ToSQL(Neq{"b":"c", "c":0}) +// b<>? AND c<>? ["c", 0] +sql, args, _ := ToSQL(Neq{"b":"c"}.Or(Neq{"b":"d"})) +// b<>? OR b<>? ["c", "d"] +sql, args, _ := ToSQL(Neq{"b": []string{"c", "d"}}) +// b NOT IN (?,?) ["c", "d"] +sql, args, _ := ToSQL(Neq{"b": 1, "c":[]int{2, 3}}) +// b<>? AND c NOT IN (?,?) [1, 2, 3] +``` + +* `Gt`, `Gte`, `Lt`, `Lte` + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(Gt{"a", 1}.And(Gte{"b", 2})) +// a>? AND b>=? [1, 2] +sql, args, _ := ToSQL(Lt{"a", 1}.Or(Lte{"b", 2})) +// a? [1, %c%, 2] +``` + +* `Or(conds ...Cond)`, Or can connect one or more conditions via Or + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(Or(Eq{"a":1}, Like{"b", "c"}, Neq{"d", 2})) +// a=? OR b LIKE ? OR d<>? [1, %c%, 2] +sql, args, _ := ToSQL(Or(Eq{"a":1}, And(Like{"b", "c"}, Neq{"d", 2}))) +// a=? OR (b LIKE ? AND d<>?) [1, %c%, 2] +``` + +* `Between` + +```Go +import . "github.com/go-xorm/builder" + +sql, args, _ := ToSQL(Between{"a", 1, 2}) +// a BETWEEN 1 AND 2 +``` + +* Define yourself conditions + +Since `Cond` is an interface. + +```Go +type Cond interface { + WriteTo(Writer) error + And(...Cond) Cond + Or(...Cond) Cond + IsValid() bool +} +``` + +You can define yourself conditions and compose with other `Cond`. \ No newline at end of file diff --git a/vendor/github.com/go-xorm/builder/go.mod b/vendor/github.com/go-xorm/builder/go.mod new file mode 100644 index 0000000000..ef1a659ad1 --- /dev/null +++ b/vendor/github.com/go-xorm/builder/go.mod @@ -0,0 +1 @@ +module "github.com/go-xorm/builder" diff --git a/vendor/github.com/go-xorm/core/.gitignore b/vendor/github.com/go-xorm/core/.gitignore new file mode 100644 index 0000000000..98e6ef67fa --- /dev/null +++ b/vendor/github.com/go-xorm/core/.gitignore @@ -0,0 +1 @@ +*.db diff --git a/vendor/github.com/go-xorm/core/README.md b/vendor/github.com/go-xorm/core/README.md new file mode 100644 index 0000000000..09b72c74b3 --- /dev/null +++ b/vendor/github.com/go-xorm/core/README.md @@ -0,0 +1,116 @@ +Core is a lightweight wrapper of sql.DB. + +[![CircleCI](https://circleci.com/gh/go-xorm/core/tree/master.svg?style=svg)](https://circleci.com/gh/go-xorm/core/tree/master) + +# Open +```Go +db, _ := core.Open(db, connstr) +``` + +# SetMapper +```Go +db.SetMapper(SameMapper()) +``` + +## Scan usage + +### Scan +```Go +rows, _ := db.Query() +for rows.Next() { + rows.Scan() +} +``` + +### ScanMap +```Go +rows, _ := db.Query() +for rows.Next() { + rows.ScanMap() +``` + +### ScanSlice + +You can use `[]string`, `[][]byte`, `[]interface{}`, `[]*string`, `[]sql.NullString` to ScanSclice. Notice, slice's length should be equal or less than select columns. + +```Go +rows, _ := db.Query() +cols, _ := rows.Columns() +for rows.Next() { + var s = make([]string, len(cols)) + rows.ScanSlice(&s) +} +``` + +```Go +rows, _ := db.Query() +cols, _ := rows.Columns() +for rows.Next() { + var s = make([]*string, len(cols)) + rows.ScanSlice(&s) +} +``` + +### ScanStruct +```Go +rows, _ := db.Query() +for rows.Next() { + rows.ScanStructByName() + rows.ScanStructByIndex() +} +``` + +## Query usage +```Go +rows, err := db.Query("select * from table where name = ?", name) + +user = User{ + Name:"lunny", +} +rows, err := db.QueryStruct("select * from table where name = ?Name", + &user) + +var user = map[string]interface{}{ + "name": "lunny", +} +rows, err = db.QueryMap("select * from table where name = ?name", + &user) +``` + +## QueryRow usage +```Go +row := db.QueryRow("select * from table where name = ?", name) + +user = User{ + Name:"lunny", +} +row := db.QueryRowStruct("select * from table where name = ?Name", + &user) + +var user = map[string]interface{}{ + "name": "lunny", +} +row = db.QueryRowMap("select * from table where name = ?name", + &user) +``` + +## Exec usage +```Go +db.Exec("insert into user (`name`, title, age, alias, nick_name,created) values (?,?,?,?,?,?)", name, title, age, alias...) + +user = User{ + Name:"lunny", + Title:"test", + Age: 18, +} +result, err = db.ExecStruct("insert into user (`name`, title, age, alias, nick_name,created) values (?Name,?Title,?Age,?Alias,?NickName,?Created)", + &user) + +var user = map[string]interface{}{ + "Name": "lunny", + "Title": "test", + "Age": 18, +} +result, err = db.ExecMap("insert into user (`name`, title, age, alias, nick_name,created) values (?Name,?Title,?Age,?Alias,?NickName,?Created)", + &user) +``` \ No newline at end of file diff --git a/vendor/github.com/go-xorm/core/benchmark.sh b/vendor/github.com/go-xorm/core/benchmark.sh new file mode 100644 index 0000000000..eab9e57e9f --- /dev/null +++ b/vendor/github.com/go-xorm/core/benchmark.sh @@ -0,0 +1 @@ +go test -v -bench=. -run=XXX diff --git a/vendor/github.com/go-xorm/core/circle.yml b/vendor/github.com/go-xorm/core/circle.yml new file mode 100644 index 0000000000..e6a05be272 --- /dev/null +++ b/vendor/github.com/go-xorm/core/circle.yml @@ -0,0 +1,15 @@ +dependencies: + override: + # './...' is a relative pattern which means all subdirectories + - go get -t -d -v ./... + - go build -v + +database: + override: + - mysql -u root -e "CREATE DATABASE core_test DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci" + +test: + override: + # './...' is a relative pattern which means all subdirectories + - go test -v -race + - go test -v -race --dbtype=sqlite3 diff --git a/vendor/github.com/go-xorm/core/go.mod b/vendor/github.com/go-xorm/core/go.mod new file mode 100644 index 0000000000..70c86bcbc8 --- /dev/null +++ b/vendor/github.com/go-xorm/core/go.mod @@ -0,0 +1 @@ +module "github.com/go-xorm/core" diff --git a/vendor/github.com/go-xorm/xorm/.drone.yml b/vendor/github.com/go-xorm/xorm/.drone.yml new file mode 100644 index 0000000000..0a79ed0216 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/.drone.yml @@ -0,0 +1,125 @@ +workspace: + base: /go + path: src/github.com/go-xorm/xorm + +clone: + git: + image: plugins/git:next + depth: 50 + tags: true + +services: + mysql: + image: mysql:5.7 + environment: + - MYSQL_DATABASE=xorm_test + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + when: + event: [ push, tag, pull_request ] + + pgsql: + image: postgres:9.5 + environment: + - POSTGRES_USER=postgres + - POSTGRES_DB=xorm_test + when: + event: [ push, tag, pull_request ] + + #mssql: + # image: microsoft/mssql-server-linux:2017-CU11 + # environment: + # - ACCEPT_EULA=Y + # - SA_PASSWORD=yourStrong(!)Password + # - MSSQL_PID=Developer + # commands: + # - echo 'CREATE DATABASE xorm_test' > create.sql + # - /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P yourStrong(!)Password -i "create.sql" + +matrix: + GO_VERSION: + - 1.8 + - 1.9 + - 1.10 + - 1.11 + +pipeline: + init_postgres: + image: postgres:9.5 + commands: + # wait for postgres service to become available + - | + until psql -U postgres -d xorm_test -h pgsql \ + -c "SELECT 1;" >/dev/null 2>&1; do sleep 1; done + # query the database + - | + psql -U postgres -d xorm_test -h pgsql \ + -c "create schema xorm;" + + build: + image: golang:${GO_VERSION} + commands: + - go get -t -d -v ./... + - go get -u github.com/go-xorm/core + - go get -u github.com/go-xorm/builder + - go build -v + when: + event: [ push, pull_request ] + + test-sqlite: + image: golang:${GO_VERSION} + commands: + - go get -u github.com/wadey/gocovmerge + - go test -v -race -db="sqlite3" -conn_str="./test.db" -coverprofile=coverage1-1.txt -covermode=atomic + - go test -v -race -db="sqlite3" -conn_str="./test.db" -cache=true -coverprofile=coverage1-2.txt -covermode=atomic + when: + event: [ push, pull_request ] + + test-mysql: + image: golang:${GO_VERSION} + commands: + - go test -v -race -db="mysql" -conn_str="root:@tcp(mysql)/xorm_test" -coverprofile=coverage2-1.txt -covermode=atomic + - go test -v -race -db="mysql" -conn_str="root:@tcp(mysql)/xorm_test" -cache=true -coverprofile=coverage2-2.txt -covermode=atomic + when: + event: [ push, pull_request ] + + test-mysql-utf8mb4: + image: golang:${GO_VERSION} + commands: + - go test -v -race -db="mysql" -conn_str="root:@tcp(mysql)/xorm_test?charset=utf8mb4" -coverprofile=coverage2.1-1.txt -covermode=atomic + - go test -v -race -db="mysql" -conn_str="root:@tcp(mysql)/xorm_test?charset=utf8mb4" -cache=true -coverprofile=coverage2.1-2.txt -covermode=atomic + when: + event: [ push, pull_request ] + + test-mymysql: + image: golang:${GO_VERSION} + commands: + - go test -v -race -db="mymysql" -conn_str="tcp:mysql:3306*xorm_test/root/" -coverprofile=coverage3-1.txt -covermode=atomic + - go test -v -race -db="mymysql" -conn_str="tcp:mysql:3306*xorm_test/root/" -cache=true -coverprofile=coverage3-2.txt -covermode=atomic + when: + event: [ push, pull_request ] + + test-postgres: + image: golang:${GO_VERSION} + commands: + - go test -v -race -db="postgres" -conn_str="postgres://postgres:@pgsql/xorm_test?sslmode=disable" -coverprofile=coverage4-1.txt -covermode=atomic + - go test -v -race -db="postgres" -conn_str="postgres://postgres:@pgsql/xorm_test?sslmode=disable" -cache=true -coverprofile=coverage4-2.txt -covermode=atomic + when: + event: [ push, pull_request ] + + test-postgres-schema: + image: golang:${GO_VERSION} + commands: + - go test -v -race -db="postgres" -conn_str="postgres://postgres:@pgsql/xorm_test?sslmode=disable" -schema=xorm -coverprofile=coverage5-1.txt -covermode=atomic + - go test -v -race -db="postgres" -conn_str="postgres://postgres:@pgsql/xorm_test?sslmode=disable" -schema=xorm -cache=true -coverprofile=coverage5-2.txt -covermode=atomic + - gocovmerge coverage1-1.txt coverage1-2.txt coverage2-1.txt coverage2-2.txt coverage2.1-1.txt coverage2.1-2.txt coverage3-1.txt coverage3-2.txt coverage4-1.txt coverage4-2.txt coverage5-1.txt coverage5-2.txt > coverage.txt + when: + event: [ push, pull_request ] + + #coverage: + # image: robertstettner/drone-codecov + # secrets: [ codecov_token ] + # files: + # - coverage.txt + # when: + # event: [ push, pull_request ] + # branch: [ master ] \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/.gitignore b/vendor/github.com/go-xorm/xorm/.gitignore new file mode 100644 index 0000000000..f1757b9830 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/.gitignore @@ -0,0 +1,33 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so +*.db + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe + +*.log +.vendor +temp_test.go +.vscode +xorm.test +*.sqlite3 +test.db.sql + +.idea/ diff --git a/vendor/github.com/go-xorm/xorm/CONTRIBUTING.md b/vendor/github.com/go-xorm/xorm/CONTRIBUTING.md new file mode 100644 index 0000000000..37f4bc5fa8 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/CONTRIBUTING.md @@ -0,0 +1,46 @@ +## Contributing to xorm + +`xorm` has a backlog of [pull requests](https://help.github.com/articles/using-pull-requests), but contributions are still very +much welcome. You can help with patch review, submitting bug reports, +or adding new functionality. There is no formal style guide, but +please conform to the style of existing code and general Go formatting +conventions when submitting patches. + +* [fork a repo](https://help.github.com/articles/fork-a-repo) +* [creating a pull request ](https://help.github.com/articles/creating-a-pull-request) + +### Language + +Since `xorm` is a world-wide open source project, please describe your issues or code changes in English as soon as possible. + +### Sign your codes with comments +``` +// !! your comments + +e.g., + +// !lunny! this is comments made by lunny +``` + +### Patch review + +Help review existing open [pull requests](https://help.github.com/articles/using-pull-requests) by commenting on the code or +proposed functionality. + +### Bug reports + +We appreciate any bug reports, but especially ones with self-contained +(doesn't depend on code outside of xorm), minimal (can't be simplified +further) test cases. It's especially helpful if you can submit a pull +request with just the failing test case(you can find some example test file like [session_get_test.go](https://github.com/go-xorm/xorm/blob/master/session_get_test.go)). + +If you implements a new database interface, you maybe need to add a test_.sh file. +For example, [mysql_test.go](https://github.com/go-xorm/xorm/blob/master/test_mysql.sh) + +### New functionality + +There are a number of pending patches for new functionality, so +additional feature patches will take a while to merge. Still, patches +are generally reviewed based on usefulness and complexity in addition +to time-in-queue, so if you have a knockout idea, take a shot. Feel +free to open an issue discussion your proposed patch beforehand. diff --git a/vendor/github.com/go-xorm/xorm/README.md b/vendor/github.com/go-xorm/xorm/README.md new file mode 100644 index 0000000000..6a57606e7f --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/README.md @@ -0,0 +1,496 @@ +# xorm + +[中文](https://github.com/go-xorm/xorm/blob/master/README_CN.md) + +Xorm is a simple and powerful ORM for Go. + +[![CircleCI](https://circleci.com/gh/go-xorm/xorm.svg?style=shield)](https://circleci.com/gh/go-xorm/xorm) [![codecov](https://codecov.io/gh/go-xorm/xorm/branch/master/graph/badge.svg)](https://codecov.io/gh/go-xorm/xorm) +[![](https://goreportcard.com/badge/github.com/go-xorm/xorm)](https://goreportcard.com/report/github.com/go-xorm/xorm) +[![Join the chat at https://img.shields.io/discord/323460943201959939.svg](https://img.shields.io/discord/323460943201959939.svg)](https://discord.gg/HuR2CF3) + +## Features + +* Struct <-> Table Mapping Support + +* Chainable APIs + +* Transaction Support + +* Both ORM and raw SQL operation Support + +* Sync database schema Support + +* Query Cache speed up + +* Database Reverse support, See [Xorm Tool README](https://github.com/go-xorm/cmd/blob/master/README.md) + +* Simple cascade loading support + +* Optimistic Locking support + +* SQL Builder support via [github.com/go-xorm/builder](https://github.com/go-xorm/builder) + +* Automatical Read/Write seperatelly + +* Postgres schema support + +* Context Cache support + +## Drivers Support + +Drivers for Go's sql package which currently support database/sql includes: + +* Mysql: [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) + +* MyMysql: [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/tree/master/godrv) + +* Postgres: [github.com/lib/pq](https://github.com/lib/pq) + +* Tidb: [github.com/pingcap/tidb](https://github.com/pingcap/tidb) + +* SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) + +* MsSql: [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb) + +* Oracle: [github.com/mattn/go-oci8](https://github.com/mattn/go-oci8) (experiment) + +## Installation + + go get github.com/go-xorm/xorm + +## Documents + +* [Manual](http://xorm.io/docs) + +* [GoDoc](http://godoc.org/github.com/go-xorm/xorm) + +## Quick Start + +* Create Engine + +```Go +engine, err := xorm.NewEngine(driverName, dataSourceName) +``` + +* Define a struct and Sync2 table struct to database + +```Go +type User struct { + Id int64 + Name string + Salt string + Age int + Passwd string `xorm:"varchar(200)"` + Created time.Time `xorm:"created"` + Updated time.Time `xorm:"updated"` +} + +err := engine.Sync2(new(User)) +``` + +* Create Engine Group + +```Go +dataSourceNameSlice := []string{masterDataSourceName, slave1DataSourceName, slave2DataSourceName} +engineGroup, err := xorm.NewEngineGroup(driverName, dataSourceNameSlice) +``` + +```Go +masterEngine, err := xorm.NewEngine(driverName, masterDataSourceName) +slave1Engine, err := xorm.NewEngine(driverName, slave1DataSourceName) +slave2Engine, err := xorm.NewEngine(driverName, slave2DataSourceName) +engineGroup, err := xorm.NewEngineGroup(masterEngine, []*Engine{slave1Engine, slave2Engine}) +``` + +Then all place where `engine` you can just use `engineGroup`. + +* `Query` runs a SQL string, the returned results is `[]map[string][]byte`, `QueryString` returns `[]map[string]string`, `QueryInterface` returns `[]map[string]interface{}`. + +```Go +results, err := engine.Query("select * from user") +results, err := engine.Where("a = 1").Query() + +results, err := engine.QueryString("select * from user") +results, err := engine.Where("a = 1").QueryString() + +results, err := engine.QueryInterface("select * from user") +results, err := engine.Where("a = 1").QueryInterface() +``` + +* `Exec` runs a SQL string, it returns `affected` and `error` + +```Go +affected, err := engine.Exec("update user set age = ? where name = ?", age, name) +``` + +* `Insert` one or multiple records to database + +```Go +affected, err := engine.Insert(&user) +// INSERT INTO struct () values () + +affected, err := engine.Insert(&user1, &user2) +// INSERT INTO struct1 () values () +// INSERT INTO struct2 () values () + +affected, err := engine.Insert(&users) +// INSERT INTO struct () values (),(),() + +affected, err := engine.Insert(&user1, &users) +// INSERT INTO struct1 () values () +// INSERT INTO struct2 () values (),(),() +``` + +* `Get` query one record from database + +```Go +has, err := engine.Get(&user) +// SELECT * FROM user LIMIT 1 + +has, err := engine.Where("name = ?", name).Desc("id").Get(&user) +// SELECT * FROM user WHERE name = ? ORDER BY id DESC LIMIT 1 + +var name string +has, err := engine.Where("id = ?", id).Cols("name").Get(&name) +// SELECT name FROM user WHERE id = ? + +var id int64 +has, err := engine.Where("name = ?", name).Cols("id").Get(&id) +has, err := engine.SQL("select id from user").Get(&id) +// SELECT id FROM user WHERE name = ? + +var valuesMap = make(map[string]string) +has, err := engine.Where("id = ?", id).Get(&valuesMap) +// SELECT * FROM user WHERE id = ? + +var valuesSlice = make([]interface{}, len(cols)) +has, err := engine.Where("id = ?", id).Cols(cols...).Get(&valuesSlice) +// SELECT col1, col2, col3 FROM user WHERE id = ? +``` + +* `Exist` check if one record exist on table + +```Go +has, err := testEngine.Exist(new(RecordExist)) +// SELECT * FROM record_exist LIMIT 1 + +has, err = testEngine.Exist(&RecordExist{ + Name: "test1", + }) +// SELECT * FROM record_exist WHERE name = ? LIMIT 1 + +has, err = testEngine.Where("name = ?", "test1").Exist(&RecordExist{}) +// SELECT * FROM record_exist WHERE name = ? LIMIT 1 + +has, err = testEngine.SQL("select * from record_exist where name = ?", "test1").Exist() +// select * from record_exist where name = ? + +has, err = testEngine.Table("record_exist").Exist() +// SELECT * FROM record_exist LIMIT 1 + +has, err = testEngine.Table("record_exist").Where("name = ?", "test1").Exist() +// SELECT * FROM record_exist WHERE name = ? LIMIT 1 +``` + +* `Find` query multiple records from database, also you can use join and extends + +```Go +var users []User +err := engine.Where("name = ?", name).And("age > 10").Limit(10, 0).Find(&users) +// SELECT * FROM user WHERE name = ? AND age > 10 limit 10 offset 0 + +type Detail struct { + Id int64 + UserId int64 `xorm:"index"` +} + +type UserDetail struct { + User `xorm:"extends"` + Detail `xorm:"extends"` +} + +var users []UserDetail +err := engine.Table("user").Select("user.*, detail.*"). + Join("INNER", "detail", "detail.user_id = user.id"). + Where("user.name = ?", name).Limit(10, 0). + Find(&users) +// SELECT user.*, detail.* FROM user INNER JOIN detail WHERE user.name = ? limit 10 offset 0 +``` + +* `Iterate` and `Rows` query multiple records and record by record handle, there are two methods Iterate and Rows + +```Go +err := engine.Iterate(&User{Name:name}, func(idx int, bean interface{}) error { + user := bean.(*User) + return nil +}) +// SELECT * FROM user + +err := engine.BufferSize(100).Iterate(&User{Name:name}, func(idx int, bean interface{}) error { + user := bean.(*User) + return nil +}) +// SELECT * FROM user Limit 0, 100 +// SELECT * FROM user Limit 101, 100 + +rows, err := engine.Rows(&User{Name:name}) +// SELECT * FROM user +defer rows.Close() +bean := new(Struct) +for rows.Next() { + err = rows.Scan(bean) +} +``` + +* `Update` update one or more records, default will update non-empty and non-zero fields except when you use Cols, AllCols and so on. + +```Go +affected, err := engine.ID(1).Update(&user) +// UPDATE user SET ... Where id = ? + +affected, err := engine.Update(&user, &User{Name:name}) +// UPDATE user SET ... Where name = ? + +var ids = []int64{1, 2, 3} +affected, err := engine.In("id", ids).Update(&user) +// UPDATE user SET ... Where id IN (?, ?, ?) + +// force update indicated columns by Cols +affected, err := engine.ID(1).Cols("age").Update(&User{Name:name, Age: 12}) +// UPDATE user SET age = ?, updated=? Where id = ? + +// force NOT update indicated columns by Omit +affected, err := engine.ID(1).Omit("name").Update(&User{Name:name, Age: 12}) +// UPDATE user SET age = ?, updated=? Where id = ? + +affected, err := engine.ID(1).AllCols().Update(&user) +// UPDATE user SET name=?,age=?,salt=?,passwd=?,updated=? Where id = ? +``` + +* `Delete` delete one or more records, Delete MUST have condition + +```Go +affected, err := engine.Where(...).Delete(&user) +// DELETE FROM user Where ... + +affected, err := engine.ID(2).Delete(&user) +// DELETE FROM user Where id = ? +``` + +* `Count` count records + +```Go +counts, err := engine.Count(&user) +// SELECT count(*) AS total FROM user +``` + +* `Sum` sum functions + +```Go +agesFloat64, err := engine.Sum(&user, "age") +// SELECT sum(age) AS total FROM user + +agesInt64, err := engine.SumInt(&user, "age") +// SELECT sum(age) AS total FROM user + +sumFloat64Slice, err := engine.Sums(&user, "age", "score") +// SELECT sum(age), sum(score) FROM user + +sumInt64Slice, err := engine.SumsInt(&user, "age", "score") +// SELECT sum(age), sum(score) FROM user +``` + +* Query conditions builder + +```Go +err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e"))).Find(&users) +// SELECT id, name ... FROM user WHERE a NOT IN (?, ?) AND b IN (?, ?, ?) +``` + +* Multiple operations in one go routine, no transation here but resue session memory + +```Go +session := engine.NewSession() +defer session.Close() + +user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()} +if _, err := session.Insert(&user1); err != nil { + return err +} + +user2 := Userinfo{Username: "yyy"} +if _, err := session.Where("id = ?", 2).Update(&user2); err != nil { + return err +} + +if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil { + return err +} + +return nil +``` + +* Transation should on one go routine. There is transaction and resue session memory + +```Go +session := engine.NewSession() +defer session.Close() + +// add Begin() before any action +if err := session.Begin(); err != nil { + // if returned then will rollback automatically + return err +} + +user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()} +if _, err := session.Insert(&user1); err != nil { + return err +} + +user2 := Userinfo{Username: "yyy"} +if _, err := session.Where("id = ?", 2).Update(&user2); err != nil { + return err +} + +if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil { + return err +} + +// add Commit() after all actions +return session.Commit() +``` + +* Or you can use `Transaction` to replace above codes. + +```Go +res, err := engine.Transaction(func(sess *xorm.Session) (interface{}, error) { + user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()} + if _, err := session.Insert(&user1); err != nil { + return nil, err + } + + user2 := Userinfo{Username: "yyy"} + if _, err := session.Where("id = ?", 2).Update(&user2); err != nil { + return nil, err + } + + if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil { + return nil, err + } + return nil, nil +}) +``` + +* Context Cache, if enabled, current query result will be cached on session and be used by next same statement on the same session. + +```Go + sess := engine.NewSession() + defer sess.Close() + + var context = xorm.NewMemoryContextCache() + + var c2 ContextGetStruct + has, err := sess.ID(1).ContextCache(context).Get(&c2) + assert.NoError(t, err) + assert.True(t, has) + assert.EqualValues(t, 1, c2.Id) + assert.EqualValues(t, "1", c2.Name) + sql, args := sess.LastSQL() + assert.True(t, len(sql) > 0) + assert.True(t, len(args) > 0) + + var c3 ContextGetStruct + has, err = sess.ID(1).ContextCache(context).Get(&c3) + assert.NoError(t, err) + assert.True(t, has) + assert.EqualValues(t, 1, c3.Id) + assert.EqualValues(t, "1", c3.Name) + sql, args = sess.LastSQL() + assert.True(t, len(sql) == 0) + assert.True(t, len(args) == 0) +``` + +## Contributing + +If you want to pull request, please see [CONTRIBUTING](https://github.com/go-xorm/xorm/blob/master/CONTRIBUTING.md). And we also provide [Xorm on Google Groups](https://groups.google.com/forum/#!forum/xorm) to discuss. + +## Credits + +### Contributors + +This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. + + +### Backers + +Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/xorm#backer)] + + + +### Sponsors + +Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/xorm#sponsor)] + +## Changelog + +* **v0.7.0** + * Some bugs fixed + +* **v0.6.6** + * Some bugs fixed + +* **v0.6.5** + * Postgres schema support + * vgo support + * Add FindAndCount + * Database special params support via NewEngineWithParams + * Some bugs fixed + +* **v0.6.4** + * Automatical Read/Write seperatelly + * Query/QueryString/QueryInterface and action with Where/And + * Get support non-struct variables + * BufferSize on Iterate + * fix some other bugs. + +[More changes ...](https://github.com/go-xorm/manual-en-US/tree/master/chapter-16) + +## Cases + +* [studygolang](http://studygolang.com/) - [github.com/studygolang/studygolang](https://github.com/studygolang/studygolang) + +* [Gitea](http://gitea.io) - [github.com/go-gitea/gitea](http://github.com/go-gitea/gitea) + +* [Gogs](http://try.gogits.org) - [github.com/gogits/gogs](http://github.com/gogits/gogs) + +* [grafana](https://grafana.com/) - [github.com/grafana/grafana](http://github.com/grafana/grafana) + +* [github.com/m3ng9i/qreader](https://github.com/m3ng9i/qreader) + +* [Wego](http://github.com/go-tango/wego) + +* [Docker.cn](https://docker.cn/) + +* [Xorm Adapter](https://github.com/casbin/xorm-adapter) for [Casbin](https://github.com/casbin/casbin) - [github.com/casbin/xorm-adapter](https://github.com/casbin/xorm-adapter) + +* [Gorevel](http://gorevel.cn/) - [github.com/goofcc/gorevel](http://github.com/goofcc/gorevel) + +* [Gowalker](http://gowalker.org) - [github.com/Unknwon/gowalker](http://github.com/Unknwon/gowalker) + +* [Gobuild.io](http://gobuild.io) - [github.com/shxsun/gobuild](http://github.com/shxsun/gobuild) + +* [Sudo China](http://sudochina.com) - [github.com/insionng/toropress](http://github.com/insionng/toropress) + +* [Godaily](http://godaily.org) - [github.com/govc/godaily](http://github.com/govc/godaily) + +* [YouGam](http://www.yougam.com/) + +* [GoCMS - github.com/zzboy/GoCMS](https://github.com/zzdboy/GoCMS) + +* [GoBBS - gobbs.domolo.com](http://gobbs.domolo.com/) + +* [go-blog](http://wangcheng.me) - [github.com/easykoo/go-blog](https://github.com/easykoo/go-blog) + +## LICENSE + +BSD License [http://creativecommons.org/licenses/BSD/](http://creativecommons.org/licenses/BSD/) \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/README_CN.md b/vendor/github.com/go-xorm/xorm/README_CN.md new file mode 100644 index 0000000000..e2ed95b62c --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/README_CN.md @@ -0,0 +1,500 @@ +# xorm + +[English](https://github.com/go-xorm/xorm/blob/master/README.md) + +xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。 + +[![CircleCI](https://circleci.com/gh/go-xorm/xorm.svg?style=shield)](https://circleci.com/gh/go-xorm/xorm) [![codecov](https://codecov.io/gh/go-xorm/xorm/branch/master/graph/badge.svg)](https://codecov.io/gh/go-xorm/xorm) +[![](https://goreportcard.com/badge/github.com/go-xorm/xorm)](https://goreportcard.com/report/github.com/go-xorm/xorm) +[![Join the chat at https://img.shields.io/discord/323460943201959939.svg](https://img.shields.io/discord/323460943201959939.svg)](https://discord.gg/HuR2CF3) + +## 特性 + +* 支持Struct和数据库表之间的灵活映射,并支持自动同步 + +* 事务支持 + +* 同时支持原始SQL语句和ORM操作的混合执行 + +* 使用连写来简化调用 + +* 支持使用Id, In, Where, Limit, Join, Having, Table, Sql, Cols等函数和结构体等方式作为条件 + +* 支持级联加载Struct + +* Schema支持(仅Postgres) + +* 支持缓存 + +* 支持根据数据库自动生成xorm的结构体 + +* 支持记录版本(即乐观锁) + +* 内置SQL Builder支持 + +* 上下文缓存支持 + +## 驱动支持 + +目前支持的Go数据库驱动和对应的数据库如下: + +* Mysql: [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) + +* MyMysql: [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/godrv) + +* Postgres: [github.com/lib/pq](https://github.com/lib/pq) + +* Tidb: [github.com/pingcap/tidb](https://github.com/pingcap/tidb) + +* SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) + +* MsSql: [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb) + +* MsSql: [github.com/lunny/godbc](https://github.com/lunny/godbc) + +* Oracle: [github.com/mattn/go-oci8](https://github.com/mattn/go-oci8) (试验性支持) + +## 安装 + + go get github.com/go-xorm/xorm + +## 文档 + +* [操作指南](http://xorm.io/docs) + +* [GoWalker代码文档](http://gowalker.org/github.com/go-xorm/xorm) + +* [Godoc代码文档](http://godoc.org/github.com/go-xorm/xorm) + +# 快速开始 + +* 第一步创建引擎,driverName, dataSourceName和database/sql接口相同 + +```Go +engine, err := xorm.NewEngine(driverName, dataSourceName) +``` + +* 定义一个和表同步的结构体,并且自动同步结构体到数据库 + +```Go +type User struct { + Id int64 + Name string + Salt string + Age int + Passwd string `xorm:"varchar(200)"` + Created time.Time `xorm:"created"` + Updated time.Time `xorm:"updated"` +} + +err := engine.Sync2(new(User)) +``` + +* 创建Engine组 + +```Go +dataSourceNameSlice := []string{masterDataSourceName, slave1DataSourceName, slave2DataSourceName} +engineGroup, err := xorm.NewEngineGroup(driverName, dataSourceNameSlice) +``` + +```Go +masterEngine, err := xorm.NewEngine(driverName, masterDataSourceName) +slave1Engine, err := xorm.NewEngine(driverName, slave1DataSourceName) +slave2Engine, err := xorm.NewEngine(driverName, slave2DataSourceName) +engineGroup, err := xorm.NewEngineGroup(masterEngine, []*Engine{slave1Engine, slave2Engine}) +``` + +所有使用 `engine` 都可以简单的用 `engineGroup` 来替换。 + +* `Query` 最原始的也支持SQL语句查询,返回的结果类型为 []map[string][]byte。`QueryString` 返回 []map[string]string, `QueryInterface` 返回 `[]map[string]interface{}`. + +```Go +results, err := engine.Query("select * from user") +results, err := engine.Where("a = 1").Query() + +results, err := engine.QueryString("select * from user") +results, err := engine.Where("a = 1").QueryString() + +results, err := engine.QueryInterface("select * from user") +results, err := engine.Where("a = 1").QueryInterface() +``` + +* `Exec` 执行一个SQL语句 + +```Go +affected, err := engine.Exec("update user set age = ? where name = ?", age, name) +``` + +* `Insert` 插入一条或者多条记录 + +```Go +affected, err := engine.Insert(&user) +// INSERT INTO struct () values () + +affected, err := engine.Insert(&user1, &user2) +// INSERT INTO struct1 () values () +// INSERT INTO struct2 () values () + +affected, err := engine.Insert(&users) +// INSERT INTO struct () values (),(),() + +affected, err := engine.Insert(&user1, &users) +// INSERT INTO struct1 () values () +// INSERT INTO struct2 () values (),(),() +``` + +* `Get` 查询单条记录 + +```Go +has, err := engine.Get(&user) +// SELECT * FROM user LIMIT 1 + +has, err := engine.Where("name = ?", name).Desc("id").Get(&user) +// SELECT * FROM user WHERE name = ? ORDER BY id DESC LIMIT 1 + +var name string +has, err := engine.Where("id = ?", id).Cols("name").Get(&name) +// SELECT name FROM user WHERE id = ? + +var id int64 +has, err := engine.Where("name = ?", name).Cols("id").Get(&id) +has, err := engine.SQL("select id from user").Get(&id) +// SELECT id FROM user WHERE name = ? + +var valuesMap = make(map[string]string) +has, err := engine.Where("id = ?", id).Get(&valuesMap) +// SELECT * FROM user WHERE id = ? + +var valuesSlice = make([]interface{}, len(cols)) +has, err := engine.Where("id = ?", id).Cols(cols...).Get(&valuesSlice) +// SELECT col1, col2, col3 FROM user WHERE id = ? +``` + +* `Exist` 检测记录是否存在 + +```Go +has, err := testEngine.Exist(new(RecordExist)) +// SELECT * FROM record_exist LIMIT 1 + +has, err = testEngine.Exist(&RecordExist{ + Name: "test1", + }) +// SELECT * FROM record_exist WHERE name = ? LIMIT 1 + +has, err = testEngine.Where("name = ?", "test1").Exist(&RecordExist{}) +// SELECT * FROM record_exist WHERE name = ? LIMIT 1 + +has, err = testEngine.SQL("select * from record_exist where name = ?", "test1").Exist() +// select * from record_exist where name = ? + +has, err = testEngine.Table("record_exist").Exist() +// SELECT * FROM record_exist LIMIT 1 + +has, err = testEngine.Table("record_exist").Where("name = ?", "test1").Exist() +// SELECT * FROM record_exist WHERE name = ? LIMIT 1 +``` + +* `Find` 查询多条记录,当然可以使用Join和extends来组合使用 + +```Go +var users []User +err := engine.Where("name = ?", name).And("age > 10").Limit(10, 0).Find(&users) +// SELECT * FROM user WHERE name = ? AND age > 10 limit 10 offset 0 + +type Detail struct { + Id int64 + UserId int64 `xorm:"index"` +} + +type UserDetail struct { + User `xorm:"extends"` + Detail `xorm:"extends"` +} + +var users []UserDetail +err := engine.Table("user").Select("user.*, detail.*") + Join("INNER", "detail", "detail.user_id = user.id"). + Where("user.name = ?", name).Limit(10, 0). + Find(&users) +// SELECT user.*, detail.* FROM user INNER JOIN detail WHERE user.name = ? limit 10 offset 0 +``` + +* `Iterate` 和 `Rows` 根据条件遍历数据库,可以有两种方式: Iterate and Rows + +```Go +err := engine.Iterate(&User{Name:name}, func(idx int, bean interface{}) error { + user := bean.(*User) + return nil +}) +// SELECT * FROM user + +err := engine.BufferSize(100).Iterate(&User{Name:name}, func(idx int, bean interface{}) error { + user := bean.(*User) + return nil +}) +// SELECT * FROM user Limit 0, 100 +// SELECT * FROM user Limit 101, 100 + +rows, err := engine.Rows(&User{Name:name}) +// SELECT * FROM user +defer rows.Close() +bean := new(Struct) +for rows.Next() { + err = rows.Scan(bean) +} +``` + +* `Update` 更新数据,除非使用Cols,AllCols函数指明,默认只更新非空和非0的字段 + +```Go +affected, err := engine.ID(1).Update(&user) +// UPDATE user SET ... Where id = ? + +affected, err := engine.Update(&user, &User{Name:name}) +// UPDATE user SET ... Where name = ? + +var ids = []int64{1, 2, 3} +affected, err := engine.In(ids).Update(&user) +// UPDATE user SET ... Where id IN (?, ?, ?) + +// force update indicated columns by Cols +affected, err := engine.ID(1).Cols("age").Update(&User{Name:name, Age: 12}) +// UPDATE user SET age = ?, updated=? Where id = ? + +// force NOT update indicated columns by Omit +affected, err := engine.ID(1).Omit("name").Update(&User{Name:name, Age: 12}) +// UPDATE user SET age = ?, updated=? Where id = ? + +affected, err := engine.ID(1).AllCols().Update(&user) +// UPDATE user SET name=?,age=?,salt=?,passwd=?,updated=? Where id = ? +``` + +* `Delete` 删除记录,需要注意,删除必须至少有一个条件,否则会报错。要清空数据库可以用EmptyTable + +```Go +affected, err := engine.Where(...).Delete(&user) +// DELETE FROM user Where ... + +affected, err := engine.ID(2).Delete(&user) +// DELETE FROM user Where id = ? +``` + +* `Count` 获取记录条数 + +```Go +counts, err := engine.Count(&user) +// SELECT count(*) AS total FROM user +``` + +* `Sum` 求和函数 + +```Go +agesFloat64, err := engine.Sum(&user, "age") +// SELECT sum(age) AS total FROM user + +agesInt64, err := engine.SumInt(&user, "age") +// SELECT sum(age) AS total FROM user + +sumFloat64Slice, err := engine.Sums(&user, "age", "score") +// SELECT sum(age), sum(score) FROM user + +sumInt64Slice, err := engine.SumsInt(&user, "age", "score") +// SELECT sum(age), sum(score) FROM user +``` + +* 条件编辑器 + +```Go +err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e"))).Find(&users) +// SELECT id, name ... FROM user WHERE a NOT IN (?, ?) AND b IN (?, ?, ?) +``` + +* 在一个Go程中多次操作数据库,但没有事务 + +```Go +session := engine.NewSession() +defer session.Close() + +user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()} +if _, err := session.Insert(&user1); err != nil { + return err +} + +user2 := Userinfo{Username: "yyy"} +if _, err := session.Where("id = ?", 2).Update(&user2); err != nil { + return err +} + +if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil { + return err +} + +return nil +``` + +* 在一个Go程中有事务 + +```Go +session := engine.NewSession() +defer session.Close() + +// add Begin() before any action +if err := session.Begin(); err != nil { + // if returned then will rollback automatically + return err +} + +user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()} +if _, err := session.Insert(&user1); err != nil { + return err +} + +user2 := Userinfo{Username: "yyy"} +if _, err := session.Where("id = ?", 2).Update(&user2); err != nil { + return err +} + +if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil { + return err +} + +// add Commit() after all actions +return session.Commit() +``` + +* 事物的简写方法 + +```Go +res, err := engine.Transaction(func(session *xorm.Session) (interface{}, error) { + user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()} + if _, err := session.Insert(&user1); err != nil { + return nil, err + } + + user2 := Userinfo{Username: "yyy"} + if _, err := session.Where("id = ?", 2).Update(&user2); err != nil { + return nil, err + } + + if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil { + return nil, err + } + return nil, nil +}) +``` + +* 上下文缓存,如果启用,那么针对单个对象的查询将会被缓存到系统中,可以被下一个查询使用。 + +```Go + sess := engine.NewSession() + defer sess.Close() + + var context = xorm.NewMemoryContextCache() + + var c2 ContextGetStruct + has, err := sess.ID(1).ContextCache(context).Get(&c2) + assert.NoError(t, err) + assert.True(t, has) + assert.EqualValues(t, 1, c2.Id) + assert.EqualValues(t, "1", c2.Name) + sql, args := sess.LastSQL() + assert.True(t, len(sql) > 0) + assert.True(t, len(args) > 0) + + var c3 ContextGetStruct + has, err = sess.ID(1).ContextCache(context).Get(&c3) + assert.NoError(t, err) + assert.True(t, has) + assert.EqualValues(t, 1, c3.Id) + assert.EqualValues(t, "1", c3.Name) + sql, args = sess.LastSQL() + assert.True(t, len(sql) == 0) + assert.True(t, len(args) == 0) +``` + +## 贡献 + +如果您也想为Xorm贡献您的力量,请查看 [CONTRIBUTING](https://github.com/go-xorm/xorm/blob/master/CONTRIBUTING.md)。您也可以加入QQ群 技术帮助和讨论。 +群一:280360085 (已满) +群二:795010183 + +## Credits + +### Contributors + +感谢所有的贡献者. [[Contribute](CONTRIBUTING.md)]. + + +### Backers + +感谢我们所有的 backers! 🙏 [[成为 backer](https://opencollective.com/xorm#backer)] + + + +### Sponsors + +成为 sponsor 来支持 xorm。您的 logo 将会被显示并被链接到您的网站。 [[成为 sponsor](https://opencollective.com/xorm#sponsor)] + +# 案例 + +* [Go语言中文网](http://studygolang.com/) - [github.com/studygolang/studygolang](https://github.com/studygolang/studygolang) + +* [Gitea](http://gitea.io) - [github.com/go-gitea/gitea](http://github.com/go-gitea/gitea) + +* [Gogs](http://try.gogits.org) - [github.com/gogits/gogs](http://github.com/gogits/gogs) + +* [grafana](https://grafana.com/) - [github.com/grafana/grafana](http://github.com/grafana/grafana) + +* [github.com/m3ng9i/qreader](https://github.com/m3ng9i/qreader) + +* [Wego](http://github.com/go-tango/wego) + +* [Docker.cn](https://docker.cn/) + +* [Xorm Adapter](https://github.com/casbin/xorm-adapter) for [Casbin](https://github.com/casbin/casbin) - [github.com/casbin/xorm-adapter](https://github.com/casbin/xorm-adapter) + +* [Gowalker](http://gowalker.org) - [github.com/Unknwon/gowalker](http://github.com/Unknwon/gowalker) + +* [Gobuild.io](http://gobuild.io) - [github.com/shxsun/gobuild](http://github.com/shxsun/gobuild) + +* [Sudo China](http://sudochina.com) - [github.com/insionng/toropress](http://github.com/insionng/toropress) + +* [Godaily](http://godaily.org) - [github.com/govc/godaily](http://github.com/govc/godaily) + +* [YouGam](http://www.yougam.com/) + +* [GoCMS - github.com/zzboy/GoCMS](https://github.com/zzdboy/GoCMS) + +* [GoBBS - gobbs.domolo.com](http://gobbs.domolo.com/) + +* [go-blog](http://wangcheng.me) - [github.com/easykoo/go-blog](https://github.com/easykoo/go-blog) + + +## 更新日志 + +* **v0.7.0** + * 修正部分Bug + +* **v0.6.6** + * 修正部分Bug + +* **v0.6.5** + * 通过 engine.SetSchema 来支持 schema,当前仅支持Postgres + * vgo 支持 + * 新增 `FindAndCount` 函数 + * 通过 `NewEngineWithParams` 支持数据库特别参数 + * 修正部分Bug + +* **v0.6.4** + * 自动读写分离支持 + * Query/QueryString/QueryInterface 支持与 Where/And 合用 + * `Get` 支持获取非结构体变量 + * `Iterate` 支持 `BufferSize` + * 修正部分Bug + +[更多更新日志...](https://github.com/go-xorm/manual-zh-CN/tree/master/chapter-16) + +## LICENSE + +BSD License +[http://creativecommons.org/licenses/BSD/](http://creativecommons.org/licenses/BSD/) diff --git a/vendor/github.com/go-xorm/xorm/circle.yml b/vendor/github.com/go-xorm/xorm/circle.yml new file mode 100644 index 0000000000..8fde316921 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/circle.yml @@ -0,0 +1,41 @@ +dependencies: + override: + # './...' is a relative pattern which means all subdirectories + - go get -t -d -v ./... + - go get -t -d -v github.com/go-xorm/tests + - go get -u github.com/go-xorm/core + - go get -u github.com/go-xorm/builder + - go build -v + +database: + override: + - mysql -u root -e "CREATE DATABASE xorm_test DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci" + - mysql -u root -e "CREATE DATABASE xorm_test1 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci" + - mysql -u root -e "CREATE DATABASE xorm_test2 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci" + - mysql -u root -e "CREATE DATABASE xorm_test3 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci" + - createdb -p 5432 -e -U postgres xorm_test + - createdb -p 5432 -e -U postgres xorm_test1 + - createdb -p 5432 -e -U postgres xorm_test2 + - createdb -p 5432 -e -U postgres xorm_test3 + - psql xorm_test postgres -c "create schema xorm" + +test: + override: + # './...' is a relative pattern which means all subdirectories + - go get -u github.com/wadey/gocovmerge + - go test -v -race -db="sqlite3" -conn_str="./test.db" -coverprofile=coverage1-1.txt -covermode=atomic + - go test -v -race -db="sqlite3" -conn_str="./test.db" -cache=true -coverprofile=coverage1-2.txt -covermode=atomic + - go test -v -race -db="mysql" -conn_str="root:@/xorm_test" -coverprofile=coverage2-1.txt -covermode=atomic + - go test -v -race -db="mysql" -conn_str="root:@/xorm_test" -cache=true -coverprofile=coverage2-2.txt -covermode=atomic + - go test -v -race -db="mymysql" -conn_str="xorm_test/root/" -coverprofile=coverage3-1.txt -covermode=atomic + - go test -v -race -db="mymysql" -conn_str="xorm_test/root/" -cache=true -coverprofile=coverage3-2.txt -covermode=atomic + - go test -v -race -db="postgres" -conn_str="dbname=xorm_test sslmode=disable" -coverprofile=coverage4-1.txt -covermode=atomic + - go test -v -race -db="postgres" -conn_str="dbname=xorm_test sslmode=disable" -cache=true -coverprofile=coverage4-2.txt -covermode=atomic + - go test -v -race -db="postgres" -conn_str="dbname=xorm_test sslmode=disable" -schema=xorm -coverprofile=coverage5-1.txt -covermode=atomic + - go test -v -race -db="postgres" -conn_str="dbname=xorm_test sslmode=disable" -schema=xorm -cache=true -coverprofile=coverage5-2.txt -covermode=atomic + - gocovmerge coverage1-1.txt coverage1-2.txt coverage2-1.txt coverage2-2.txt coverage3-1.txt coverage3-2.txt coverage4-1.txt coverage4-2.txt coverage5-1.txt coverage5-2.txt > coverage.txt + - cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./sqlite3.sh + - cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./mysql.sh + - cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./postgres.sh + post: + - bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/gen_reserved.sh b/vendor/github.com/go-xorm/xorm/gen_reserved.sh new file mode 100644 index 0000000000..434a1bfcb0 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/gen_reserved.sh @@ -0,0 +1,6 @@ +#!/bin/bash +if [ -f $1 ];then + cat $1| awk '{printf("\""$1"\":true,\n")}' +else + echo "argument $1 if not a file!" +fi diff --git a/vendor/github.com/go-xorm/xorm/go.mod b/vendor/github.com/go-xorm/xorm/go.mod new file mode 100644 index 0000000000..1856169558 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/go.mod @@ -0,0 +1,24 @@ +module github.com/go-xorm/xorm + +require ( + github.com/cockroachdb/apd v1.1.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f + github.com/go-sql-driver/mysql v1.4.0 + github.com/go-xorm/builder v0.3.2 + github.com/go-xorm/core v0.6.0 + github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a // indirect + github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect + github.com/jackc/pgx v3.2.0+incompatible + github.com/kr/pretty v0.1.0 // indirect + github.com/lib/pq v1.0.0 + github.com/mattn/go-sqlite3 v1.9.0 + github.com/pkg/errors v0.8.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/satori/go.uuid v1.2.0 // indirect + github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 // indirect + github.com/stretchr/testify v1.2.2 + github.com/ziutek/mymysql v1.5.4 + gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect + gopkg.in/stretchr/testify.v1 v1.2.2 +) diff --git a/vendor/github.com/go-xorm/xorm/go.sum b/vendor/github.com/go-xorm/xorm/go.sum new file mode 100644 index 0000000000..dbf757d1d3 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/go.sum @@ -0,0 +1,43 @@ +github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/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-20181014144952-4e0d7dc8888f h1:WH0w/R4Yoey+04HhFxqZ6VX6I0d7RMyw5aXQ9UTvQPs= +github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc= +github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-xorm/builder v0.3.2 h1:pSsZQRRzJNapKEAEhigw3xLmiLPeAYv5GFlpYZ8+a5I= +github.com/go-xorm/builder v0.3.2/go.mod h1:v8mE3MFBgtL+RGFNfUnAMUqqfk/Y4W5KuwCFQIEpQLk= +github.com/go-xorm/core v0.6.0 h1:tp6hX+ku4OD9khFZS8VGBDRY3kfVCtelPfmkgCyHxL0= +github.com/go-xorm/core v0.6.0/go.mod h1:d8FJ9Br8OGyQl12MCclmYBuBqqxsyeedpXciV5Myih8= +github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y= +github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM= +github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc= +github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= +github.com/jackc/pgx v3.2.0+incompatible h1:0Vihzu20St42/UDsvZGdNE6jak7oi/UOeMzwMPHkgFY= +github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +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/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= +github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/stretchr/testify.v1 v1.2.2 h1:yhQC6Uy5CqibAIlk1wlusa/MJ3iAN49/BsR/dCCKz3M= +gopkg.in/stretchr/testify.v1 v1.2.2/go.mod h1:QI5V/q6UbPmuhtm10CaFZxED9NreB8PnFYN9JcR6TxU= diff --git a/vendor/github.com/go-xorm/xorm/pg_reserved.txt b/vendor/github.com/go-xorm/xorm/pg_reserved.txt new file mode 100644 index 0000000000..720ed377ba --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/pg_reserved.txt @@ -0,0 +1,746 @@ +A non-reserved non-reserved +ABORT non-reserved +ABS reserved reserved +ABSENT non-reserved non-reserved +ABSOLUTE non-reserved non-reserved non-reserved reserved +ACCESS non-reserved +ACCORDING non-reserved non-reserved +ACTION non-reserved non-reserved non-reserved reserved +ADA non-reserved non-reserved non-reserved +ADD non-reserved non-reserved non-reserved reserved +ADMIN non-reserved non-reserved non-reserved +AFTER non-reserved non-reserved non-reserved +AGGREGATE non-reserved +ALL reserved reserved reserved reserved +ALLOCATE reserved reserved reserved +ALSO non-reserved +ALTER non-reserved reserved reserved reserved +ALWAYS non-reserved non-reserved non-reserved +ANALYSE reserved +ANALYZE reserved +AND reserved reserved reserved reserved +ANY reserved reserved reserved reserved +ARE reserved reserved reserved +ARRAY reserved reserved reserved +ARRAY_AGG reserved reserved +ARRAY_MAX_CARDINALITY reserved +AS reserved reserved reserved reserved +ASC reserved non-reserved non-reserved reserved +ASENSITIVE reserved reserved +ASSERTION non-reserved non-reserved non-reserved reserved +ASSIGNMENT non-reserved non-reserved non-reserved +ASYMMETRIC reserved reserved reserved +AT non-reserved reserved reserved reserved +ATOMIC reserved reserved +ATTRIBUTE non-reserved non-reserved non-reserved +ATTRIBUTES non-reserved non-reserved +AUTHORIZATION reserved (can be function or type) reserved reserved reserved +AVG reserved reserved reserved +BACKWARD non-reserved +BASE64 non-reserved non-reserved +BEFORE non-reserved non-reserved non-reserved +BEGIN non-reserved reserved reserved reserved +BEGIN_FRAME reserved +BEGIN_PARTITION reserved +BERNOULLI non-reserved non-reserved +BETWEEN non-reserved (cannot be function or type) reserved reserved reserved +BIGINT non-reserved (cannot be function or type) reserved reserved +BINARY reserved (can be function or type) reserved reserved +BIT non-reserved (cannot be function or type) reserved +BIT_LENGTH reserved +BLOB reserved reserved +BLOCKED non-reserved non-reserved +BOM non-reserved non-reserved +BOOLEAN non-reserved (cannot be function or type) reserved reserved +BOTH reserved reserved reserved reserved +BREADTH non-reserved non-reserved +BY non-reserved reserved reserved reserved +C non-reserved non-reserved non-reserved +CACHE non-reserved +CALL reserved reserved +CALLED non-reserved reserved reserved +CARDINALITY reserved reserved +CASCADE non-reserved non-reserved non-reserved reserved +CASCADED non-reserved reserved reserved reserved +CASE reserved reserved reserved reserved +CAST reserved reserved reserved reserved +CATALOG non-reserved non-reserved non-reserved reserved +CATALOG_NAME non-reserved non-reserved non-reserved +CEIL reserved reserved +CEILING reserved reserved +CHAIN non-reserved non-reserved non-reserved +CHAR non-reserved (cannot be function or type) reserved reserved reserved +CHARACTER non-reserved (cannot be function or type) reserved reserved reserved +CHARACTERISTICS non-reserved non-reserved non-reserved +CHARACTERS non-reserved non-reserved +CHARACTER_LENGTH reserved reserved reserved +CHARACTER_SET_CATALOG non-reserved non-reserved non-reserved +CHARACTER_SET_NAME non-reserved non-reserved non-reserved +CHARACTER_SET_SCHEMA non-reserved non-reserved non-reserved +CHAR_LENGTH reserved reserved reserved +CHECK reserved reserved reserved reserved +CHECKPOINT non-reserved +CLASS non-reserved +CLASS_ORIGIN non-reserved non-reserved non-reserved +CLOB reserved reserved +CLOSE non-reserved reserved reserved reserved +CLUSTER non-reserved +COALESCE non-reserved (cannot be function or type) reserved reserved reserved +COBOL non-reserved non-reserved non-reserved +COLLATE reserved reserved reserved reserved +COLLATION reserved (can be function or type) non-reserved non-reserved reserved +COLLATION_CATALOG non-reserved non-reserved non-reserved +COLLATION_NAME non-reserved non-reserved non-reserved +COLLATION_SCHEMA non-reserved non-reserved non-reserved +COLLECT reserved reserved +COLUMN reserved reserved reserved reserved +COLUMNS non-reserved non-reserved +COLUMN_NAME non-reserved non-reserved non-reserved +COMMAND_FUNCTION non-reserved non-reserved non-reserved +COMMAND_FUNCTION_CODE non-reserved non-reserved +COMMENT non-reserved +COMMENTS non-reserved +COMMIT non-reserved reserved reserved reserved +COMMITTED non-reserved non-reserved non-reserved non-reserved +CONCURRENTLY reserved (can be function or type) +CONDITION reserved reserved +CONDITION_NUMBER non-reserved non-reserved non-reserved +CONFIGURATION non-reserved +CONNECT reserved reserved reserved +CONNECTION non-reserved non-reserved non-reserved reserved +CONNECTION_NAME non-reserved non-reserved non-reserved +CONSTRAINT reserved reserved reserved reserved +CONSTRAINTS non-reserved non-reserved non-reserved reserved +CONSTRAINT_CATALOG non-reserved non-reserved non-reserved +CONSTRAINT_NAME non-reserved non-reserved non-reserved +CONSTRAINT_SCHEMA non-reserved non-reserved non-reserved +CONSTRUCTOR non-reserved non-reserved +CONTAINS reserved non-reserved +CONTENT non-reserved non-reserved non-reserved +CONTINUE non-reserved non-reserved non-reserved reserved +CONTROL non-reserved non-reserved +CONVERSION non-reserved +CONVERT reserved reserved reserved +COPY non-reserved +CORR reserved reserved +CORRESPONDING reserved reserved reserved +COST non-reserved +COUNT reserved reserved reserved +COVAR_POP reserved reserved +COVAR_SAMP reserved reserved +CREATE reserved reserved reserved reserved +CROSS reserved (can be function or type) reserved reserved reserved +CSV non-reserved +CUBE reserved reserved +CUME_DIST reserved reserved +CURRENT non-reserved reserved reserved reserved +CURRENT_CATALOG reserved reserved reserved +CURRENT_DATE reserved reserved reserved reserved +CURRENT_DEFAULT_TRANSFORM_GROUP reserved reserved +CURRENT_PATH reserved reserved +CURRENT_ROLE reserved reserved reserved +CURRENT_ROW reserved +CURRENT_SCHEMA reserved (can be function or type) reserved reserved +CURRENT_TIME reserved reserved reserved reserved +CURRENT_TIMESTAMP reserved reserved reserved reserved +CURRENT_TRANSFORM_GROUP_FOR_TYPE reserved reserved +CURRENT_USER reserved reserved reserved reserved +CURSOR non-reserved reserved reserved reserved +CURSOR_NAME non-reserved non-reserved non-reserved +CYCLE non-reserved reserved reserved +DATA non-reserved non-reserved non-reserved non-reserved +DATABASE non-reserved +DATALINK reserved reserved +DATE reserved reserved reserved +DATETIME_INTERVAL_CODE non-reserved non-reserved non-reserved +DATETIME_INTERVAL_PRECISION non-reserved non-reserved non-reserved +DAY non-reserved reserved reserved reserved +DB non-reserved non-reserved +DEALLOCATE non-reserved reserved reserved reserved +DEC non-reserved (cannot be function or type) reserved reserved reserved +DECIMAL non-reserved (cannot be function or type) reserved reserved reserved +DECLARE non-reserved reserved reserved reserved +DEFAULT reserved reserved reserved reserved +DEFAULTS non-reserved non-reserved non-reserved +DEFERRABLE reserved non-reserved non-reserved reserved +DEFERRED non-reserved non-reserved non-reserved reserved +DEFINED non-reserved non-reserved +DEFINER non-reserved non-reserved non-reserved +DEGREE non-reserved non-reserved +DELETE non-reserved reserved reserved reserved +DELIMITER non-reserved +DELIMITERS non-reserved +DENSE_RANK reserved reserved +DEPTH non-reserved non-reserved +DEREF reserved reserved +DERIVED non-reserved non-reserved +DESC reserved non-reserved non-reserved reserved +DESCRIBE reserved reserved reserved +DESCRIPTOR non-reserved non-reserved reserved +DETERMINISTIC reserved reserved +DIAGNOSTICS non-reserved non-reserved reserved +DICTIONARY non-reserved +DISABLE non-reserved +DISCARD non-reserved +DISCONNECT reserved reserved reserved +DISPATCH non-reserved non-reserved +DISTINCT reserved reserved reserved reserved +DLNEWCOPY reserved reserved +DLPREVIOUSCOPY reserved reserved +DLURLCOMPLETE reserved reserved +DLURLCOMPLETEONLY reserved reserved +DLURLCOMPLETEWRITE reserved reserved +DLURLPATH reserved reserved +DLURLPATHONLY reserved reserved +DLURLPATHWRITE reserved reserved +DLURLSCHEME reserved reserved +DLURLSERVER reserved reserved +DLVALUE reserved reserved +DO reserved +DOCUMENT non-reserved non-reserved non-reserved +DOMAIN non-reserved non-reserved non-reserved reserved +DOUBLE non-reserved reserved reserved reserved +DROP non-reserved reserved reserved reserved +DYNAMIC reserved reserved +DYNAMIC_FUNCTION non-reserved non-reserved non-reserved +DYNAMIC_FUNCTION_CODE non-reserved non-reserved +EACH non-reserved reserved reserved +ELEMENT reserved reserved +ELSE reserved reserved reserved reserved +EMPTY non-reserved non-reserved +ENABLE non-reserved +ENCODING non-reserved non-reserved non-reserved +ENCRYPTED non-reserved +END reserved reserved reserved reserved +END-EXEC reserved reserved reserved +END_FRAME reserved +END_PARTITION reserved +ENFORCED non-reserved +ENUM non-reserved +EQUALS reserved non-reserved +ESCAPE non-reserved reserved reserved reserved +EVENT non-reserved +EVERY reserved reserved +EXCEPT reserved reserved reserved reserved +EXCEPTION reserved +EXCLUDE non-reserved non-reserved non-reserved +EXCLUDING non-reserved non-reserved non-reserved +EXCLUSIVE non-reserved +EXEC reserved reserved reserved +EXECUTE non-reserved reserved reserved reserved +EXISTS non-reserved (cannot be function or type) reserved reserved reserved +EXP reserved reserved +EXPLAIN non-reserved +EXPRESSION non-reserved +EXTENSION non-reserved +EXTERNAL non-reserved reserved reserved reserved +EXTRACT non-reserved (cannot be function or type) reserved reserved reserved +FALSE reserved reserved reserved reserved +FAMILY non-reserved +FETCH reserved reserved reserved reserved +FILE non-reserved non-reserved +FILTER reserved reserved +FINAL non-reserved non-reserved +FIRST non-reserved non-reserved non-reserved reserved +FIRST_VALUE reserved reserved +FLAG non-reserved non-reserved +FLOAT non-reserved (cannot be function or type) reserved reserved reserved +FLOOR reserved reserved +FOLLOWING non-reserved non-reserved non-reserved +FOR reserved reserved reserved reserved +FORCE non-reserved +FOREIGN reserved reserved reserved reserved +FORTRAN non-reserved non-reserved non-reserved +FORWARD non-reserved +FOUND non-reserved non-reserved reserved +FRAME_ROW reserved +FREE reserved reserved +FREEZE reserved (can be function or type) +FROM reserved reserved reserved reserved +FS non-reserved non-reserved +FULL reserved (can be function or type) reserved reserved reserved +FUNCTION non-reserved reserved reserved +FUNCTIONS non-reserved +FUSION reserved reserved +G non-reserved non-reserved +GENERAL non-reserved non-reserved +GENERATED non-reserved non-reserved +GET reserved reserved reserved +GLOBAL non-reserved reserved reserved reserved +GO non-reserved non-reserved reserved +GOTO non-reserved non-reserved reserved +GRANT reserved reserved reserved reserved +GRANTED non-reserved non-reserved non-reserved +GREATEST non-reserved (cannot be function or type) +GROUP reserved reserved reserved reserved +GROUPING reserved reserved +GROUPS reserved +HANDLER non-reserved +HAVING reserved reserved reserved reserved +HEADER non-reserved +HEX non-reserved non-reserved +HIERARCHY non-reserved non-reserved +HOLD non-reserved reserved reserved +HOUR non-reserved reserved reserved reserved +ID non-reserved non-reserved +IDENTITY non-reserved reserved reserved reserved +IF non-reserved +IGNORE non-reserved non-reserved +ILIKE reserved (can be function or type) +IMMEDIATE non-reserved non-reserved non-reserved reserved +IMMEDIATELY non-reserved +IMMUTABLE non-reserved +IMPLEMENTATION non-reserved non-reserved +IMPLICIT non-reserved +IMPORT reserved reserved +IN reserved reserved reserved reserved +INCLUDING non-reserved non-reserved non-reserved +INCREMENT non-reserved non-reserved non-reserved +INDENT non-reserved non-reserved +INDEX non-reserved +INDEXES non-reserved +INDICATOR reserved reserved reserved +INHERIT non-reserved +INHERITS non-reserved +INITIALLY reserved non-reserved non-reserved reserved +INLINE non-reserved +INNER reserved (can be function or type) reserved reserved reserved +INOUT non-reserved (cannot be function or type) reserved reserved +INPUT non-reserved non-reserved non-reserved reserved +INSENSITIVE non-reserved reserved reserved reserved +INSERT non-reserved reserved reserved reserved +INSTANCE non-reserved non-reserved +INSTANTIABLE non-reserved non-reserved +INSTEAD non-reserved non-reserved non-reserved +INT non-reserved (cannot be function or type) reserved reserved reserved +INTEGER non-reserved (cannot be function or type) reserved reserved reserved +INTEGRITY non-reserved non-reserved +INTERSECT reserved reserved reserved reserved +INTERSECTION reserved reserved +INTERVAL non-reserved (cannot be function or type) reserved reserved reserved +INTO reserved reserved reserved reserved +INVOKER non-reserved non-reserved non-reserved +IS reserved (can be function or type) reserved reserved reserved +ISNULL reserved (can be function or type) +ISOLATION non-reserved non-reserved non-reserved reserved +JOIN reserved (can be function or type) reserved reserved reserved +K non-reserved non-reserved +KEY non-reserved non-reserved non-reserved reserved +KEY_MEMBER non-reserved non-reserved +KEY_TYPE non-reserved non-reserved +LABEL non-reserved +LAG reserved reserved +LANGUAGE non-reserved reserved reserved reserved +LARGE non-reserved reserved reserved +LAST non-reserved non-reserved non-reserved reserved +LAST_VALUE reserved reserved +LATERAL reserved reserved reserved +LC_COLLATE non-reserved +LC_CTYPE non-reserved +LEAD reserved reserved +LEADING reserved reserved reserved reserved +LEAKPROOF non-reserved +LEAST non-reserved (cannot be function or type) +LEFT reserved (can be function or type) reserved reserved reserved +LENGTH non-reserved non-reserved non-reserved +LEVEL non-reserved non-reserved non-reserved reserved +LIBRARY non-reserved non-reserved +LIKE reserved (can be function or type) reserved reserved reserved +LIKE_REGEX reserved reserved +LIMIT reserved non-reserved non-reserved +LINK non-reserved non-reserved +LISTEN non-reserved +LN reserved reserved +LOAD non-reserved +LOCAL non-reserved reserved reserved reserved +LOCALTIME reserved reserved reserved +LOCALTIMESTAMP reserved reserved reserved +LOCATION non-reserved non-reserved non-reserved +LOCATOR non-reserved non-reserved +LOCK non-reserved +LOWER reserved reserved reserved +M non-reserved non-reserved +MAP non-reserved non-reserved +MAPPING non-reserved non-reserved non-reserved +MATCH non-reserved reserved reserved reserved +MATCHED non-reserved non-reserved +MATERIALIZED non-reserved +MAX reserved reserved reserved +MAXVALUE non-reserved non-reserved non-reserved +MAX_CARDINALITY reserved +MEMBER reserved reserved +MERGE reserved reserved +MESSAGE_LENGTH non-reserved non-reserved non-reserved +MESSAGE_OCTET_LENGTH non-reserved non-reserved non-reserved +MESSAGE_TEXT non-reserved non-reserved non-reserved +METHOD reserved reserved +MIN reserved reserved reserved +MINUTE non-reserved reserved reserved reserved +MINVALUE non-reserved non-reserved non-reserved +MOD reserved reserved +MODE non-reserved +MODIFIES reserved reserved +MODULE reserved reserved reserved +MONTH non-reserved reserved reserved reserved +MORE non-reserved non-reserved non-reserved +MOVE non-reserved +MULTISET reserved reserved +MUMPS non-reserved non-reserved non-reserved +NAME non-reserved non-reserved non-reserved non-reserved +NAMES non-reserved non-reserved non-reserved reserved +NAMESPACE non-reserved non-reserved +NATIONAL non-reserved (cannot be function or type) reserved reserved reserved +NATURAL reserved (can be function or type) reserved reserved reserved +NCHAR non-reserved (cannot be function or type) reserved reserved reserved +NCLOB reserved reserved +NESTING non-reserved non-reserved +NEW reserved reserved +NEXT non-reserved non-reserved non-reserved reserved +NFC non-reserved non-reserved +NFD non-reserved non-reserved +NFKC non-reserved non-reserved +NFKD non-reserved non-reserved +NIL non-reserved non-reserved +NO non-reserved reserved reserved reserved +NONE non-reserved (cannot be function or type) reserved reserved +NORMALIZE reserved reserved +NORMALIZED non-reserved non-reserved +NOT reserved reserved reserved reserved +NOTHING non-reserved +NOTIFY non-reserved +NOTNULL reserved (can be function or type) +NOWAIT non-reserved +NTH_VALUE reserved reserved +NTILE reserved reserved +NULL reserved reserved reserved reserved +NULLABLE non-reserved non-reserved non-reserved +NULLIF non-reserved (cannot be function or type) reserved reserved reserved +NULLS non-reserved non-reserved non-reserved +NUMBER non-reserved non-reserved non-reserved +NUMERIC non-reserved (cannot be function or type) reserved reserved reserved +OBJECT non-reserved non-reserved non-reserved +OCCURRENCES_REGEX reserved reserved +OCTETS non-reserved non-reserved +OCTET_LENGTH reserved reserved reserved +OF non-reserved reserved reserved reserved +OFF non-reserved non-reserved non-reserved +OFFSET reserved reserved reserved +OIDS non-reserved +OLD reserved reserved +ON reserved reserved reserved reserved +ONLY reserved reserved reserved reserved +OPEN reserved reserved reserved +OPERATOR non-reserved +OPTION non-reserved non-reserved non-reserved reserved +OPTIONS non-reserved non-reserved non-reserved +OR reserved reserved reserved reserved +ORDER reserved reserved reserved reserved +ORDERING non-reserved non-reserved +ORDINALITY non-reserved non-reserved +OTHERS non-reserved non-reserved +OUT non-reserved (cannot be function or type) reserved reserved +OUTER reserved (can be function or type) reserved reserved reserved +OUTPUT non-reserved non-reserved reserved +OVER reserved (can be function or type) reserved reserved +OVERLAPS reserved (can be function or type) reserved reserved reserved +OVERLAY non-reserved (cannot be function or type) reserved reserved +OVERRIDING non-reserved non-reserved +OWNED non-reserved +OWNER non-reserved +P non-reserved non-reserved +PAD non-reserved non-reserved reserved +PARAMETER reserved reserved +PARAMETER_MODE non-reserved non-reserved +PARAMETER_NAME non-reserved non-reserved +PARAMETER_ORDINAL_POSITION non-reserved non-reserved +PARAMETER_SPECIFIC_CATALOG non-reserved non-reserved +PARAMETER_SPECIFIC_NAME non-reserved non-reserved +PARAMETER_SPECIFIC_SCHEMA non-reserved non-reserved +PARSER non-reserved +PARTIAL non-reserved non-reserved non-reserved reserved +PARTITION non-reserved reserved reserved +PASCAL non-reserved non-reserved non-reserved +PASSING non-reserved non-reserved non-reserved +PASSTHROUGH non-reserved non-reserved +PASSWORD non-reserved +PATH non-reserved non-reserved +PERCENT reserved +PERCENTILE_CONT reserved reserved +PERCENTILE_DISC reserved reserved +PERCENT_RANK reserved reserved +PERIOD reserved +PERMISSION non-reserved non-reserved +PLACING reserved non-reserved non-reserved +PLANS non-reserved +PLI non-reserved non-reserved non-reserved +PORTION reserved +POSITION non-reserved (cannot be function or type) reserved reserved reserved +POSITION_REGEX reserved reserved +POWER reserved reserved +PRECEDES reserved +PRECEDING non-reserved non-reserved non-reserved +PRECISION non-reserved (cannot be function or type) reserved reserved reserved +PREPARE non-reserved reserved reserved reserved +PREPARED non-reserved +PRESERVE non-reserved non-reserved non-reserved reserved +PRIMARY reserved reserved reserved reserved +PRIOR non-reserved non-reserved non-reserved reserved +PRIVILEGES non-reserved non-reserved non-reserved reserved +PROCEDURAL non-reserved +PROCEDURE non-reserved reserved reserved reserved +PROGRAM non-reserved +PUBLIC non-reserved non-reserved reserved +QUOTE non-reserved +RANGE non-reserved reserved reserved +RANK reserved reserved +READ non-reserved non-reserved non-reserved reserved +READS reserved reserved +REAL non-reserved (cannot be function or type) reserved reserved reserved +REASSIGN non-reserved +RECHECK non-reserved +RECOVERY non-reserved non-reserved +RECURSIVE non-reserved reserved reserved +REF non-reserved reserved reserved +REFERENCES reserved reserved reserved reserved +REFERENCING reserved reserved +REFRESH non-reserved +REGR_AVGX reserved reserved +REGR_AVGY reserved reserved +REGR_COUNT reserved reserved +REGR_INTERCEPT reserved reserved +REGR_R2 reserved reserved +REGR_SLOPE reserved reserved +REGR_SXX reserved reserved +REGR_SXY reserved reserved +REGR_SYY reserved reserved +REINDEX non-reserved +RELATIVE non-reserved non-reserved non-reserved reserved +RELEASE non-reserved reserved reserved +RENAME non-reserved +REPEATABLE non-reserved non-reserved non-reserved non-reserved +REPLACE non-reserved +REPLICA non-reserved +REQUIRING non-reserved non-reserved +RESET non-reserved +RESPECT non-reserved non-reserved +RESTART non-reserved non-reserved non-reserved +RESTORE non-reserved non-reserved +RESTRICT non-reserved non-reserved non-reserved reserved +RESULT reserved reserved +RETURN reserved reserved +RETURNED_CARDINALITY non-reserved non-reserved +RETURNED_LENGTH non-reserved non-reserved non-reserved +RETURNED_OCTET_LENGTH non-reserved non-reserved non-reserved +RETURNED_SQLSTATE non-reserved non-reserved non-reserved +RETURNING reserved non-reserved non-reserved +RETURNS non-reserved reserved reserved +REVOKE non-reserved reserved reserved reserved +RIGHT reserved (can be function or type) reserved reserved reserved +ROLE non-reserved non-reserved non-reserved +ROLLBACK non-reserved reserved reserved reserved +ROLLUP reserved reserved +ROUTINE non-reserved non-reserved +ROUTINE_CATALOG non-reserved non-reserved +ROUTINE_NAME non-reserved non-reserved +ROUTINE_SCHEMA non-reserved non-reserved +ROW non-reserved (cannot be function or type) reserved reserved +ROWS non-reserved reserved reserved reserved +ROW_COUNT non-reserved non-reserved non-reserved +ROW_NUMBER reserved reserved +RULE non-reserved +SAVEPOINT non-reserved reserved reserved +SCALE non-reserved non-reserved non-reserved +SCHEMA non-reserved non-reserved non-reserved reserved +SCHEMA_NAME non-reserved non-reserved non-reserved +SCOPE reserved reserved +SCOPE_CATALOG non-reserved non-reserved +SCOPE_NAME non-reserved non-reserved +SCOPE_SCHEMA non-reserved non-reserved +SCROLL non-reserved reserved reserved reserved +SEARCH non-reserved reserved reserved +SECOND non-reserved reserved reserved reserved +SECTION non-reserved non-reserved reserved +SECURITY non-reserved non-reserved non-reserved +SELECT reserved reserved reserved reserved +SELECTIVE non-reserved non-reserved +SELF non-reserved non-reserved +SENSITIVE reserved reserved +SEQUENCE non-reserved non-reserved non-reserved +SEQUENCES non-reserved +SERIALIZABLE non-reserved non-reserved non-reserved non-reserved +SERVER non-reserved non-reserved non-reserved +SERVER_NAME non-reserved non-reserved non-reserved +SESSION non-reserved non-reserved non-reserved reserved +SESSION_USER reserved reserved reserved reserved +SET non-reserved reserved reserved reserved +SETOF non-reserved (cannot be function or type) +SETS non-reserved non-reserved +SHARE non-reserved +SHOW non-reserved +SIMILAR reserved (can be function or type) reserved reserved +SIMPLE non-reserved non-reserved non-reserved +SIZE non-reserved non-reserved reserved +SMALLINT non-reserved (cannot be function or type) reserved reserved reserved +SNAPSHOT non-reserved +SOME reserved reserved reserved reserved +SOURCE non-reserved non-reserved +SPACE non-reserved non-reserved reserved +SPECIFIC reserved reserved +SPECIFICTYPE reserved reserved +SPECIFIC_NAME non-reserved non-reserved +SQL reserved reserved reserved +SQLCODE reserved +SQLERROR reserved +SQLEXCEPTION reserved reserved +SQLSTATE reserved reserved reserved +SQLWARNING reserved reserved +SQRT reserved reserved +STABLE non-reserved +STANDALONE non-reserved non-reserved non-reserved +START non-reserved reserved reserved +STATE non-reserved non-reserved +STATEMENT non-reserved non-reserved non-reserved +STATIC reserved reserved +STATISTICS non-reserved +STDDEV_POP reserved reserved +STDDEV_SAMP reserved reserved +STDIN non-reserved +STDOUT non-reserved +STORAGE non-reserved +STRICT non-reserved +STRIP non-reserved non-reserved non-reserved +STRUCTURE non-reserved non-reserved +STYLE non-reserved non-reserved +SUBCLASS_ORIGIN non-reserved non-reserved non-reserved +SUBMULTISET reserved reserved +SUBSTRING non-reserved (cannot be function or type) reserved reserved reserved +SUBSTRING_REGEX reserved reserved +SUCCEEDS reserved +SUM reserved reserved reserved +SYMMETRIC reserved reserved reserved +SYSID non-reserved +SYSTEM non-reserved reserved reserved +SYSTEM_TIME reserved +SYSTEM_USER reserved reserved reserved +T non-reserved non-reserved +TABLE reserved reserved reserved reserved +TABLES non-reserved +TABLESAMPLE reserved reserved +TABLESPACE non-reserved +TABLE_NAME non-reserved non-reserved non-reserved +TEMP non-reserved +TEMPLATE non-reserved +TEMPORARY non-reserved non-reserved non-reserved reserved +TEXT non-reserved +THEN reserved reserved reserved reserved +TIES non-reserved non-reserved +TIME non-reserved (cannot be function or type) reserved reserved reserved +TIMESTAMP non-reserved (cannot be function or type) reserved reserved reserved +TIMEZONE_HOUR reserved reserved reserved +TIMEZONE_MINUTE reserved reserved reserved +TO reserved reserved reserved reserved +TOKEN non-reserved non-reserved +TOP_LEVEL_COUNT non-reserved non-reserved +TRAILING reserved reserved reserved reserved +TRANSACTION non-reserved non-reserved non-reserved reserved +TRANSACTIONS_COMMITTED non-reserved non-reserved +TRANSACTIONS_ROLLED_BACK non-reserved non-reserved +TRANSACTION_ACTIVE non-reserved non-reserved +TRANSFORM non-reserved non-reserved +TRANSFORMS non-reserved non-reserved +TRANSLATE reserved reserved reserved +TRANSLATE_REGEX reserved reserved +TRANSLATION reserved reserved reserved +TREAT non-reserved (cannot be function or type) reserved reserved +TRIGGER non-reserved reserved reserved +TRIGGER_CATALOG non-reserved non-reserved +TRIGGER_NAME non-reserved non-reserved +TRIGGER_SCHEMA non-reserved non-reserved +TRIM non-reserved (cannot be function or type) reserved reserved reserved +TRIM_ARRAY reserved reserved +TRUE reserved reserved reserved reserved +TRUNCATE non-reserved reserved reserved +TRUSTED non-reserved +TYPE non-reserved non-reserved non-reserved non-reserved +TYPES non-reserved +UESCAPE reserved reserved +UNBOUNDED non-reserved non-reserved non-reserved +UNCOMMITTED non-reserved non-reserved non-reserved non-reserved +UNDER non-reserved non-reserved +UNENCRYPTED non-reserved +UNION reserved reserved reserved reserved +UNIQUE reserved reserved reserved reserved +UNKNOWN non-reserved reserved reserved reserved +UNLINK non-reserved non-reserved +UNLISTEN non-reserved +UNLOGGED non-reserved +UNNAMED non-reserved non-reserved non-reserved +UNNEST reserved reserved +UNTIL non-reserved +UNTYPED non-reserved non-reserved +UPDATE non-reserved reserved reserved reserved +UPPER reserved reserved reserved +URI non-reserved non-reserved +USAGE non-reserved non-reserved reserved +USER reserved reserved reserved reserved +USER_DEFINED_TYPE_CATALOG non-reserved non-reserved +USER_DEFINED_TYPE_CODE non-reserved non-reserved +USER_DEFINED_TYPE_NAME non-reserved non-reserved +USER_DEFINED_TYPE_SCHEMA non-reserved non-reserved +USING reserved reserved reserved reserved +VACUUM non-reserved +VALID non-reserved non-reserved non-reserved +VALIDATE non-reserved +VALIDATOR non-reserved +VALUE non-reserved reserved reserved reserved +VALUES non-reserved (cannot be function or type) reserved reserved reserved +VALUE_OF reserved +VARBINARY reserved reserved +VARCHAR non-reserved (cannot be function or type) reserved reserved reserved +VARIADIC reserved +VARYING non-reserved reserved reserved reserved +VAR_POP reserved reserved +VAR_SAMP reserved reserved +VERBOSE reserved (can be function or type) +VERSION non-reserved non-reserved non-reserved +VERSIONING reserved +VIEW non-reserved non-reserved non-reserved reserved +VOLATILE non-reserved +WHEN reserved reserved reserved reserved +WHENEVER reserved reserved reserved +WHERE reserved reserved reserved reserved +WHITESPACE non-reserved non-reserved non-reserved +WIDTH_BUCKET reserved reserved +WINDOW reserved reserved reserved +WITH reserved reserved reserved reserved +WITHIN reserved reserved +WITHOUT non-reserved reserved reserved +WORK non-reserved non-reserved non-reserved reserved +WRAPPER non-reserved non-reserved non-reserved +WRITE non-reserved non-reserved non-reserved reserved +XML non-reserved reserved reserved +XMLAGG reserved reserved +XMLATTRIBUTES non-reserved (cannot be function or type) reserved reserved +XMLBINARY reserved reserved +XMLCAST reserved reserved +XMLCOMMENT reserved reserved +XMLCONCAT non-reserved (cannot be function or type) reserved reserved +XMLDECLARATION non-reserved non-reserved +XMLDOCUMENT reserved reserved +XMLELEMENT non-reserved (cannot be function or type) reserved reserved +XMLEXISTS non-reserved (cannot be function or type) reserved reserved +XMLFOREST non-reserved (cannot be function or type) reserved reserved +XMLITERATE reserved reserved +XMLNAMESPACES reserved reserved +XMLPARSE non-reserved (cannot be function or type) reserved reserved +XMLPI non-reserved (cannot be function or type) reserved reserved +XMLQUERY reserved reserved +XMLROOT non-reserved (cannot be function or type) +XMLSCHEMA non-reserved non-reserved +XMLSERIALIZE non-reserved (cannot be function or type) reserved reserved +XMLTABLE reserved reserved +XMLTEXT reserved reserved +XMLVALIDATE reserved reserved +YEAR non-reserved reserved reserved reserved +YES non-reserved non-reserved non-reserved +ZONE non-reserved non-reserved non-reserved reserved \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_mssql.sh b/vendor/github.com/go-xorm/xorm/test_mssql.sh new file mode 100644 index 0000000000..6f9cf7295f --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_mssql.sh @@ -0,0 +1 @@ +go test -db=mssql -conn_str="server=192.168.1.58;user id=sa;password=123456;database=xorm_test" \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_mssql_cache.sh b/vendor/github.com/go-xorm/xorm/test_mssql_cache.sh new file mode 100644 index 0000000000..76efd6ca0a --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_mssql_cache.sh @@ -0,0 +1 @@ +go test -db=mssql -conn_str="server=192.168.1.58;user id=sa;password=123456;database=xorm_test" -cache=true \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_mymysql.sh b/vendor/github.com/go-xorm/xorm/test_mymysql.sh new file mode 100644 index 0000000000..f7780d14fa --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_mymysql.sh @@ -0,0 +1 @@ +go test -db=mymysql -conn_str="xorm_test/root/" \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_mymysql_cache.sh b/vendor/github.com/go-xorm/xorm/test_mymysql_cache.sh new file mode 100644 index 0000000000..0100286d65 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_mymysql_cache.sh @@ -0,0 +1 @@ +go test -db=mymysql -conn_str="xorm_test/root/" -cache=true \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_mysql.sh b/vendor/github.com/go-xorm/xorm/test_mysql.sh new file mode 100644 index 0000000000..650e4ee170 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_mysql.sh @@ -0,0 +1 @@ +go test -db=mysql -conn_str="root:@/xorm_test" \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_mysql_cache.sh b/vendor/github.com/go-xorm/xorm/test_mysql_cache.sh new file mode 100644 index 0000000000..c542e73594 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_mysql_cache.sh @@ -0,0 +1 @@ +go test -db=mysql -conn_str="root:@/xorm_test" -cache=true \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_postgres.sh b/vendor/github.com/go-xorm/xorm/test_postgres.sh new file mode 100644 index 0000000000..dc1152e0a6 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_postgres.sh @@ -0,0 +1 @@ +go test -db=postgres -conn_str="dbname=xorm_test sslmode=disable" \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_postgres_cache.sh b/vendor/github.com/go-xorm/xorm/test_postgres_cache.sh new file mode 100644 index 0000000000..462fc948cb --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_postgres_cache.sh @@ -0,0 +1 @@ +go test -db=postgres -conn_str="dbname=xorm_test sslmode=disable" -cache=true \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_sqlite.sh b/vendor/github.com/go-xorm/xorm/test_sqlite.sh new file mode 100644 index 0000000000..6352b5cb5f --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_sqlite.sh @@ -0,0 +1 @@ +go test -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_sqlite_cache.sh b/vendor/github.com/go-xorm/xorm/test_sqlite_cache.sh new file mode 100644 index 0000000000..75a054c3f1 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_sqlite_cache.sh @@ -0,0 +1 @@ +go test -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" -cache=true \ No newline at end of file diff --git a/vendor/github.com/gogits/chardet/README.md b/vendor/github.com/gogits/chardet/README.md new file mode 100644 index 0000000000..bbde23fb73 --- /dev/null +++ b/vendor/github.com/gogits/chardet/README.md @@ -0,0 +1,12 @@ +# chardet + +chardet is library to automatically detect +[charset](http://en.wikipedia.org/wiki/Character_encoding) of texts for [Go +programming language](http://golang.org/). It's based on the algorithm and data +in [ICU](http://icu-project.org/)'s implementation. + +The project was created by [saintfish](http://github.com/saintfish/chardet). In January 2015 it was forked by the gogits project in order to incorporate bugfixes and new features. + +## Documentation and Usage + +See [pkgdoc](http://godoc.org/github.com/gogits/chardet) diff --git a/vendor/github.com/gogits/chardet/icu-license.html b/vendor/github.com/gogits/chardet/icu-license.html new file mode 100644 index 0000000000..d078d0575b --- /dev/null +++ b/vendor/github.com/gogits/chardet/icu-license.html @@ -0,0 +1,51 @@ + + + + +ICU License - ICU 1.8.1 and later + + + +

ICU License - ICU 1.8.1 and later

+ +

COPYRIGHT AND PERMISSION NOTICE

+ +

+Copyright (c) 1995-2012 International Business Machines Corporation and others +

+

+All rights reserved. +

+

+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, and/or sell +copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies +of the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. +

+

+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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL +THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, +OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE +USE OR PERFORMANCE OF THIS SOFTWARE. +

+

+Except as contained in this notice, the name of a copyright holder shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization of the copyright holder. +

+ +
+

+All trademarks and registered trademarks mentioned herein are the property of their respective owners. +

+ + diff --git a/vendor/github.com/gogits/cron/.gitignore b/vendor/github.com/gogits/cron/.gitignore new file mode 100644 index 0000000000..00268614f0 --- /dev/null +++ b/vendor/github.com/gogits/cron/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/gogits/cron/.travis.yml b/vendor/github.com/gogits/cron/.travis.yml new file mode 100644 index 0000000000..4f2ee4d973 --- /dev/null +++ b/vendor/github.com/gogits/cron/.travis.yml @@ -0,0 +1 @@ +language: go diff --git a/vendor/github.com/gogits/cron/README.md b/vendor/github.com/gogits/cron/README.md new file mode 100644 index 0000000000..157ed082d4 --- /dev/null +++ b/vendor/github.com/gogits/cron/README.md @@ -0,0 +1,2 @@ +[![GoDoc](http://godoc.org/github.com/robfig/cron?status.png)](http://godoc.org/github.com/robfig/cron) +[![Build Status](https://travis-ci.org/robfig/cron.svg?branch=master)](https://travis-ci.org/robfig/cron) diff --git a/vendor/github.com/golang/snappy/.gitignore b/vendor/github.com/golang/snappy/.gitignore new file mode 100644 index 0000000000..042091d9b3 --- /dev/null +++ b/vendor/github.com/golang/snappy/.gitignore @@ -0,0 +1,16 @@ +cmd/snappytool/snappytool +testdata/bench + +# These explicitly listed benchmark data files are for an obsolete version of +# snappy_test.go. +testdata/alice29.txt +testdata/asyoulik.txt +testdata/fireworks.jpeg +testdata/geo.protodata +testdata/html +testdata/html_x_4 +testdata/kppkn.gtb +testdata/lcet10.txt +testdata/paper-100k.pdf +testdata/plrabn12.txt +testdata/urls.10K diff --git a/vendor/github.com/golang/snappy/README b/vendor/github.com/golang/snappy/README new file mode 100644 index 0000000000..cea12879a0 --- /dev/null +++ b/vendor/github.com/golang/snappy/README @@ -0,0 +1,107 @@ +The Snappy compression format in the Go programming language. + +To download and install from source: +$ go get github.com/golang/snappy + +Unless otherwise noted, the Snappy-Go source files are distributed +under the BSD-style license found in the LICENSE file. + + + +Benchmarks. + +The golang/snappy benchmarks include compressing (Z) and decompressing (U) ten +or so files, the same set used by the C++ Snappy code (github.com/google/snappy +and note the "google", not "golang"). On an "Intel(R) Core(TM) i7-3770 CPU @ +3.40GHz", Go's GOARCH=amd64 numbers as of 2016-05-29: + +"go test -test.bench=." + +_UFlat0-8 2.19GB/s ± 0% html +_UFlat1-8 1.41GB/s ± 0% urls +_UFlat2-8 23.5GB/s ± 2% jpg +_UFlat3-8 1.91GB/s ± 0% jpg_200 +_UFlat4-8 14.0GB/s ± 1% pdf +_UFlat5-8 1.97GB/s ± 0% html4 +_UFlat6-8 814MB/s ± 0% txt1 +_UFlat7-8 785MB/s ± 0% txt2 +_UFlat8-8 857MB/s ± 0% txt3 +_UFlat9-8 719MB/s ± 1% txt4 +_UFlat10-8 2.84GB/s ± 0% pb +_UFlat11-8 1.05GB/s ± 0% gaviota + +_ZFlat0-8 1.04GB/s ± 0% html +_ZFlat1-8 534MB/s ± 0% urls +_ZFlat2-8 15.7GB/s ± 1% jpg +_ZFlat3-8 740MB/s ± 3% jpg_200 +_ZFlat4-8 9.20GB/s ± 1% pdf +_ZFlat5-8 991MB/s ± 0% html4 +_ZFlat6-8 379MB/s ± 0% txt1 +_ZFlat7-8 352MB/s ± 0% txt2 +_ZFlat8-8 396MB/s ± 1% txt3 +_ZFlat9-8 327MB/s ± 1% txt4 +_ZFlat10-8 1.33GB/s ± 1% pb +_ZFlat11-8 605MB/s ± 1% gaviota + + + +"go test -test.bench=. -tags=noasm" + +_UFlat0-8 621MB/s ± 2% html +_UFlat1-8 494MB/s ± 1% urls +_UFlat2-8 23.2GB/s ± 1% jpg +_UFlat3-8 1.12GB/s ± 1% jpg_200 +_UFlat4-8 4.35GB/s ± 1% pdf +_UFlat5-8 609MB/s ± 0% html4 +_UFlat6-8 296MB/s ± 0% txt1 +_UFlat7-8 288MB/s ± 0% txt2 +_UFlat8-8 309MB/s ± 1% txt3 +_UFlat9-8 280MB/s ± 1% txt4 +_UFlat10-8 753MB/s ± 0% pb +_UFlat11-8 400MB/s ± 0% gaviota + +_ZFlat0-8 409MB/s ± 1% html +_ZFlat1-8 250MB/s ± 1% urls +_ZFlat2-8 12.3GB/s ± 1% jpg +_ZFlat3-8 132MB/s ± 0% jpg_200 +_ZFlat4-8 2.92GB/s ± 0% pdf +_ZFlat5-8 405MB/s ± 1% html4 +_ZFlat6-8 179MB/s ± 1% txt1 +_ZFlat7-8 170MB/s ± 1% txt2 +_ZFlat8-8 189MB/s ± 1% txt3 +_ZFlat9-8 164MB/s ± 1% txt4 +_ZFlat10-8 479MB/s ± 1% pb +_ZFlat11-8 270MB/s ± 1% gaviota + + + +For comparison (Go's encoded output is byte-for-byte identical to C++'s), here +are the numbers from C++ Snappy's + +make CXXFLAGS="-O2 -DNDEBUG -g" clean snappy_unittest.log && cat snappy_unittest.log + +BM_UFlat/0 2.4GB/s html +BM_UFlat/1 1.4GB/s urls +BM_UFlat/2 21.8GB/s jpg +BM_UFlat/3 1.5GB/s jpg_200 +BM_UFlat/4 13.3GB/s pdf +BM_UFlat/5 2.1GB/s html4 +BM_UFlat/6 1.0GB/s txt1 +BM_UFlat/7 959.4MB/s txt2 +BM_UFlat/8 1.0GB/s txt3 +BM_UFlat/9 864.5MB/s txt4 +BM_UFlat/10 2.9GB/s pb +BM_UFlat/11 1.2GB/s gaviota + +BM_ZFlat/0 944.3MB/s html (22.31 %) +BM_ZFlat/1 501.6MB/s urls (47.78 %) +BM_ZFlat/2 14.3GB/s jpg (99.95 %) +BM_ZFlat/3 538.3MB/s jpg_200 (73.00 %) +BM_ZFlat/4 8.3GB/s pdf (83.30 %) +BM_ZFlat/5 903.5MB/s html4 (22.52 %) +BM_ZFlat/6 336.0MB/s txt1 (57.88 %) +BM_ZFlat/7 312.3MB/s txt2 (61.91 %) +BM_ZFlat/8 353.1MB/s txt3 (54.99 %) +BM_ZFlat/9 289.9MB/s txt4 (66.26 %) +BM_ZFlat/10 1.2GB/s pb (19.68 %) +BM_ZFlat/11 527.4MB/s gaviota (37.72 %) diff --git a/vendor/github.com/golang/snappy/decode.go b/vendor/github.com/golang/snappy/decode.go index 7be590cee7..72efb0353d 100644 --- a/vendor/github.com/golang/snappy/decode.go +++ b/vendor/github.com/golang/snappy/decode.go @@ -18,7 +18,6 @@ var ( // ErrUnsupported reports that the input isn't supported. ErrUnsupported = errors.New("snappy: unsupported input") - errUnsupportedCopy4Tag = errors.New("snappy: unsupported COPY_4 tag") errUnsupportedLiteralLength = errors.New("snappy: unsupported literal length") ) @@ -46,7 +45,6 @@ func decodedLen(src []byte) (blockLen, headerLen int, err error) { const ( decodeErrCodeCorrupt = 1 decodeErrCodeUnsupportedLiteralLength = 2 - decodeErrCodeUnsupportedCopy4Tag = 3 ) // Decode returns the decoded form of src. The returned slice may be a sub- @@ -69,8 +67,6 @@ func Decode(dst, src []byte) ([]byte, error) { return dst, nil case decodeErrCodeUnsupportedLiteralLength: return nil, errUnsupportedLiteralLength - case decodeErrCodeUnsupportedCopy4Tag: - return nil, errUnsupportedCopy4Tag } return nil, ErrCorrupt } @@ -108,9 +104,9 @@ func (r *Reader) Reset(reader io.Reader) { r.readHeader = false } -func (r *Reader) readFull(p []byte) (ok bool) { +func (r *Reader) readFull(p []byte, allowEOF bool) (ok bool) { if _, r.err = io.ReadFull(r.r, p); r.err != nil { - if r.err == io.ErrUnexpectedEOF { + if r.err == io.ErrUnexpectedEOF || (r.err == io.EOF && !allowEOF) { r.err = ErrCorrupt } return false @@ -129,7 +125,7 @@ func (r *Reader) Read(p []byte) (int, error) { r.i += n return n, nil } - if !r.readFull(r.buf[:4]) { + if !r.readFull(r.buf[:4], true) { return 0, r.err } chunkType := r.buf[0] @@ -156,7 +152,7 @@ func (r *Reader) Read(p []byte) (int, error) { return 0, r.err } buf := r.buf[:chunkLen] - if !r.readFull(buf) { + if !r.readFull(buf, false) { return 0, r.err } checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 @@ -189,13 +185,17 @@ func (r *Reader) Read(p []byte) (int, error) { return 0, r.err } buf := r.buf[:checksumSize] - if !r.readFull(buf) { + if !r.readFull(buf, false) { return 0, r.err } checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 // Read directly into r.decoded instead of via r.buf. n := chunkLen - checksumSize - if !r.readFull(r.decoded[:n]) { + if n > len(r.decoded) { + r.err = ErrCorrupt + return 0, r.err + } + if !r.readFull(r.decoded[:n], false) { return 0, r.err } if crc(r.decoded[:n]) != checksum { @@ -211,7 +211,7 @@ func (r *Reader) Read(p []byte) (int, error) { r.err = ErrCorrupt return 0, r.err } - if !r.readFull(r.buf[:len(magicBody)]) { + if !r.readFull(r.buf[:len(magicBody)], false) { return 0, r.err } for i := 0; i < len(magicBody); i++ { @@ -230,7 +230,7 @@ func (r *Reader) Read(p []byte) (int, error) { } // Section 4.4 Padding (chunk type 0xfe). // Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd). - if !r.readFull(r.buf[:chunkLen]) { + if !r.readFull(r.buf[:chunkLen], false) { return 0, r.err } } diff --git a/vendor/github.com/golang/snappy/decode_amd64.go b/vendor/github.com/golang/snappy/decode_amd64.go index 32bce47093..fcd192b849 100644 --- a/vendor/github.com/golang/snappy/decode_amd64.go +++ b/vendor/github.com/golang/snappy/decode_amd64.go @@ -2,6 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build !appengine +// +build gc +// +build !noasm + package snappy // decode has the same semantics as in decode_other.go. diff --git a/vendor/github.com/golang/snappy/decode_amd64.s b/vendor/github.com/golang/snappy/decode_amd64.s index c33f5bf97b..e6179f65e3 100644 --- a/vendor/github.com/golang/snappy/decode_amd64.s +++ b/vendor/github.com/golang/snappy/decode_amd64.s @@ -2,12 +2,16 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build !appengine +// +build gc +// +build !noasm + #include "textflag.h" -// func decode(dst, src []byte) int -// // The asm code generally follows the pure Go code in decode_other.go, except // where marked with a "!!!". + +// func decode(dst, src []byte) int // // All local variables fit into registers. The non-zero stack size is only to // spill registers and push args when issuing a CALL. The register allocation: @@ -222,6 +226,25 @@ tagLit63: // ---------------------------------------- // The code below handles copy tags. +tagCopy4: + // case tagCopy4: + // s += 5 + ADDQ $5, SI + + // if uint(s) > uint(len(src)) { etc } + MOVQ SI, BX + SUBQ R11, BX + CMPQ BX, R12 + JA errCorrupt + + // length = 1 + int(src[s-5])>>2 + SHRQ $2, CX + INCQ CX + + // offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) + MOVLQZX -4(SI), DX + JMP doCopy + tagCopy2: // case tagCopy2: // s += 3 @@ -237,7 +260,7 @@ tagCopy2: SHRQ $2, CX INCQ CX - // offset = int(src[s-2]) | int(src[s-1])<<8 + // offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) MOVWQZX -2(SI), DX JMP doCopy @@ -247,7 +270,7 @@ tagCopy: // - CX == src[s] CMPQ BX, $2 JEQ tagCopy2 - JA errUC4T + JA tagCopy4 // case tagCopy1: // s += 2 @@ -259,7 +282,7 @@ tagCopy: CMPQ BX, R12 JA errCorrupt - // offset = int(src[s-2])&0xe0<<3 | int(src[s-1]) + // offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) MOVQ CX, DX ANDQ $0xe0, DX SHLQ $3, DX @@ -465,8 +488,3 @@ errCorrupt: // return decodeErrCodeCorrupt MOVQ $1, ret+48(FP) RET - -errUC4T: - // return decodeErrCodeUnsupportedCopy4Tag - MOVQ $3, ret+48(FP) - RET diff --git a/vendor/github.com/golang/snappy/decode_other.go b/vendor/github.com/golang/snappy/decode_other.go index 1a8114ab1f..8c9f2049bc 100644 --- a/vendor/github.com/golang/snappy/decode_other.go +++ b/vendor/github.com/golang/snappy/decode_other.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 +// +build !amd64 appengine !gc noasm package snappy @@ -63,7 +63,7 @@ func decode(dst, src []byte) int { return decodeErrCodeCorrupt } length = 4 + int(src[s-2])>>2&0x7 - offset = int(src[s-2])&0xe0<<3 | int(src[s-1]) + offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) case tagCopy2: s += 3 @@ -71,10 +71,15 @@ func decode(dst, src []byte) int { return decodeErrCodeCorrupt } length = 1 + int(src[s-3])>>2 - offset = int(src[s-2]) | int(src[s-1])<<8 + offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) case tagCopy4: - return decodeErrCodeUnsupportedCopy4Tag + s += 5 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = 1 + int(src[s-5])>>2 + offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) } if offset <= 0 || d < offset || length > len(dst)-d { diff --git a/vendor/github.com/golang/snappy/encode.go b/vendor/github.com/golang/snappy/encode.go index 38ebe952e0..8d393e904b 100644 --- a/vendor/github.com/golang/snappy/encode.go +++ b/vendor/github.com/golang/snappy/encode.go @@ -10,78 +10,11 @@ import ( "io" ) -// maxOffset limits how far copy back-references can go, the same as the C++ -// code. -const maxOffset = 1 << 15 - -// emitLiteral writes a literal chunk and returns the number of bytes written. -func emitLiteral(dst, lit []byte) int { - i, n := 0, uint(len(lit)-1) - switch { - case n < 60: - dst[0] = uint8(n)<<2 | tagLiteral - i = 1 - case n < 1<<8: - dst[0] = 60<<2 | tagLiteral - dst[1] = uint8(n) - i = 2 - case n < 1<<16: - dst[0] = 61<<2 | tagLiteral - dst[1] = uint8(n) - dst[2] = uint8(n >> 8) - i = 3 - case n < 1<<24: - dst[0] = 62<<2 | tagLiteral - dst[1] = uint8(n) - dst[2] = uint8(n >> 8) - dst[3] = uint8(n >> 16) - i = 4 - case int64(n) < 1<<32: - dst[0] = 63<<2 | tagLiteral - dst[1] = uint8(n) - dst[2] = uint8(n >> 8) - dst[3] = uint8(n >> 16) - dst[4] = uint8(n >> 24) - i = 5 - default: - panic("snappy: source buffer is too long") - } - if copy(dst[i:], lit) != len(lit) { - panic("snappy: destination buffer is too short") - } - return i + len(lit) -} - -// emitCopy writes a copy chunk and returns the number of bytes written. -func emitCopy(dst []byte, offset, length int32) int { - i := 0 - for length > 0 { - x := length - 4 - if 0 <= x && x < 1<<3 && offset < 1<<11 { - dst[i+0] = uint8(offset>>8)&0x07<<5 | uint8(x)<<2 | tagCopy1 - dst[i+1] = uint8(offset) - i += 2 - break - } - - x = length - if x > 1<<6 { - x = 1 << 6 - } - dst[i+0] = uint8(x-1)<<2 | tagCopy2 - dst[i+1] = uint8(offset) - dst[i+2] = uint8(offset >> 8) - i += 3 - length -= x - } - return i -} - // Encode returns the encoded form of src. The returned slice may be a sub- // slice of dst if dst was large enough to hold the entire encoded block. // Otherwise, a newly allocated slice will be returned. // -// It is valid to pass a nil dst. +// The dst and src must not overlap. It is valid to pass a nil dst. func Encode(dst, src []byte) []byte { if n := MaxEncodedLen(len(src)); n < 0 { panic(ErrTooLarge) @@ -98,94 +31,43 @@ func Encode(dst, src []byte) []byte { if len(p) > maxBlockSize { p, src = p[:maxBlockSize], p[maxBlockSize:] } - d += encodeBlock(dst[d:], p) + if len(p) < minNonLiteralBlockSize { + d += emitLiteral(dst[d:], p) + } else { + d += encodeBlock(dst[d:], p) + } } return dst[:d] } -// encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It -// assumes that the varint-encoded length of the decompressed bytes has already -// been written. +// inputMargin is the minimum number of extra input bytes to keep, inside +// encodeBlock's inner loop. On some architectures, this margin lets us +// implement a fast path for emitLiteral, where the copy of short (<= 16 byte) +// literals can be implemented as a single load to and store from a 16-byte +// register. That literal's actual length can be as short as 1 byte, so this +// can copy up to 15 bytes too much, but that's OK as subsequent iterations of +// the encoding loop will fix up the copy overrun, and this inputMargin ensures +// that we don't overrun the dst and src buffers. +const inputMargin = 16 - 1 + +// minNonLiteralBlockSize is the minimum size of the input to encodeBlock that +// could be encoded with a copy tag. This is the minimum with respect to the +// algorithm used by encodeBlock, not a minimum enforced by the file format. // -// It also assumes that: -// len(dst) >= MaxEncodedLen(len(src)) && -// 0 < len(src) && len(src) <= maxBlockSize -func encodeBlock(dst, src []byte) (d int) { - // Return early if src is short. - if len(src) <= 4 { - return emitLiteral(dst, src) - } - - // Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive. - const maxTableSize = 1 << 14 - shift, tableSize := uint(32-8), 1<<8 - for tableSize < maxTableSize && tableSize < len(src) { - shift-- - tableSize *= 2 - } - var table [maxTableSize]int32 - - // Iterate over the source bytes. - var ( - s int32 // The iterator position. - t int32 // The last position with the same hash as s. - lit int32 // The start position of any pending literal bytes. - - // Copied from the C++ snappy implementation: - // - // Heuristic match skipping: If 32 bytes are scanned with no matches - // found, start looking only at every other byte. If 32 more bytes are - // scanned, look at every third byte, etc.. When a match is found, - // immediately go back to looking at every byte. This is a small loss - // (~5% performance, ~0.1% density) for compressible data due to more - // bookkeeping, but for non-compressible data (such as JPEG) it's a - // huge win since the compressor quickly "realizes" the data is - // incompressible and doesn't bother looking for matches everywhere. - // - // The "skip" variable keeps track of how many bytes there are since - // the last match; dividing it by 32 (ie. right-shifting by five) gives - // the number of bytes to move ahead for each iteration. - skip uint32 = 32 - ) - for uint32(s+3) < uint32(len(src)) { // The uint32 conversions catch overflow from the +3. - // Update the hash table. - b0, b1, b2, b3 := src[s], src[s+1], src[s+2], src[s+3] - h := uint32(b0) | uint32(b1)<<8 | uint32(b2)<<16 | uint32(b3)<<24 - p := &table[(h*0x1e35a7bd)>>shift] - // We need to to store values in [-1, inf) in table. To save - // some initialization time, (re)use the table's zero value - // and shift the values against this zero: add 1 on writes, - // subtract 1 on reads. - t, *p = *p-1, s+1 - // If t is invalid or src[s:s+4] differs from src[t:t+4], accumulate a literal byte. - if t < 0 || s-t >= maxOffset || b0 != src[t] || b1 != src[t+1] || b2 != src[t+2] || b3 != src[t+3] { - s += int32(skip >> 5) - skip++ - continue - } - skip = 32 - // Otherwise, we have a match. First, emit any pending literal bytes. - if lit != s { - d += emitLiteral(dst[d:], src[lit:s]) - } - // Extend the match to be as long as possible. - s0 := s - s, t = s+4, t+4 - for int(s) < len(src) && src[s] == src[t] { - s++ - t++ - } - // Emit the copied bytes. - d += emitCopy(dst[d:], s-t, s-s0) - lit = s - } - - // Emit any final pending literal bytes and return. - if int(lit) != len(src) { - d += emitLiteral(dst[d:], src[lit:]) - } - return d -} +// The encoded output must start with at least a 1 byte literal, as there are +// no previous bytes to copy. A minimal (1 byte) copy after that, generated +// from an emitCopy call in encodeBlock's main loop, would require at least +// another inputMargin bytes, for the reason above: we want any emitLiteral +// calls inside encodeBlock's main loop to use the fast path if possible, which +// requires being able to overrun by inputMargin bytes. Thus, +// minNonLiteralBlockSize equals 1 + 1 + inputMargin. +// +// The C++ code doesn't use this exact threshold, but it could, as discussed at +// https://groups.google.com/d/topic/snappy-compression/oGbhsdIJSJ8/discussion +// The difference between Go (2+inputMargin) and C++ (inputMargin) is purely an +// optimization. It should not affect the encoded form. This is tested by +// TestSameEncodingAsCppShortCopies. +const minNonLiteralBlockSize = 1 + 1 + inputMargin // MaxEncodedLen returns the maximum length of a snappy block, given its // uncompressed length. @@ -256,7 +138,7 @@ func NewBufferedWriter(w io.Writer) *Writer { } } -// Writer is an io.Writer than can write Snappy-compressed bytes. +// Writer is an io.Writer that can write Snappy-compressed bytes. type Writer struct { w io.Writer err error diff --git a/vendor/github.com/golang/snappy/encode_amd64.go b/vendor/github.com/golang/snappy/encode_amd64.go new file mode 100644 index 0000000000..150d91bc8b --- /dev/null +++ b/vendor/github.com/golang/snappy/encode_amd64.go @@ -0,0 +1,29 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine +// +build gc +// +build !noasm + +package snappy + +// emitLiteral has the same semantics as in encode_other.go. +// +//go:noescape +func emitLiteral(dst, lit []byte) int + +// emitCopy has the same semantics as in encode_other.go. +// +//go:noescape +func emitCopy(dst []byte, offset, length int) int + +// extendMatch has the same semantics as in encode_other.go. +// +//go:noescape +func extendMatch(src []byte, i, j int) int + +// encodeBlock has the same semantics as in encode_other.go. +// +//go:noescape +func encodeBlock(dst, src []byte) (d int) diff --git a/vendor/github.com/golang/snappy/encode_amd64.s b/vendor/github.com/golang/snappy/encode_amd64.s new file mode 100644 index 0000000000..adfd979fe2 --- /dev/null +++ b/vendor/github.com/golang/snappy/encode_amd64.s @@ -0,0 +1,730 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" + +// The XXX lines assemble on Go 1.4, 1.5 and 1.7, but not 1.6, due to a +// Go toolchain regression. See https://github.com/golang/go/issues/15426 and +// https://github.com/golang/snappy/issues/29 +// +// As a workaround, the package was built with a known good assembler, and +// those instructions were disassembled by "objdump -d" to yield the +// 4e 0f b7 7c 5c 78 movzwq 0x78(%rsp,%r11,2),%r15 +// style comments, in AT&T asm syntax. Note that rsp here is a physical +// register, not Go/asm's SP pseudo-register (see https://golang.org/doc/asm). +// The instructions were then encoded as "BYTE $0x.." sequences, which assemble +// fine on Go 1.6. + +// The asm code generally follows the pure Go code in encode_other.go, except +// where marked with a "!!!". + +// ---------------------------------------------------------------------------- + +// func emitLiteral(dst, lit []byte) int +// +// All local variables fit into registers. The register allocation: +// - AX len(lit) +// - BX n +// - DX return value +// - DI &dst[i] +// - R10 &lit[0] +// +// The 24 bytes of stack space is to call runtime·memmove. +// +// The unusual register allocation of local variables, such as R10 for the +// source pointer, matches the allocation used at the call site in encodeBlock, +// which makes it easier to manually inline this function. +TEXT ·emitLiteral(SB), NOSPLIT, $24-56 + MOVQ dst_base+0(FP), DI + MOVQ lit_base+24(FP), R10 + MOVQ lit_len+32(FP), AX + MOVQ AX, DX + MOVL AX, BX + SUBL $1, BX + + CMPL BX, $60 + JLT oneByte + CMPL BX, $256 + JLT twoBytes + +threeBytes: + MOVB $0xf4, 0(DI) + MOVW BX, 1(DI) + ADDQ $3, DI + ADDQ $3, DX + JMP memmove + +twoBytes: + MOVB $0xf0, 0(DI) + MOVB BX, 1(DI) + ADDQ $2, DI + ADDQ $2, DX + JMP memmove + +oneByte: + SHLB $2, BX + MOVB BX, 0(DI) + ADDQ $1, DI + ADDQ $1, DX + +memmove: + MOVQ DX, ret+48(FP) + + // copy(dst[i:], lit) + // + // This means calling runtime·memmove(&dst[i], &lit[0], len(lit)), so we push + // DI, R10 and AX as arguments. + MOVQ DI, 0(SP) + MOVQ R10, 8(SP) + MOVQ AX, 16(SP) + CALL runtime·memmove(SB) + RET + +// ---------------------------------------------------------------------------- + +// func emitCopy(dst []byte, offset, length int) int +// +// All local variables fit into registers. The register allocation: +// - AX length +// - SI &dst[0] +// - DI &dst[i] +// - R11 offset +// +// The unusual register allocation of local variables, such as R11 for the +// offset, matches the allocation used at the call site in encodeBlock, which +// makes it easier to manually inline this function. +TEXT ·emitCopy(SB), NOSPLIT, $0-48 + MOVQ dst_base+0(FP), DI + MOVQ DI, SI + MOVQ offset+24(FP), R11 + MOVQ length+32(FP), AX + +loop0: + // for length >= 68 { etc } + CMPL AX, $68 + JLT step1 + + // Emit a length 64 copy, encoded as 3 bytes. + MOVB $0xfe, 0(DI) + MOVW R11, 1(DI) + ADDQ $3, DI + SUBL $64, AX + JMP loop0 + +step1: + // if length > 64 { etc } + CMPL AX, $64 + JLE step2 + + // Emit a length 60 copy, encoded as 3 bytes. + MOVB $0xee, 0(DI) + MOVW R11, 1(DI) + ADDQ $3, DI + SUBL $60, AX + +step2: + // if length >= 12 || offset >= 2048 { goto step3 } + CMPL AX, $12 + JGE step3 + CMPL R11, $2048 + JGE step3 + + // Emit the remaining copy, encoded as 2 bytes. + MOVB R11, 1(DI) + SHRL $8, R11 + SHLB $5, R11 + SUBB $4, AX + SHLB $2, AX + ORB AX, R11 + ORB $1, R11 + MOVB R11, 0(DI) + ADDQ $2, DI + + // Return the number of bytes written. + SUBQ SI, DI + MOVQ DI, ret+40(FP) + RET + +step3: + // Emit the remaining copy, encoded as 3 bytes. + SUBL $1, AX + SHLB $2, AX + ORB $2, AX + MOVB AX, 0(DI) + MOVW R11, 1(DI) + ADDQ $3, DI + + // Return the number of bytes written. + SUBQ SI, DI + MOVQ DI, ret+40(FP) + RET + +// ---------------------------------------------------------------------------- + +// func extendMatch(src []byte, i, j int) int +// +// All local variables fit into registers. The register allocation: +// - DX &src[0] +// - SI &src[j] +// - R13 &src[len(src) - 8] +// - R14 &src[len(src)] +// - R15 &src[i] +// +// The unusual register allocation of local variables, such as R15 for a source +// pointer, matches the allocation used at the call site in encodeBlock, which +// makes it easier to manually inline this function. +TEXT ·extendMatch(SB), NOSPLIT, $0-48 + MOVQ src_base+0(FP), DX + MOVQ src_len+8(FP), R14 + MOVQ i+24(FP), R15 + MOVQ j+32(FP), SI + ADDQ DX, R14 + ADDQ DX, R15 + ADDQ DX, SI + MOVQ R14, R13 + SUBQ $8, R13 + +cmp8: + // As long as we are 8 or more bytes before the end of src, we can load and + // compare 8 bytes at a time. If those 8 bytes are equal, repeat. + CMPQ SI, R13 + JA cmp1 + MOVQ (R15), AX + MOVQ (SI), BX + CMPQ AX, BX + JNE bsf + ADDQ $8, R15 + ADDQ $8, SI + JMP cmp8 + +bsf: + // If those 8 bytes were not equal, XOR the two 8 byte values, and return + // the index of the first byte that differs. The BSF instruction finds the + // least significant 1 bit, the amd64 architecture is little-endian, and + // the shift by 3 converts a bit index to a byte index. + XORQ AX, BX + BSFQ BX, BX + SHRQ $3, BX + ADDQ BX, SI + + // Convert from &src[ret] to ret. + SUBQ DX, SI + MOVQ SI, ret+40(FP) + RET + +cmp1: + // In src's tail, compare 1 byte at a time. + CMPQ SI, R14 + JAE extendMatchEnd + MOVB (R15), AX + MOVB (SI), BX + CMPB AX, BX + JNE extendMatchEnd + ADDQ $1, R15 + ADDQ $1, SI + JMP cmp1 + +extendMatchEnd: + // Convert from &src[ret] to ret. + SUBQ DX, SI + MOVQ SI, ret+40(FP) + RET + +// ---------------------------------------------------------------------------- + +// func encodeBlock(dst, src []byte) (d int) +// +// All local variables fit into registers, other than "var table". The register +// allocation: +// - AX . . +// - BX . . +// - CX 56 shift (note that amd64 shifts by non-immediates must use CX). +// - DX 64 &src[0], tableSize +// - SI 72 &src[s] +// - DI 80 &dst[d] +// - R9 88 sLimit +// - R10 . &src[nextEmit] +// - R11 96 prevHash, currHash, nextHash, offset +// - R12 104 &src[base], skip +// - R13 . &src[nextS], &src[len(src) - 8] +// - R14 . len(src), bytesBetweenHashLookups, &src[len(src)], x +// - R15 112 candidate +// +// The second column (56, 64, etc) is the stack offset to spill the registers +// when calling other functions. We could pack this slightly tighter, but it's +// simpler to have a dedicated spill map independent of the function called. +// +// "var table [maxTableSize]uint16" takes up 32768 bytes of stack space. An +// extra 56 bytes, to call other functions, and an extra 64 bytes, to spill +// local variables (registers) during calls gives 32768 + 56 + 64 = 32888. +TEXT ·encodeBlock(SB), 0, $32888-56 + MOVQ dst_base+0(FP), DI + MOVQ src_base+24(FP), SI + MOVQ src_len+32(FP), R14 + + // shift, tableSize := uint32(32-8), 1<<8 + MOVQ $24, CX + MOVQ $256, DX + +calcShift: + // for ; tableSize < maxTableSize && tableSize < len(src); tableSize *= 2 { + // shift-- + // } + CMPQ DX, $16384 + JGE varTable + CMPQ DX, R14 + JGE varTable + SUBQ $1, CX + SHLQ $1, DX + JMP calcShift + +varTable: + // var table [maxTableSize]uint16 + // + // In the asm code, unlike the Go code, we can zero-initialize only the + // first tableSize elements. Each uint16 element is 2 bytes and each MOVOU + // writes 16 bytes, so we can do only tableSize/8 writes instead of the + // 2048 writes that would zero-initialize all of table's 32768 bytes. + SHRQ $3, DX + LEAQ table-32768(SP), BX + PXOR X0, X0 + +memclr: + MOVOU X0, 0(BX) + ADDQ $16, BX + SUBQ $1, DX + JNZ memclr + + // !!! DX = &src[0] + MOVQ SI, DX + + // sLimit := len(src) - inputMargin + MOVQ R14, R9 + SUBQ $15, R9 + + // !!! Pre-emptively spill CX, DX and R9 to the stack. Their values don't + // change for the rest of the function. + MOVQ CX, 56(SP) + MOVQ DX, 64(SP) + MOVQ R9, 88(SP) + + // nextEmit := 0 + MOVQ DX, R10 + + // s := 1 + ADDQ $1, SI + + // nextHash := hash(load32(src, s), shift) + MOVL 0(SI), R11 + IMULL $0x1e35a7bd, R11 + SHRL CX, R11 + +outer: + // for { etc } + + // skip := 32 + MOVQ $32, R12 + + // nextS := s + MOVQ SI, R13 + + // candidate := 0 + MOVQ $0, R15 + +inner0: + // for { etc } + + // s := nextS + MOVQ R13, SI + + // bytesBetweenHashLookups := skip >> 5 + MOVQ R12, R14 + SHRQ $5, R14 + + // nextS = s + bytesBetweenHashLookups + ADDQ R14, R13 + + // skip += bytesBetweenHashLookups + ADDQ R14, R12 + + // if nextS > sLimit { goto emitRemainder } + MOVQ R13, AX + SUBQ DX, AX + CMPQ AX, R9 + JA emitRemainder + + // candidate = int(table[nextHash]) + // XXX: MOVWQZX table-32768(SP)(R11*2), R15 + // XXX: 4e 0f b7 7c 5c 78 movzwq 0x78(%rsp,%r11,2),%r15 + BYTE $0x4e + BYTE $0x0f + BYTE $0xb7 + BYTE $0x7c + BYTE $0x5c + BYTE $0x78 + + // table[nextHash] = uint16(s) + MOVQ SI, AX + SUBQ DX, AX + + // XXX: MOVW AX, table-32768(SP)(R11*2) + // XXX: 66 42 89 44 5c 78 mov %ax,0x78(%rsp,%r11,2) + BYTE $0x66 + BYTE $0x42 + BYTE $0x89 + BYTE $0x44 + BYTE $0x5c + BYTE $0x78 + + // nextHash = hash(load32(src, nextS), shift) + MOVL 0(R13), R11 + IMULL $0x1e35a7bd, R11 + SHRL CX, R11 + + // if load32(src, s) != load32(src, candidate) { continue } break + MOVL 0(SI), AX + MOVL (DX)(R15*1), BX + CMPL AX, BX + JNE inner0 + +fourByteMatch: + // As per the encode_other.go code: + // + // A 4-byte match has been found. We'll later see etc. + + // !!! Jump to a fast path for short (<= 16 byte) literals. See the comment + // on inputMargin in encode.go. + MOVQ SI, AX + SUBQ R10, AX + CMPQ AX, $16 + JLE emitLiteralFastPath + + // ---------------------------------------- + // Begin inline of the emitLiteral call. + // + // d += emitLiteral(dst[d:], src[nextEmit:s]) + + MOVL AX, BX + SUBL $1, BX + + CMPL BX, $60 + JLT inlineEmitLiteralOneByte + CMPL BX, $256 + JLT inlineEmitLiteralTwoBytes + +inlineEmitLiteralThreeBytes: + MOVB $0xf4, 0(DI) + MOVW BX, 1(DI) + ADDQ $3, DI + JMP inlineEmitLiteralMemmove + +inlineEmitLiteralTwoBytes: + MOVB $0xf0, 0(DI) + MOVB BX, 1(DI) + ADDQ $2, DI + JMP inlineEmitLiteralMemmove + +inlineEmitLiteralOneByte: + SHLB $2, BX + MOVB BX, 0(DI) + ADDQ $1, DI + +inlineEmitLiteralMemmove: + // Spill local variables (registers) onto the stack; call; unspill. + // + // copy(dst[i:], lit) + // + // This means calling runtime·memmove(&dst[i], &lit[0], len(lit)), so we push + // DI, R10 and AX as arguments. + MOVQ DI, 0(SP) + MOVQ R10, 8(SP) + MOVQ AX, 16(SP) + ADDQ AX, DI // Finish the "d +=" part of "d += emitLiteral(etc)". + MOVQ SI, 72(SP) + MOVQ DI, 80(SP) + MOVQ R15, 112(SP) + CALL runtime·memmove(SB) + MOVQ 56(SP), CX + MOVQ 64(SP), DX + MOVQ 72(SP), SI + MOVQ 80(SP), DI + MOVQ 88(SP), R9 + MOVQ 112(SP), R15 + JMP inner1 + +inlineEmitLiteralEnd: + // End inline of the emitLiteral call. + // ---------------------------------------- + +emitLiteralFastPath: + // !!! Emit the 1-byte encoding "uint8(len(lit)-1)<<2". + MOVB AX, BX + SUBB $1, BX + SHLB $2, BX + MOVB BX, (DI) + ADDQ $1, DI + + // !!! Implement the copy from lit to dst as a 16-byte load and store. + // (Encode's documentation says that dst and src must not overlap.) + // + // This always copies 16 bytes, instead of only len(lit) bytes, but that's + // OK. Subsequent iterations will fix up the overrun. + // + // Note that on amd64, it is legal and cheap to issue unaligned 8-byte or + // 16-byte loads and stores. This technique probably wouldn't be as + // effective on architectures that are fussier about alignment. + MOVOU 0(R10), X0 + MOVOU X0, 0(DI) + ADDQ AX, DI + +inner1: + // for { etc } + + // base := s + MOVQ SI, R12 + + // !!! offset := base - candidate + MOVQ R12, R11 + SUBQ R15, R11 + SUBQ DX, R11 + + // ---------------------------------------- + // Begin inline of the extendMatch call. + // + // s = extendMatch(src, candidate+4, s+4) + + // !!! R14 = &src[len(src)] + MOVQ src_len+32(FP), R14 + ADDQ DX, R14 + + // !!! R13 = &src[len(src) - 8] + MOVQ R14, R13 + SUBQ $8, R13 + + // !!! R15 = &src[candidate + 4] + ADDQ $4, R15 + ADDQ DX, R15 + + // !!! s += 4 + ADDQ $4, SI + +inlineExtendMatchCmp8: + // As long as we are 8 or more bytes before the end of src, we can load and + // compare 8 bytes at a time. If those 8 bytes are equal, repeat. + CMPQ SI, R13 + JA inlineExtendMatchCmp1 + MOVQ (R15), AX + MOVQ (SI), BX + CMPQ AX, BX + JNE inlineExtendMatchBSF + ADDQ $8, R15 + ADDQ $8, SI + JMP inlineExtendMatchCmp8 + +inlineExtendMatchBSF: + // If those 8 bytes were not equal, XOR the two 8 byte values, and return + // the index of the first byte that differs. The BSF instruction finds the + // least significant 1 bit, the amd64 architecture is little-endian, and + // the shift by 3 converts a bit index to a byte index. + XORQ AX, BX + BSFQ BX, BX + SHRQ $3, BX + ADDQ BX, SI + JMP inlineExtendMatchEnd + +inlineExtendMatchCmp1: + // In src's tail, compare 1 byte at a time. + CMPQ SI, R14 + JAE inlineExtendMatchEnd + MOVB (R15), AX + MOVB (SI), BX + CMPB AX, BX + JNE inlineExtendMatchEnd + ADDQ $1, R15 + ADDQ $1, SI + JMP inlineExtendMatchCmp1 + +inlineExtendMatchEnd: + // End inline of the extendMatch call. + // ---------------------------------------- + + // ---------------------------------------- + // Begin inline of the emitCopy call. + // + // d += emitCopy(dst[d:], base-candidate, s-base) + + // !!! length := s - base + MOVQ SI, AX + SUBQ R12, AX + +inlineEmitCopyLoop0: + // for length >= 68 { etc } + CMPL AX, $68 + JLT inlineEmitCopyStep1 + + // Emit a length 64 copy, encoded as 3 bytes. + MOVB $0xfe, 0(DI) + MOVW R11, 1(DI) + ADDQ $3, DI + SUBL $64, AX + JMP inlineEmitCopyLoop0 + +inlineEmitCopyStep1: + // if length > 64 { etc } + CMPL AX, $64 + JLE inlineEmitCopyStep2 + + // Emit a length 60 copy, encoded as 3 bytes. + MOVB $0xee, 0(DI) + MOVW R11, 1(DI) + ADDQ $3, DI + SUBL $60, AX + +inlineEmitCopyStep2: + // if length >= 12 || offset >= 2048 { goto inlineEmitCopyStep3 } + CMPL AX, $12 + JGE inlineEmitCopyStep3 + CMPL R11, $2048 + JGE inlineEmitCopyStep3 + + // Emit the remaining copy, encoded as 2 bytes. + MOVB R11, 1(DI) + SHRL $8, R11 + SHLB $5, R11 + SUBB $4, AX + SHLB $2, AX + ORB AX, R11 + ORB $1, R11 + MOVB R11, 0(DI) + ADDQ $2, DI + JMP inlineEmitCopyEnd + +inlineEmitCopyStep3: + // Emit the remaining copy, encoded as 3 bytes. + SUBL $1, AX + SHLB $2, AX + ORB $2, AX + MOVB AX, 0(DI) + MOVW R11, 1(DI) + ADDQ $3, DI + +inlineEmitCopyEnd: + // End inline of the emitCopy call. + // ---------------------------------------- + + // nextEmit = s + MOVQ SI, R10 + + // if s >= sLimit { goto emitRemainder } + MOVQ SI, AX + SUBQ DX, AX + CMPQ AX, R9 + JAE emitRemainder + + // As per the encode_other.go code: + // + // We could immediately etc. + + // x := load64(src, s-1) + MOVQ -1(SI), R14 + + // prevHash := hash(uint32(x>>0), shift) + MOVL R14, R11 + IMULL $0x1e35a7bd, R11 + SHRL CX, R11 + + // table[prevHash] = uint16(s-1) + MOVQ SI, AX + SUBQ DX, AX + SUBQ $1, AX + + // XXX: MOVW AX, table-32768(SP)(R11*2) + // XXX: 66 42 89 44 5c 78 mov %ax,0x78(%rsp,%r11,2) + BYTE $0x66 + BYTE $0x42 + BYTE $0x89 + BYTE $0x44 + BYTE $0x5c + BYTE $0x78 + + // currHash := hash(uint32(x>>8), shift) + SHRQ $8, R14 + MOVL R14, R11 + IMULL $0x1e35a7bd, R11 + SHRL CX, R11 + + // candidate = int(table[currHash]) + // XXX: MOVWQZX table-32768(SP)(R11*2), R15 + // XXX: 4e 0f b7 7c 5c 78 movzwq 0x78(%rsp,%r11,2),%r15 + BYTE $0x4e + BYTE $0x0f + BYTE $0xb7 + BYTE $0x7c + BYTE $0x5c + BYTE $0x78 + + // table[currHash] = uint16(s) + ADDQ $1, AX + + // XXX: MOVW AX, table-32768(SP)(R11*2) + // XXX: 66 42 89 44 5c 78 mov %ax,0x78(%rsp,%r11,2) + BYTE $0x66 + BYTE $0x42 + BYTE $0x89 + BYTE $0x44 + BYTE $0x5c + BYTE $0x78 + + // if uint32(x>>8) == load32(src, candidate) { continue } + MOVL (DX)(R15*1), BX + CMPL R14, BX + JEQ inner1 + + // nextHash = hash(uint32(x>>16), shift) + SHRQ $8, R14 + MOVL R14, R11 + IMULL $0x1e35a7bd, R11 + SHRL CX, R11 + + // s++ + ADDQ $1, SI + + // break out of the inner1 for loop, i.e. continue the outer loop. + JMP outer + +emitRemainder: + // if nextEmit < len(src) { etc } + MOVQ src_len+32(FP), AX + ADDQ DX, AX + CMPQ R10, AX + JEQ encodeBlockEnd + + // d += emitLiteral(dst[d:], src[nextEmit:]) + // + // Push args. + MOVQ DI, 0(SP) + MOVQ $0, 8(SP) // Unnecessary, as the callee ignores it, but conservative. + MOVQ $0, 16(SP) // Unnecessary, as the callee ignores it, but conservative. + MOVQ R10, 24(SP) + SUBQ R10, AX + MOVQ AX, 32(SP) + MOVQ AX, 40(SP) // Unnecessary, as the callee ignores it, but conservative. + + // Spill local variables (registers) onto the stack; call; unspill. + MOVQ DI, 80(SP) + CALL ·emitLiteral(SB) + MOVQ 80(SP), DI + + // Finish the "d +=" part of "d += emitLiteral(etc)". + ADDQ 48(SP), DI + +encodeBlockEnd: + MOVQ dst_base+0(FP), AX + SUBQ AX, DI + MOVQ DI, d+48(FP) + RET diff --git a/vendor/github.com/golang/snappy/encode_other.go b/vendor/github.com/golang/snappy/encode_other.go new file mode 100644 index 0000000000..dbcae905e6 --- /dev/null +++ b/vendor/github.com/golang/snappy/encode_other.go @@ -0,0 +1,238 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !amd64 appengine !gc noasm + +package snappy + +func load32(b []byte, i int) uint32 { + b = b[i : i+4 : len(b)] // Help the compiler eliminate bounds checks on the next line. + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +func load64(b []byte, i int) uint64 { + b = b[i : i+8 : len(b)] // Help the compiler eliminate bounds checks on the next line. + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} + +// emitLiteral writes a literal chunk and returns the number of bytes written. +// +// It assumes that: +// dst is long enough to hold the encoded bytes +// 1 <= len(lit) && len(lit) <= 65536 +func emitLiteral(dst, lit []byte) int { + i, n := 0, uint(len(lit)-1) + switch { + case n < 60: + dst[0] = uint8(n)<<2 | tagLiteral + i = 1 + case n < 1<<8: + dst[0] = 60<<2 | tagLiteral + dst[1] = uint8(n) + i = 2 + default: + dst[0] = 61<<2 | tagLiteral + dst[1] = uint8(n) + dst[2] = uint8(n >> 8) + i = 3 + } + return i + copy(dst[i:], lit) +} + +// emitCopy writes a copy chunk and returns the number of bytes written. +// +// It assumes that: +// dst is long enough to hold the encoded bytes +// 1 <= offset && offset <= 65535 +// 4 <= length && length <= 65535 +func emitCopy(dst []byte, offset, length int) int { + i := 0 + // The maximum length for a single tagCopy1 or tagCopy2 op is 64 bytes. The + // threshold for this loop is a little higher (at 68 = 64 + 4), and the + // length emitted down below is is a little lower (at 60 = 64 - 4), because + // it's shorter to encode a length 67 copy as a length 60 tagCopy2 followed + // by a length 7 tagCopy1 (which encodes as 3+2 bytes) than to encode it as + // a length 64 tagCopy2 followed by a length 3 tagCopy2 (which encodes as + // 3+3 bytes). The magic 4 in the 64±4 is because the minimum length for a + // tagCopy1 op is 4 bytes, which is why a length 3 copy has to be an + // encodes-as-3-bytes tagCopy2 instead of an encodes-as-2-bytes tagCopy1. + for length >= 68 { + // Emit a length 64 copy, encoded as 3 bytes. + dst[i+0] = 63<<2 | tagCopy2 + dst[i+1] = uint8(offset) + dst[i+2] = uint8(offset >> 8) + i += 3 + length -= 64 + } + if length > 64 { + // Emit a length 60 copy, encoded as 3 bytes. + dst[i+0] = 59<<2 | tagCopy2 + dst[i+1] = uint8(offset) + dst[i+2] = uint8(offset >> 8) + i += 3 + length -= 60 + } + if length >= 12 || offset >= 2048 { + // Emit the remaining copy, encoded as 3 bytes. + dst[i+0] = uint8(length-1)<<2 | tagCopy2 + dst[i+1] = uint8(offset) + dst[i+2] = uint8(offset >> 8) + return i + 3 + } + // Emit the remaining copy, encoded as 2 bytes. + dst[i+0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1 + dst[i+1] = uint8(offset) + return i + 2 +} + +// extendMatch returns the largest k such that k <= len(src) and that +// src[i:i+k-j] and src[j:k] have the same contents. +// +// It assumes that: +// 0 <= i && i < j && j <= len(src) +func extendMatch(src []byte, i, j int) int { + for ; j < len(src) && src[i] == src[j]; i, j = i+1, j+1 { + } + return j +} + +func hash(u, shift uint32) uint32 { + return (u * 0x1e35a7bd) >> shift +} + +// encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlock(dst, src []byte) (d int) { + // Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive. + // The table element type is uint16, as s < sLimit and sLimit < len(src) + // and len(src) <= maxBlockSize and maxBlockSize == 65536. + const ( + maxTableSize = 1 << 14 + // tableMask is redundant, but helps the compiler eliminate bounds + // checks. + tableMask = maxTableSize - 1 + ) + shift := uint32(32 - 8) + for tableSize := 1 << 8; tableSize < maxTableSize && tableSize < len(src); tableSize *= 2 { + shift-- + } + // In Go, all array elements are zero-initialized, so there is no advantage + // to a smaller tableSize per se. However, it matches the C++ algorithm, + // and in the asm versions of this code, we can get away with zeroing only + // the first tableSize elements. + var table [maxTableSize]uint16 + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + nextHash := hash(load32(src, s), shift) + + for { + // Copied from the C++ snappy implementation: + // + // Heuristic match skipping: If 32 bytes are scanned with no matches + // found, start looking only at every other byte. If 32 more bytes are + // scanned (or skipped), look at every third byte, etc.. When a match + // is found, immediately go back to looking at every byte. This is a + // small loss (~5% performance, ~0.1% density) for compressible data + // due to more bookkeeping, but for non-compressible data (such as + // JPEG) it's a huge win since the compressor quickly "realizes" the + // data is incompressible and doesn't bother looking for matches + // everywhere. + // + // The "skip" variable keeps track of how many bytes there are since + // the last match; dividing it by 32 (ie. right-shifting by five) gives + // the number of bytes to move ahead for each iteration. + skip := 32 + + nextS := s + candidate := 0 + for { + s = nextS + bytesBetweenHashLookups := skip >> 5 + nextS = s + bytesBetweenHashLookups + skip += bytesBetweenHashLookups + if nextS > sLimit { + goto emitRemainder + } + candidate = int(table[nextHash&tableMask]) + table[nextHash&tableMask] = uint16(s) + nextHash = hash(load32(src, nextS), shift) + if load32(src, s) == load32(src, candidate) { + break + } + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + d += emitLiteral(dst[d:], src[nextEmit:s]) + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + + // Extend the 4-byte match as long as possible. + // + // This is an inlined version of: + // s = extendMatch(src, candidate+4, s+4) + s += 4 + for i := candidate + 4; s < len(src) && src[i] == src[s]; i, s = i+1, s+1 { + } + + d += emitCopy(dst[d:], base-candidate, s-base) + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-1 and at s. If + // another emitCopy is not our next move, also calculate nextHash + // at s+1. At least on GOARCH=amd64, these three hash calculations + // are faster as one load64 call (with some shifts) instead of + // three load32 calls. + x := load64(src, s-1) + prevHash := hash(uint32(x>>0), shift) + table[prevHash&tableMask] = uint16(s - 1) + currHash := hash(uint32(x>>8), shift) + candidate = int(table[currHash&tableMask]) + table[currHash&tableMask] = uint16(s) + if uint32(x>>8) != load32(src, candidate) { + nextHash = hash(uint32(x>>16), shift) + s++ + break + } + } + } + +emitRemainder: + if nextEmit < len(src) { + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} diff --git a/vendor/github.com/golang/snappy/snappy.go b/vendor/github.com/golang/snappy/snappy.go index 010254265f..ece692ea46 100644 --- a/vendor/github.com/golang/snappy/snappy.go +++ b/vendor/github.com/golang/snappy/snappy.go @@ -2,10 +2,21 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package snappy implements the snappy block-based compression format. -// It aims for very high speeds and reasonable compression. +// Package snappy implements the Snappy compression format. It aims for very +// high speeds and reasonable compression. // -// The C++ snappy implementation is at https://github.com/google/snappy +// There are actually two Snappy formats: block and stream. They are related, +// but different: trying to decompress block-compressed data as a Snappy stream +// will fail, and vice versa. The block format is the Decode and Encode +// functions and the stream format is the Reader and Writer types. +// +// The block format, the more common case, is used when the complete size (the +// number of bytes) of the original data is known upfront, at the time +// compression starts. The stream format, also known as the framing format, is +// for when that isn't always true. +// +// The canonical, C++ implementation is at https://github.com/google/snappy and +// it only implements the block format. package snappy // import "github.com/golang/snappy" import ( @@ -32,7 +43,10 @@ Lempel-Ziv compression algorithms. In particular: - For l == 2, the offset ranges in [0, 1<<16) and the length in [1, 65). The length is 1 + m. The offset is the little-endian unsigned integer denoted by the next 2 bytes. - - For l == 3, this tag is a legacy format that is no longer supported. + - For l == 3, this tag is a legacy format that is no longer issued by most + encoders. Nonetheless, the offset ranges in [0, 1<<32) and the length in + [1, 65). The length is 1 + m. The offset is the little-endian unsigned + integer denoted by the next 4 bytes. */ const ( tagLiteral = 0x00 diff --git a/vendor/github.com/gorilla/context/.travis.yml b/vendor/github.com/gorilla/context/.travis.yml new file mode 100644 index 0000000000..6f440f1e42 --- /dev/null +++ b/vendor/github.com/gorilla/context/.travis.yml @@ -0,0 +1,19 @@ +language: go +sudo: false + +matrix: + include: + - go: 1.3 + - go: 1.4 + - go: 1.5 + - go: 1.6 + - go: 1.7 + - go: tip + allow_failures: + - go: tip + +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d .) + - go vet $(go list ./... | grep -v /vendor/) + - go test -v -race ./... diff --git a/vendor/github.com/gorilla/context/README.md b/vendor/github.com/gorilla/context/README.md new file mode 100644 index 0000000000..08f86693bc --- /dev/null +++ b/vendor/github.com/gorilla/context/README.md @@ -0,0 +1,10 @@ +context +======= +[![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context) + +gorilla/context is a general purpose registry for global request variables. + +> Note: gorilla/context, having been born well before `context.Context` existed, does not play well +> with the shallow copying of the request that [`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) (added to net/http Go 1.7 onwards) performs. You should either use *just* gorilla/context, or moving forward, the new `http.Request.Context()`. + +Read the full documentation here: http://www.gorillatoolkit.org/pkg/context diff --git a/vendor/github.com/gorilla/mux/.travis.yml b/vendor/github.com/gorilla/mux/.travis.yml new file mode 100644 index 0000000000..ad0935dbd3 --- /dev/null +++ b/vendor/github.com/gorilla/mux/.travis.yml @@ -0,0 +1,23 @@ +language: go +sudo: false + +matrix: + include: + - go: 1.5.x + - go: 1.6.x + - go: 1.7.x + - go: 1.8.x + - go: 1.9.x + - go: 1.10.x + - go: tip + allow_failures: + - go: tip + +install: + - # Skip + +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d .) + - go tool vet . + - go test -v -race ./... diff --git a/vendor/github.com/gorilla/mux/ISSUE_TEMPLATE.md b/vendor/github.com/gorilla/mux/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..232be82e47 --- /dev/null +++ b/vendor/github.com/gorilla/mux/ISSUE_TEMPLATE.md @@ -0,0 +1,11 @@ +**What version of Go are you running?** (Paste the output of `go version`) + + +**What version of gorilla/mux are you at?** (Paste the output of `git rev-parse HEAD` inside `$GOPATH/src/github.com/gorilla/mux`) + + +**Describe your problem** (and what you have tried so far) + + +**Paste a minimal, runnable, reproduction of your issue below** (use backticks to format it) + diff --git a/vendor/github.com/gorilla/mux/README.md b/vendor/github.com/gorilla/mux/README.md new file mode 100644 index 0000000000..e424397ac4 --- /dev/null +++ b/vendor/github.com/gorilla/mux/README.md @@ -0,0 +1,649 @@ +# gorilla/mux + +[![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux) +[![Build Status](https://travis-ci.org/gorilla/mux.svg?branch=master)](https://travis-ci.org/gorilla/mux) +[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge) + +![Gorilla Logo](http://www.gorillatoolkit.org/static/images/gorilla-icon-64.png) + +http://www.gorillatoolkit.org/pkg/mux + +Package `gorilla/mux` implements a request router and dispatcher for matching incoming requests to +their respective handler. + +The name mux stands for "HTTP request multiplexer". Like the standard `http.ServeMux`, `mux.Router` matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions. The main features are: + +* It implements the `http.Handler` interface so it is compatible with the standard `http.ServeMux`. +* Requests can be matched based on URL host, path, path prefix, schemes, header and query values, HTTP methods or using custom matchers. +* URL hosts, paths and query values can have variables with an optional regular expression. +* Registered URLs can be built, or "reversed", which helps maintaining references to resources. +* Routes can be used as subrouters: nested routes are only tested if the parent route matches. This is useful to define groups of routes that share common conditions like a host, a path prefix or other repeated attributes. As a bonus, this optimizes request matching. + +--- + +* [Install](#install) +* [Examples](#examples) +* [Matching Routes](#matching-routes) +* [Static Files](#static-files) +* [Registered URLs](#registered-urls) +* [Walking Routes](#walking-routes) +* [Graceful Shutdown](#graceful-shutdown) +* [Middleware](#middleware) +* [Testing Handlers](#testing-handlers) +* [Full Example](#full-example) + +--- + +## Install + +With a [correctly configured](https://golang.org/doc/install#testing) Go toolchain: + +```sh +go get -u github.com/gorilla/mux +``` + +## Examples + +Let's start registering a couple of URL paths and handlers: + +```go +func main() { + r := mux.NewRouter() + r.HandleFunc("/", HomeHandler) + r.HandleFunc("/products", ProductsHandler) + r.HandleFunc("/articles", ArticlesHandler) + http.Handle("/", r) +} +``` + +Here we register three routes mapping URL paths to handlers. This is equivalent to how `http.HandleFunc()` works: if an incoming request URL matches one of the paths, the corresponding handler is called passing (`http.ResponseWriter`, `*http.Request`) as parameters. + +Paths can have variables. They are defined using the format `{name}` or `{name:pattern}`. If a regular expression pattern is not defined, the matched variable will be anything until the next slash. For example: + +```go +r := mux.NewRouter() +r.HandleFunc("/products/{key}", ProductHandler) +r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) +r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) +``` + +The names are used to create a map of route variables which can be retrieved calling `mux.Vars()`: + +```go +func ArticlesCategoryHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "Category: %v\n", vars["category"]) +} +``` + +And this is all you need to know about the basic usage. More advanced options are explained below. + +### Matching Routes + +Routes can also be restricted to a domain or subdomain. Just define a host pattern to be matched. They can also have variables: + +```go +r := mux.NewRouter() +// Only matches if domain is "www.example.com". +r.Host("www.example.com") +// Matches a dynamic subdomain. +r.Host("{subdomain:[a-z]+}.domain.com") +``` + +There are several other matchers that can be added. To match path prefixes: + +```go +r.PathPrefix("/products/") +``` + +...or HTTP methods: + +```go +r.Methods("GET", "POST") +``` + +...or URL schemes: + +```go +r.Schemes("https") +``` + +...or header values: + +```go +r.Headers("X-Requested-With", "XMLHttpRequest") +``` + +...or query values: + +```go +r.Queries("key", "value") +``` + +...or to use a custom matcher function: + +```go +r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { + return r.ProtoMajor == 0 +}) +``` + +...and finally, it is possible to combine several matchers in a single route: + +```go +r.HandleFunc("/products", ProductsHandler). + Host("www.example.com"). + Methods("GET"). + Schemes("http") +``` + +Routes are tested in the order they were added to the router. If two routes match, the first one wins: + +```go +r := mux.NewRouter() +r.HandleFunc("/specific", specificHandler) +r.PathPrefix("/").Handler(catchAllHandler) +``` + +Setting the same matching conditions again and again can be boring, so we have a way to group several routes that share the same requirements. We call it "subrouting". + +For example, let's say we have several URLs that should only match when the host is `www.example.com`. Create a route for that host and get a "subrouter" from it: + +```go +r := mux.NewRouter() +s := r.Host("www.example.com").Subrouter() +``` + +Then register routes in the subrouter: + +```go +s.HandleFunc("/products/", ProductsHandler) +s.HandleFunc("/products/{key}", ProductHandler) +s.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) +``` + +The three URL paths we registered above will only be tested if the domain is `www.example.com`, because the subrouter is tested first. This is not only convenient, but also optimizes request matching. You can create subrouters combining any attribute matchers accepted by a route. + +Subrouters can be used to create domain or path "namespaces": you define subrouters in a central place and then parts of the app can register its paths relatively to a given subrouter. + +There's one more thing about subroutes. When a subrouter has a path prefix, the inner routes use it as base for their paths: + +```go +r := mux.NewRouter() +s := r.PathPrefix("/products").Subrouter() +// "/products/" +s.HandleFunc("/", ProductsHandler) +// "/products/{key}/" +s.HandleFunc("/{key}/", ProductHandler) +// "/products/{key}/details" +s.HandleFunc("/{key}/details", ProductDetailsHandler) +``` + + +### Static Files + +Note that the path provided to `PathPrefix()` represents a "wildcard": calling +`PathPrefix("/static/").Handler(...)` means that the handler will be passed any +request that matches "/static/\*". This makes it easy to serve static files with mux: + +```go +func main() { + var dir string + + flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir") + flag.Parse() + r := mux.NewRouter() + + // This will serve files under http://localhost:8000/static/ + r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir)))) + + srv := &http.Server{ + Handler: r, + Addr: "127.0.0.1:8000", + // Good practice: enforce timeouts for servers you create! + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) +} +``` + +### Registered URLs + +Now let's see how to build registered URLs. + +Routes can be named. All routes that define a name can have their URLs built, or "reversed". We define a name calling `Name()` on a route. For example: + +```go +r := mux.NewRouter() +r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). + Name("article") +``` + +To build a URL, get the route and call the `URL()` method, passing a sequence of key/value pairs for the route variables. For the previous route, we would do: + +```go +url, err := r.Get("article").URL("category", "technology", "id", "42") +``` + +...and the result will be a `url.URL` with the following path: + +``` +"/articles/technology/42" +``` + +This also works for host and query value variables: + +```go +r := mux.NewRouter() +r.Host("{subdomain}.domain.com"). + Path("/articles/{category}/{id:[0-9]+}"). + Queries("filter", "{filter}"). + HandlerFunc(ArticleHandler). + Name("article") + +// url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla" +url, err := r.Get("article").URL("subdomain", "news", + "category", "technology", + "id", "42", + "filter", "gorilla") +``` + +All variables defined in the route are required, and their values must conform to the corresponding patterns. These requirements guarantee that a generated URL will always match a registered route -- the only exception is for explicitly defined "build-only" routes which never match. + +Regex support also exists for matching Headers within a route. For example, we could do: + +```go +r.HeadersRegexp("Content-Type", "application/(text|json)") +``` + +...and the route will match both requests with a Content-Type of `application/json` as well as `application/text` + +There's also a way to build only the URL host or path for a route: use the methods `URLHost()` or `URLPath()` instead. For the previous route, we would do: + +```go +// "http://news.domain.com/" +host, err := r.Get("article").URLHost("subdomain", "news") + +// "/articles/technology/42" +path, err := r.Get("article").URLPath("category", "technology", "id", "42") +``` + +And if you use subrouters, host and path defined separately can be built as well: + +```go +r := mux.NewRouter() +s := r.Host("{subdomain}.domain.com").Subrouter() +s.Path("/articles/{category}/{id:[0-9]+}"). + HandlerFunc(ArticleHandler). + Name("article") + +// "http://news.domain.com/articles/technology/42" +url, err := r.Get("article").URL("subdomain", "news", + "category", "technology", + "id", "42") +``` + +### Walking Routes + +The `Walk` function on `mux.Router` can be used to visit all of the routes that are registered on a router. For example, +the following prints all of the registered routes: + +```go +package main + +import ( + "fmt" + "net/http" + "strings" + + "github.com/gorilla/mux" +) + +func handler(w http.ResponseWriter, r *http.Request) { + return +} + +func main() { + r := mux.NewRouter() + r.HandleFunc("/", handler) + r.HandleFunc("/products", handler).Methods("POST") + r.HandleFunc("/articles", handler).Methods("GET") + r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT") + r.HandleFunc("/authors", handler).Queries("surname", "{surname}") + err := r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { + pathTemplate, err := route.GetPathTemplate() + if err == nil { + fmt.Println("ROUTE:", pathTemplate) + } + pathRegexp, err := route.GetPathRegexp() + if err == nil { + fmt.Println("Path regexp:", pathRegexp) + } + queriesTemplates, err := route.GetQueriesTemplates() + if err == nil { + fmt.Println("Queries templates:", strings.Join(queriesTemplates, ",")) + } + queriesRegexps, err := route.GetQueriesRegexp() + if err == nil { + fmt.Println("Queries regexps:", strings.Join(queriesRegexps, ",")) + } + methods, err := route.GetMethods() + if err == nil { + fmt.Println("Methods:", strings.Join(methods, ",")) + } + fmt.Println() + return nil + }) + + if err != nil { + fmt.Println(err) + } + + http.Handle("/", r) +} +``` + +### Graceful Shutdown + +Go 1.8 introduced the ability to [gracefully shutdown](https://golang.org/doc/go1.8#http_shutdown) a `*http.Server`. Here's how to do that alongside `mux`: + +```go +package main + +import ( + "context" + "flag" + "log" + "net/http" + "os" + "os/signal" + "time" + + "github.com/gorilla/mux" +) + +func main() { + var wait time.Duration + flag.DurationVar(&wait, "graceful-timeout", time.Second * 15, "the duration for which the server gracefully wait for existing connections to finish - e.g. 15s or 1m") + flag.Parse() + + r := mux.NewRouter() + // Add your routes as needed + + srv := &http.Server{ + Addr: "0.0.0.0:8080", + // Good practice to set timeouts to avoid Slowloris attacks. + WriteTimeout: time.Second * 15, + ReadTimeout: time.Second * 15, + IdleTimeout: time.Second * 60, + Handler: r, // Pass our instance of gorilla/mux in. + } + + // Run our server in a goroutine so that it doesn't block. + go func() { + if err := srv.ListenAndServe(); err != nil { + log.Println(err) + } + }() + + c := make(chan os.Signal, 1) + // We'll accept graceful shutdowns when quit via SIGINT (Ctrl+C) + // SIGKILL, SIGQUIT or SIGTERM (Ctrl+/) will not be caught. + signal.Notify(c, os.Interrupt) + + // Block until we receive our signal. + <-c + + // Create a deadline to wait for. + ctx, cancel := context.WithTimeout(context.Background(), wait) + defer cancel() + // Doesn't block if no connections, but will otherwise wait + // until the timeout deadline. + srv.Shutdown(ctx) + // Optionally, you could run srv.Shutdown in a goroutine and block on + // <-ctx.Done() if your application should wait for other services + // to finalize based on context cancellation. + log.Println("shutting down") + os.Exit(0) +} +``` + +### Middleware + +Mux supports the addition of middlewares to a [Router](https://godoc.org/github.com/gorilla/mux#Router), which are executed in the order they are added if a match is found, including its subrouters. +Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or `ResponseWriter` hijacking. + +Mux middlewares are defined using the de facto standard type: + +```go +type MiddlewareFunc func(http.Handler) http.Handler +``` + +Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc. This takes advantage of closures being able access variables from the context where they are created, while retaining the signature enforced by the receivers. + +A very basic middleware which logs the URI of the request being handled could be written as: + +```go +func loggingMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Do stuff here + log.Println(r.RequestURI) + // Call the next handler, which can be another middleware in the chain, or the final handler. + next.ServeHTTP(w, r) + }) +} +``` + +Middlewares can be added to a router using `Router.Use()`: + +```go +r := mux.NewRouter() +r.HandleFunc("/", handler) +r.Use(loggingMiddleware) +``` + +A more complex authentication middleware, which maps session token to users, could be written as: + +```go +// Define our struct +type authenticationMiddleware struct { + tokenUsers map[string]string +} + +// Initialize it somewhere +func (amw *authenticationMiddleware) Populate() { + amw.tokenUsers["00000000"] = "user0" + amw.tokenUsers["aaaaaaaa"] = "userA" + amw.tokenUsers["05f717e5"] = "randomUser" + amw.tokenUsers["deadbeef"] = "user0" +} + +// Middleware function, which will be called for each request +func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("X-Session-Token") + + if user, found := amw.tokenUsers[token]; found { + // We found the token in our map + log.Printf("Authenticated user %s\n", user) + // Pass down the request to the next middleware (or final handler) + next.ServeHTTP(w, r) + } else { + // Write an error and stop the handler chain + http.Error(w, "Forbidden", http.StatusForbidden) + } + }) +} +``` + +```go +r := mux.NewRouter() +r.HandleFunc("/", handler) + +amw := authenticationMiddleware{} +amw.Populate() + +r.Use(amw.Middleware) +``` + +Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. Middlewares _should_ write to `ResponseWriter` if they _are_ going to terminate the request, and they _should not_ write to `ResponseWriter` if they _are not_ going to terminate it. + +### Testing Handlers + +Testing handlers in a Go web application is straightforward, and _mux_ doesn't complicate this any further. Given two files: `endpoints.go` and `endpoints_test.go`, here's how we'd test an application using _mux_. + +First, our simple HTTP handler: + +```go +// endpoints.go +package main + +func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { + // A very simple health check. + w.WriteHeader(http.StatusOK) + w.Header().Set("Content-Type", "application/json") + + // In the future we could report back on the status of our DB, or our cache + // (e.g. Redis) by performing a simple PING, and include them in the response. + io.WriteString(w, `{"alive": true}`) +} + +func main() { + r := mux.NewRouter() + r.HandleFunc("/health", HealthCheckHandler) + + log.Fatal(http.ListenAndServe("localhost:8080", r)) +} +``` + +Our test code: + +```go +// endpoints_test.go +package main + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestHealthCheckHandler(t *testing.T) { + // Create a request to pass to our handler. We don't have any query parameters for now, so we'll + // pass 'nil' as the third parameter. + req, err := http.NewRequest("GET", "/health", nil) + if err != nil { + t.Fatal(err) + } + + // We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response. + rr := httptest.NewRecorder() + handler := http.HandlerFunc(HealthCheckHandler) + + // Our handlers satisfy http.Handler, so we can call their ServeHTTP method + // directly and pass in our Request and ResponseRecorder. + handler.ServeHTTP(rr, req) + + // Check the status code is what we expect. + if status := rr.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusOK) + } + + // Check the response body is what we expect. + expected := `{"alive": true}` + if rr.Body.String() != expected { + t.Errorf("handler returned unexpected body: got %v want %v", + rr.Body.String(), expected) + } +} +``` + +In the case that our routes have [variables](#examples), we can pass those in the request. We could write +[table-driven tests](https://dave.cheney.net/2013/06/09/writing-table-driven-tests-in-go) to test multiple +possible route variables as needed. + +```go +// endpoints.go +func main() { + r := mux.NewRouter() + // A route with a route variable: + r.HandleFunc("/metrics/{type}", MetricsHandler) + + log.Fatal(http.ListenAndServe("localhost:8080", r)) +} +``` + +Our test file, with a table-driven test of `routeVariables`: + +```go +// endpoints_test.go +func TestMetricsHandler(t *testing.T) { + tt := []struct{ + routeVariable string + shouldPass bool + }{ + {"goroutines", true}, + {"heap", true}, + {"counters", true}, + {"queries", true}, + {"adhadaeqm3k", false}, + } + + for _, tc := range tt { + path := fmt.Sprintf("/metrics/%s", tc.routeVariable) + req, err := http.NewRequest("GET", path, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + + // Need to create a router that we can pass the request through so that the vars will be added to the context + router := mux.NewRouter() + router.HandleFunc("/metrics/{type}", MetricsHandler) + router.ServeHTTP(rr, req) + + // In this case, our MetricsHandler returns a non-200 response + // for a route variable it doesn't know about. + if rr.Code == http.StatusOK && !tc.shouldPass { + t.Errorf("handler should have failed on routeVariable %s: got %v want %v", + tc.routeVariable, rr.Code, http.StatusOK) + } + } +} +``` + +## Full Example + +Here's a complete, runnable example of a small `mux` based server: + +```go +package main + +import ( + "net/http" + "log" + "github.com/gorilla/mux" +) + +func YourHandler(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("Gorilla!\n")) +} + +func main() { + r := mux.NewRouter() + // Routes consist of a path and a handler function. + r.HandleFunc("/", YourHandler) + + // Bind to a port and pass our router in + log.Fatal(http.ListenAndServe(":8000", r)) +} +``` + +## License + +BSD licensed. See the LICENSE file for details. diff --git a/vendor/github.com/gorilla/mux/doc.go b/vendor/github.com/gorilla/mux/doc.go index e9573dd8ad..38957deead 100644 --- a/vendor/github.com/gorilla/mux/doc.go +++ b/vendor/github.com/gorilla/mux/doc.go @@ -12,8 +12,8 @@ or other conditions. The main features are: * Requests can be matched based on URL host, path, path prefix, schemes, header and query values, HTTP methods or using custom matchers. - * URL hosts and paths can have variables with an optional regular - expression. + * URL hosts, paths and query values can have variables with an optional + regular expression. * Registered URLs can be built, or "reversed", which helps maintaining references to resources. * Routes can be used as subrouters: nested routes are only tested if the @@ -57,6 +57,11 @@ calling mux.Vars(): vars := mux.Vars(request) category := vars["category"] +Note that if any capturing groups are present, mux will panic() during parsing. To prevent +this, convert any capturing groups to non-capturing, e.g. change "/{sort:(asc|desc)}" to +"/{sort:(?:asc|desc)}". This is a change from prior versions which behaved unpredictably +when capturing groups were present. + And this is all you need to know about the basic usage. More advanced options are explained below. @@ -183,18 +188,20 @@ key/value pairs for the route variables. For the previous route, we would do: "/articles/technology/42" -This also works for host variables: +This also works for host and query value variables: r := mux.NewRouter() r.Host("{subdomain}.domain.com"). Path("/articles/{category}/{id:[0-9]+}"). + Queries("filter", "{filter}"). HandlerFunc(ArticleHandler). Name("article") - // url.String() will be "http://news.domain.com/articles/technology/42" + // url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla" url, err := r.Get("article").URL("subdomain", "news", "category", "technology", - "id", "42") + "id", "42", + "filter", "gorilla") All variables defined in the route are required, and their values must conform to the corresponding patterns. These requirements guarantee that a @@ -231,5 +238,69 @@ as well: url, err := r.Get("article").URL("subdomain", "news", "category", "technology", "id", "42") + +Mux supports the addition of middlewares to a Router, which are executed in the order they are added if a match is found, including its subrouters. Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or ResponseWriter hijacking. + + type MiddlewareFunc func(http.Handler) http.Handler + +Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc (closures can access variables from the context where they are created). + +A very basic middleware which logs the URI of the request being handled could be written as: + + func simpleMw(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Do stuff here + log.Println(r.RequestURI) + // Call the next handler, which can be another middleware in the chain, or the final handler. + next.ServeHTTP(w, r) + }) + } + +Middlewares can be added to a router using `Router.Use()`: + + r := mux.NewRouter() + r.HandleFunc("/", handler) + r.Use(simpleMw) + +A more complex authentication middleware, which maps session token to users, could be written as: + + // Define our struct + type authenticationMiddleware struct { + tokenUsers map[string]string + } + + // Initialize it somewhere + func (amw *authenticationMiddleware) Populate() { + amw.tokenUsers["00000000"] = "user0" + amw.tokenUsers["aaaaaaaa"] = "userA" + amw.tokenUsers["05f717e5"] = "randomUser" + amw.tokenUsers["deadbeef"] = "user0" + } + + // Middleware function, which will be called for each request + func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("X-Session-Token") + + if user, found := amw.tokenUsers[token]; found { + // We found the token in our map + log.Printf("Authenticated user %s\n", user) + next.ServeHTTP(w, r) + } else { + http.Error(w, "Forbidden", http.StatusForbidden) + } + }) + } + + r := mux.NewRouter() + r.HandleFunc("/", handler) + + amw := authenticationMiddleware{} + amw.Populate() + + r.Use(amw.Middleware) + +Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. + */ package mux diff --git a/vendor/github.com/gorilla/mux/middleware.go b/vendor/github.com/gorilla/mux/middleware.go new file mode 100644 index 0000000000..ceb812cee2 --- /dev/null +++ b/vendor/github.com/gorilla/mux/middleware.go @@ -0,0 +1,72 @@ +package mux + +import ( + "net/http" + "strings" +) + +// MiddlewareFunc is a function which receives an http.Handler and returns another http.Handler. +// Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed +// to it, and then calls the handler passed as parameter to the MiddlewareFunc. +type MiddlewareFunc func(http.Handler) http.Handler + +// middleware interface is anything which implements a MiddlewareFunc named Middleware. +type middleware interface { + Middleware(handler http.Handler) http.Handler +} + +// Middleware allows MiddlewareFunc to implement the middleware interface. +func (mw MiddlewareFunc) Middleware(handler http.Handler) http.Handler { + return mw(handler) +} + +// Use appends a MiddlewareFunc to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router. +func (r *Router) Use(mwf ...MiddlewareFunc) { + for _, fn := range mwf { + r.middlewares = append(r.middlewares, fn) + } +} + +// useInterface appends a middleware to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router. +func (r *Router) useInterface(mw middleware) { + r.middlewares = append(r.middlewares, mw) +} + +// CORSMethodMiddleware sets the Access-Control-Allow-Methods response header +// on a request, by matching routes based only on paths. It also handles +// OPTIONS requests, by settings Access-Control-Allow-Methods, and then +// returning without calling the next http handler. +func CORSMethodMiddleware(r *Router) MiddlewareFunc { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + var allMethods []string + + err := r.Walk(func(route *Route, _ *Router, _ []*Route) error { + for _, m := range route.matchers { + if _, ok := m.(*routeRegexp); ok { + if m.Match(req, &RouteMatch{}) { + methods, err := route.GetMethods() + if err != nil { + return err + } + + allMethods = append(allMethods, methods...) + } + break + } + } + return nil + }) + + if err == nil { + w.Header().Set("Access-Control-Allow-Methods", strings.Join(append(allMethods, "OPTIONS"), ",")) + + if req.Method == "OPTIONS" { + return + } + } + + next.ServeHTTP(w, req) + }) + } +} diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go index d66ec38415..4bbafa51da 100644 --- a/vendor/github.com/gorilla/mux/mux.go +++ b/vendor/github.com/gorilla/mux/mux.go @@ -10,7 +10,14 @@ import ( "net/http" "path" "regexp" - "strings" +) + +var ( + // ErrMethodMismatch is returned when the method in the request does not match + // the method defined against the route. + ErrMethodMismatch = errors.New("method is not allowed") + // ErrNotFound is returned when no route match is found. + ErrNotFound = errors.New("no matching route was found") ) // NewRouter returns a new router instance. @@ -39,6 +46,10 @@ func NewRouter() *Router { type Router struct { // Configurable Handler to be used when no route matches. NotFoundHandler http.Handler + + // Configurable Handler to be used when the request method does not match the route. + MethodNotAllowedHandler http.Handler + // Parent route, if this is a subrouter. parent parentRoute // Routes to be matched, in order. @@ -55,21 +66,51 @@ type Router struct { KeepContext bool // see Router.UseEncodedPath(). This defines a flag for all routes. useEncodedPath bool + // Slice of middlewares to be called after a match is found + middlewares []middleware } -// Match matches registered routes against the request. +// Match attempts to match the given request against the router's registered routes. +// +// If the request matches a route of this router or one of its subrouters the Route, +// Handler, and Vars fields of the the match argument are filled and this function +// returns true. +// +// If the request does not match any of this router's or its subrouters' routes +// then this function returns false. If available, a reason for the match failure +// will be filled in the match argument's MatchErr field. If the match failure type +// (eg: not found) has a registered handler, the handler is assigned to the Handler +// field of the match argument. func (r *Router) Match(req *http.Request, match *RouteMatch) bool { for _, route := range r.routes { if route.Match(req, match) { + // Build middleware chain if no error was found + if match.MatchErr == nil { + for i := len(r.middlewares) - 1; i >= 0; i-- { + match.Handler = r.middlewares[i].Middleware(match.Handler) + } + } return true } } + if match.MatchErr == ErrMethodMismatch { + if r.MethodNotAllowedHandler != nil { + match.Handler = r.MethodNotAllowedHandler + return true + } + + return false + } + // Closest match for a router (includes sub-routers) if r.NotFoundHandler != nil { match.Handler = r.NotFoundHandler + match.MatchErr = ErrNotFound return true } + + match.MatchErr = ErrNotFound return false } @@ -81,7 +122,7 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { if !r.skipClean { path := req.URL.Path if r.useEncodedPath { - path = getPath(req) + path = req.URL.EscapedPath() } // Clean path to canonical form and redirect. if p := cleanPath(path); p != path { @@ -105,12 +146,19 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { req = setVars(req, match.Vars) req = setCurrentRoute(req, match.Route) } + + if handler == nil && match.MatchErr == ErrMethodMismatch { + handler = methodNotAllowedHandler() + } + if handler == nil { handler = http.NotFoundHandler() } + if !r.KeepContext { defer contextClear(req) } + handler.ServeHTTP(w, req) } @@ -128,13 +176,18 @@ func (r *Router) GetRoute(name string) *Route { // StrictSlash defines the trailing slash behavior for new routes. The initial // value is false. // -// When true, if the route path is "/path/", accessing "/path" will redirect +// When true, if the route path is "/path/", accessing "/path" will perform a redirect // to the former and vice versa. In other words, your application will always // see the path as specified in the route. // // When false, if the route path is "/path", accessing "/path/" will not match // this route and vice versa. // +// The re-direct is a HTTP 301 (Moved Permanently). Note that when this is set for +// routes with a non-idempotent method (e.g. POST, PUT), the subsequent re-directed +// request will be made as a GET by most clients. Use middleware or client settings +// to modify this behaviour as needed. +// // Special case: when a route sets a path prefix using the PathPrefix() method, // strict slash is ignored for that route because the redirect behavior can't // be determined from a prefix alone. However, any subrouters created from that @@ -160,10 +213,6 @@ func (r *Router) SkipClean(value bool) *Router { // UseEncodedPath tells the router to match the encoded original path // to the routes. // For eg. "/path/foo%2Fbar/to" will match the path "/path/{var}/to". -// This behavior has the drawback of needing to match routes against -// r.RequestURI instead of r.URL.Path. Any modifications (such as http.StripPrefix) -// to r.URL.Path will not affect routing when this flag is on and thus may -// induce unintended behavior. // // If not called, the router will match the unencoded path to the routes. // For eg. "/path/foo%2Fbar/to" will match the path "/path/foo/bar/to" @@ -176,6 +225,13 @@ func (r *Router) UseEncodedPath() *Router { // parentRoute // ---------------------------------------------------------------------------- +func (r *Router) getBuildScheme() string { + if r.parent != nil { + return r.parent.getBuildScheme() + } + return "" +} + // getNamedRoutes returns the map where named routes are registered. func (r *Router) getNamedRoutes() map[string]*Route { if r.namedRoutes == nil { @@ -299,10 +355,6 @@ type WalkFunc func(route *Route, router *Router, ancestors []*Route) error func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error { for _, t := range r.routes { - if t.regexp == nil || t.regexp.path == nil || t.regexp.path.template == "" { - continue - } - err := walkFn(t, r, ancestors) if err == SkipRouter { continue @@ -312,10 +364,12 @@ func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error { } for _, sr := range t.matchers { if h, ok := sr.(*Router); ok { + ancestors = append(ancestors, t) err := h.walk(walkFn, ancestors) if err != nil { return err } + ancestors = ancestors[:len(ancestors)-1] } } if h, ok := t.handler.(*Router); ok { @@ -339,6 +393,11 @@ type RouteMatch struct { Route *Route Handler http.Handler Vars map[string]string + + // MatchErr is set to appropriate matching error + // It is set to ErrMethodMismatch if there is a mismatch in + // the request method and route method + MatchErr error } type contextKey int @@ -380,28 +439,6 @@ func setCurrentRoute(r *http.Request, val interface{}) *http.Request { // Helpers // ---------------------------------------------------------------------------- -// getPath returns the escaped path if possible; doing what URL.EscapedPath() -// which was added in go1.5 does -func getPath(req *http.Request) string { - if req.RequestURI != "" { - // Extract the path from RequestURI (which is escaped unlike URL.Path) - // as detailed here as detailed in https://golang.org/pkg/net/url/#URL - // for < 1.5 server side workaround - // http://localhost/path/here?v=1 -> /path/here - path := req.RequestURI - path = strings.TrimPrefix(path, req.URL.Scheme+`://`) - path = strings.TrimPrefix(path, req.URL.Host) - if i := strings.LastIndex(path, "?"); i > -1 { - path = path[:i] - } - if i := strings.LastIndex(path, "#"); i > -1 { - path = path[:i] - } - return path - } - return req.URL.Path -} - // cleanPath returns the canonical path for p, eliminating . and .. elements. // Borrowed from the net/http package. func cleanPath(p string) string { @@ -458,7 +495,7 @@ func mapFromPairsToString(pairs ...string) (map[string]string, error) { return m, nil } -// mapFromPairsToRegex converts variadic string paramers to a +// mapFromPairsToRegex converts variadic string parameters to a // string to regex map. func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) { length, err := checkPairs(pairs...) @@ -540,3 +577,12 @@ func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]s } return true } + +// methodNotAllowed replies to the request with an HTTP status code 405. +func methodNotAllowed(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusMethodNotAllowed) +} + +// methodNotAllowedHandler returns a simple request handler +// that replies to each request with a status code 405. +func methodNotAllowedHandler() http.Handler { return http.HandlerFunc(methodNotAllowed) } diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go index fd8fe39560..2b57e5627d 100644 --- a/vendor/github.com/gorilla/mux/regexp.go +++ b/vendor/github.com/gorilla/mux/regexp.go @@ -14,6 +14,20 @@ import ( "strings" ) +type routeRegexpOptions struct { + strictSlash bool + useEncodedPath bool +} + +type regexpType int + +const ( + regexpTypePath regexpType = 0 + regexpTypeHost regexpType = 1 + regexpTypePrefix regexpType = 2 + regexpTypeQuery regexpType = 3 +) + // newRouteRegexp parses a route template and returns a routeRegexp, // used to match a host, a path or a query string. // @@ -24,7 +38,7 @@ import ( // Previously we accepted only Python-like identifiers for variable // names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that // name and pattern can't be empty, and names can't contain a colon. -func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash, useEncodedPath bool) (*routeRegexp, error) { +func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*routeRegexp, error) { // Check if it is well-formed. idxs, errBraces := braceIndices(tpl) if errBraces != nil { @@ -34,19 +48,18 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash, template := tpl // Now let's parse it. defaultPattern := "[^/]+" - if matchQuery { - defaultPattern = "[^?&]*" - } else if matchHost { + if typ == regexpTypeQuery { + defaultPattern = ".*" + } else if typ == regexpTypeHost { defaultPattern = "[^.]+" - matchPrefix = false } // Only match strict slash if not matching - if matchPrefix || matchHost || matchQuery { - strictSlash = false + if typ != regexpTypePath { + options.strictSlash = false } // Set a flag for strictSlash. endSlash := false - if strictSlash && strings.HasSuffix(tpl, "/") { + if options.strictSlash && strings.HasSuffix(tpl, "/") { tpl = tpl[:len(tpl)-1] endSlash = true } @@ -88,16 +101,16 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash, // Add the remaining. raw := tpl[end:] pattern.WriteString(regexp.QuoteMeta(raw)) - if strictSlash { + if options.strictSlash { pattern.WriteString("[/]?") } - if matchQuery { + if typ == regexpTypeQuery { // Add the default pattern if the query value is empty if queryVal := strings.SplitN(template, "=", 2)[1]; queryVal == "" { pattern.WriteString(defaultPattern) } } - if !matchPrefix { + if typ != regexpTypePrefix { pattern.WriteByte('$') } reverse.WriteString(raw) @@ -109,17 +122,22 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash, if errCompile != nil { return nil, errCompile } + + // Check for capturing groups which used to work in older versions + if reg.NumSubexp() != len(idxs)/2 { + panic(fmt.Sprintf("route %s contains capture groups in its regexp. ", template) + + "Only non-capturing groups are accepted: e.g. (?:pattern) instead of (pattern)") + } + // Done! return &routeRegexp{ - template: template, - matchHost: matchHost, - matchQuery: matchQuery, - strictSlash: strictSlash, - useEncodedPath: useEncodedPath, - regexp: reg, - reverse: reverse.String(), - varsN: varsN, - varsR: varsR, + template: template, + regexpType: typ, + options: options, + regexp: reg, + reverse: reverse.String(), + varsN: varsN, + varsR: varsR, }, nil } @@ -128,15 +146,10 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash, type routeRegexp struct { // The unmodified template. template string - // True for host match, false for path or query string match. - matchHost bool - // True for query string match, false for path and host match. - matchQuery bool - // The strictSlash value defined on the route, but disabled if PathPrefix was used. - strictSlash bool - // Determines whether to use encoded path from getPath function or unencoded - // req.URL.Path for path matching - useEncodedPath bool + // The type of match + regexpType regexpType + // Options for matching + options routeRegexpOptions // Expanded regexp. regexp *regexp.Regexp // Reverse template. @@ -149,13 +162,13 @@ type routeRegexp struct { // Match matches the regexp against the URL host or path. func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { - if !r.matchHost { - if r.matchQuery { + if r.regexpType != regexpTypeHost { + if r.regexpType == regexpTypeQuery { return r.matchQueryString(req) } path := req.URL.Path - if r.useEncodedPath { - path = getPath(req) + if r.options.useEncodedPath { + path = req.URL.EscapedPath() } return r.regexp.MatchString(path) } @@ -171,6 +184,9 @@ func (r *routeRegexp) url(values map[string]string) (string, error) { if !ok { return "", fmt.Errorf("mux: missing route variable %q", v) } + if r.regexpType == regexpTypeQuery { + value = url.QueryEscape(value) + } urlValues[k] = value } rv := fmt.Sprintf(r.reverse, urlValues...) @@ -193,7 +209,7 @@ func (r *routeRegexp) url(values map[string]string) (string, error) { // For a URL with foo=bar&baz=ding, we return only the relevant key // value pair for the routeRegexp. func (r *routeRegexp) getURLQuery(req *http.Request) string { - if !r.matchQuery { + if r.regexpType != regexpTypeQuery { return "" } templateKey := strings.SplitN(r.template, "=", 2)[0] @@ -262,7 +278,7 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) } path := req.URL.Path if r.useEncodedPath { - path = getPath(req) + path = req.URL.EscapedPath() } // Store path variables. if v.path != nil { @@ -270,7 +286,7 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) if len(matches) > 0 { extractVars(path, matches, v.path.varsN, m.Vars) // Check if we should redirect. - if v.path.strictSlash { + if v.path.options.strictSlash { p1 := strings.HasSuffix(path, "/") p2 := strings.HasSuffix(v.path.template, "/") if p1 != p2 { diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go index 293b6d4938..a591d73545 100644 --- a/vendor/github.com/gorilla/mux/route.go +++ b/vendor/github.com/gorilla/mux/route.go @@ -31,6 +31,8 @@ type Route struct { skipClean bool // If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to" useEncodedPath bool + // The scheme used when building URLs. + buildScheme string // If true, this route never matches: it is only used to build URLs. buildOnly bool // The name used to build URLs. @@ -41,6 +43,8 @@ type Route struct { buildVarsFunc BuildVarsFunc } +// SkipClean reports whether path cleaning is enabled for this route via +// Router.SkipClean. func (r *Route) SkipClean() bool { return r.skipClean } @@ -50,12 +54,33 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { if r.buildOnly || r.err != nil { return false } + + var matchErr error + // Match everything. for _, m := range r.matchers { if matched := m.Match(req, match); !matched { + if _, ok := m.(methodMatcher); ok { + matchErr = ErrMethodMismatch + continue + } + matchErr = nil return false } } + + if matchErr != nil { + match.MatchErr = matchErr + return false + } + + if match.MatchErr == ErrMethodMismatch { + // We found a route which matches request method, clear MatchErr + match.MatchErr = nil + // Then override the mis-matched handler + match.Handler = r.handler + } + // Yay, we have a match. Let's collect some info about it. if match.Route == nil { match.Route = r @@ -66,6 +91,7 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { if match.Vars == nil { match.Vars = make(map[string]string) } + // Set variables. if r.regexp != nil { r.regexp.setMatch(req, match, r) @@ -147,20 +173,23 @@ func (r *Route) addMatcher(m matcher) *Route { } // addRegexpMatcher adds a host or path matcher and builder to a route. -func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery bool) error { +func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error { if r.err != nil { return r.err } r.regexp = r.getRegexpGroup() - if !matchHost && !matchQuery { - if len(tpl) == 0 || tpl[0] != '/' { + if typ == regexpTypePath || typ == regexpTypePrefix { + if len(tpl) > 0 && tpl[0] != '/' { return fmt.Errorf("mux: path must start with a slash, got %q", tpl) } if r.regexp.path != nil { tpl = strings.TrimRight(r.regexp.path.template, "/") + tpl } } - rr, err := newRouteRegexp(tpl, matchHost, matchPrefix, matchQuery, r.strictSlash, r.useEncodedPath) + rr, err := newRouteRegexp(tpl, typ, routeRegexpOptions{ + strictSlash: r.strictSlash, + useEncodedPath: r.useEncodedPath, + }) if err != nil { return err } @@ -169,7 +198,7 @@ func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery return err } } - if matchHost { + if typ == regexpTypeHost { if r.regexp.path != nil { if err = uniqueVars(rr.varsN, r.regexp.path.varsN); err != nil { return err @@ -182,7 +211,7 @@ func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery return err } } - if matchQuery { + if typ == regexpTypeQuery { r.regexp.queries = append(r.regexp.queries, rr) } else { r.regexp.path = rr @@ -234,7 +263,8 @@ func (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool { // "X-Requested-With", "XMLHttpRequest") // // The above route will only match if both the request header matches both regular expressions. -// It the value is an empty string, it will match any value if the key is set. +// If the value is an empty string, it will match any value if the key is set. +// Use the start and end of string anchors (^ and $) to match an exact value. func (r *Route) HeadersRegexp(pairs ...string) *Route { if r.err == nil { var headers map[string]*regexp.Regexp @@ -264,7 +294,7 @@ func (r *Route) HeadersRegexp(pairs ...string) *Route { // Variable names must be unique in a given route. They can be retrieved // calling mux.Vars(request). func (r *Route) Host(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, true, false, false) + r.err = r.addRegexpMatcher(tpl, regexpTypeHost) return r } @@ -324,7 +354,7 @@ func (r *Route) Methods(methods ...string) *Route { // Variable names must be unique in a given route. They can be retrieved // calling mux.Vars(request). func (r *Route) Path(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, false, false, false) + r.err = r.addRegexpMatcher(tpl, regexpTypePath) return r } @@ -340,7 +370,7 @@ func (r *Route) Path(tpl string) *Route { // Also note that the setting of Router.StrictSlash() has no effect on routes // with a PathPrefix matcher. func (r *Route) PathPrefix(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, false, true, false) + r.err = r.addRegexpMatcher(tpl, regexpTypePrefix) return r } @@ -371,7 +401,7 @@ func (r *Route) Queries(pairs ...string) *Route { return nil } for i := 0; i < length; i += 2 { - if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], false, false, true); r.err != nil { + if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], regexpTypeQuery); r.err != nil { return r } } @@ -394,6 +424,9 @@ func (r *Route) Schemes(schemes ...string) *Route { for k, v := range schemes { schemes[k] = strings.ToLower(v) } + if r.buildScheme == "" && len(schemes) > 0 { + r.buildScheme = schemes[0] + } return r.addMatcher(schemeMatcher(schemes)) } @@ -477,22 +510,33 @@ func (r *Route) URL(pairs ...string) (*url.URL, error) { return nil, err } var scheme, host, path string + queries := make([]string, 0, len(r.regexp.queries)) if r.regexp.host != nil { - // Set a default scheme. - scheme = "http" if host, err = r.regexp.host.url(values); err != nil { return nil, err } + scheme = "http" + if s := r.getBuildScheme(); s != "" { + scheme = s + } } if r.regexp.path != nil { if path, err = r.regexp.path.url(values); err != nil { return nil, err } } + for _, q := range r.regexp.queries { + var query string + if query, err = q.url(values); err != nil { + return nil, err + } + queries = append(queries, query) + } return &url.URL{ - Scheme: scheme, - Host: host, - Path: path, + Scheme: scheme, + Host: host, + Path: path, + RawQuery: strings.Join(queries, "&"), }, nil } @@ -514,10 +558,14 @@ func (r *Route) URLHost(pairs ...string) (*url.URL, error) { if err != nil { return nil, err } - return &url.URL{ + u := &url.URL{ Scheme: "http", Host: host, - }, nil + } + if s := r.getBuildScheme(); s != "" { + u.Scheme = s + } + return u, nil } // URLPath builds the path part of the URL for a route. See Route.URL(). @@ -558,6 +606,74 @@ func (r *Route) GetPathTemplate() (string, error) { return r.regexp.path.template, nil } +// GetPathRegexp returns the expanded regular expression used to match route path. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not define a path. +func (r *Route) GetPathRegexp() (string, error) { + if r.err != nil { + return "", r.err + } + if r.regexp == nil || r.regexp.path == nil { + return "", errors.New("mux: route does not have a path") + } + return r.regexp.path.regexp.String(), nil +} + +// GetQueriesRegexp returns the expanded regular expressions used to match the +// route queries. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not have queries. +func (r *Route) GetQueriesRegexp() ([]string, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp == nil || r.regexp.queries == nil { + return nil, errors.New("mux: route doesn't have queries") + } + var queries []string + for _, query := range r.regexp.queries { + queries = append(queries, query.regexp.String()) + } + return queries, nil +} + +// GetQueriesTemplates returns the templates used to build the +// query matching. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not define queries. +func (r *Route) GetQueriesTemplates() ([]string, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp == nil || r.regexp.queries == nil { + return nil, errors.New("mux: route doesn't have queries") + } + var queries []string + for _, query := range r.regexp.queries { + queries = append(queries, query.template) + } + return queries, nil +} + +// GetMethods returns the methods the route matches against +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if route does not have methods. +func (r *Route) GetMethods() ([]string, error) { + if r.err != nil { + return nil, r.err + } + for _, m := range r.matchers { + if methods, ok := m.(methodMatcher); ok { + return []string(methods), nil + } + } + return nil, errors.New("mux: route doesn't have methods") +} + // GetHostTemplate returns the template used to build the // route match. // This is useful for building simple REST API documentation and for instrumentation @@ -599,11 +715,22 @@ func (r *Route) buildVars(m map[string]string) map[string]string { // parentRoute allows routes to know about parent host and path definitions. type parentRoute interface { + getBuildScheme() string getNamedRoutes() map[string]*Route getRegexpGroup() *routeRegexpGroup buildVars(map[string]string) map[string]string } +func (r *Route) getBuildScheme() string { + if r.buildScheme != "" { + return r.buildScheme + } + if r.parent != nil { + return r.parent.getBuildScheme() + } + return "" +} + // getNamedRoutes returns the map where named routes are registered. func (r *Route) getNamedRoutes() map[string]*Route { if r.parent == nil { diff --git a/vendor/github.com/gorilla/mux/test_helpers.go b/vendor/github.com/gorilla/mux/test_helpers.go new file mode 100644 index 0000000000..32ecffde48 --- /dev/null +++ b/vendor/github.com/gorilla/mux/test_helpers.go @@ -0,0 +1,19 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mux + +import "net/http" + +// SetURLVars sets the URL variables for the given request, to be accessed via +// mux.Vars for testing route behaviour. Arguments are not modified, a shallow +// copy is returned. +// +// This API should only be used for testing purposes; it provides a way to +// inject variables into the request context. Alternatively, URL variables +// can be set by making a route that captures the required variables, +// starting a server and sending the request to that server. +func SetURLVars(r *http.Request, val map[string]string) *http.Request { + return setVars(r, val) +} diff --git a/vendor/github.com/gorilla/securecookie/.travis.yml b/vendor/github.com/gorilla/securecookie/.travis.yml new file mode 100644 index 0000000000..6f440f1e42 --- /dev/null +++ b/vendor/github.com/gorilla/securecookie/.travis.yml @@ -0,0 +1,19 @@ +language: go +sudo: false + +matrix: + include: + - go: 1.3 + - go: 1.4 + - go: 1.5 + - go: 1.6 + - go: 1.7 + - go: tip + allow_failures: + - go: tip + +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d .) + - go vet $(go list ./... | grep -v /vendor/) + - go test -v -race ./... diff --git a/vendor/github.com/gorilla/securecookie/README.md b/vendor/github.com/gorilla/securecookie/README.md new file mode 100644 index 0000000000..aa7bd1a5b2 --- /dev/null +++ b/vendor/github.com/gorilla/securecookie/README.md @@ -0,0 +1,80 @@ +securecookie +============ +[![GoDoc](https://godoc.org/github.com/gorilla/securecookie?status.svg)](https://godoc.org/github.com/gorilla/securecookie) [![Build Status](https://travis-ci.org/gorilla/securecookie.png?branch=master)](https://travis-ci.org/gorilla/securecookie) +[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/securecookie/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/securecookie?badge) + + +securecookie encodes and decodes authenticated and optionally encrypted +cookie values. + +Secure cookies can't be forged, because their values are validated using HMAC. +When encrypted, the content is also inaccessible to malicious eyes. It is still +recommended that sensitive data not be stored in cookies, and that HTTPS be used +to prevent cookie [replay attacks](https://en.wikipedia.org/wiki/Replay_attack). + +## Examples + +To use it, first create a new SecureCookie instance: + +```go +// Hash keys should be at least 32 bytes long +var hashKey = []byte("very-secret") +// Block keys should be 16 bytes (AES-128) or 32 bytes (AES-256) long. +// Shorter keys may weaken the encryption used. +var blockKey = []byte("a-lot-secret") +var s = securecookie.New(hashKey, blockKey) +``` + +The hashKey is required, used to authenticate the cookie value using HMAC. +It is recommended to use a key with 32 or 64 bytes. + +The blockKey is optional, used to encrypt the cookie value -- set it to nil +to not use encryption. If set, the length must correspond to the block size +of the encryption algorithm. For AES, used by default, valid lengths are +16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. + +Strong keys can be created using the convenience function GenerateRandomKey(). + +Once a SecureCookie instance is set, use it to encode a cookie value: + +```go +func SetCookieHandler(w http.ResponseWriter, r *http.Request) { + value := map[string]string{ + "foo": "bar", + } + if encoded, err := s.Encode("cookie-name", value); err == nil { + cookie := &http.Cookie{ + Name: "cookie-name", + Value: encoded, + Path: "/", + Secure: true, + HttpOnly: true, + } + http.SetCookie(w, cookie) + } +} +``` + +Later, use the same SecureCookie instance to decode and validate a cookie +value: + +```go +func ReadCookieHandler(w http.ResponseWriter, r *http.Request) { + if cookie, err := r.Cookie("cookie-name"); err == nil { + value := make(map[string]string) + if err = s2.Decode("cookie-name", cookie.Value, &value); err == nil { + fmt.Fprintf(w, "The value of foo is %q", value["foo"]) + } + } +} +``` + +We stored a map[string]string, but secure cookies can hold any value that +can be encoded using `encoding/gob`. To store custom types, they must be +registered first using gob.Register(). For basic types this is not needed; +it works out of the box. An optional JSON encoder that uses `encoding/json` is +available for types compatible with JSON. + +## License + +BSD licensed. See the LICENSE file for details. diff --git a/vendor/github.com/gorilla/sessions/.travis.yml b/vendor/github.com/gorilla/sessions/.travis.yml new file mode 100644 index 0000000000..db17dd3eb6 --- /dev/null +++ b/vendor/github.com/gorilla/sessions/.travis.yml @@ -0,0 +1,22 @@ +language: go +sudo: false + +matrix: + include: + - go: 1.3 + - go: 1.4 + - go: 1.5 + - go: 1.6 + - go: 1.7 + - go: tip + allow_failures: + - go: tip + +install: + - # skip + +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d .) + - go vet $(go list ./... | grep -v /vendor/) + - go test -v -race ./... diff --git a/vendor/github.com/gorilla/sessions/AUTHORS b/vendor/github.com/gorilla/sessions/AUTHORS new file mode 100644 index 0000000000..1e3e7acb62 --- /dev/null +++ b/vendor/github.com/gorilla/sessions/AUTHORS @@ -0,0 +1,43 @@ +# This is the official list of gorilla/sessions authors for copyright purposes. +# +# Please keep the list sorted. + +Ahmadreza Zibaei +Anton Lindström +Brian Jones +Collin Stedman +Deniz Eren +Dmitry Chestnykh +Dustin Oprea +Egon Elbre +enumappstore +Geofrey Ernest +Google LLC (https://opensource.google.com/) +Jerry Saravia +Jonathan Gillham +Justin Clift +Justin Hellings +Kamil Kisiel +Keiji Yoshida +kliron +Kshitij Saraogi +Lauris BH +Lukas Rist +Mark Dain +Matt Ho +Matt Silverlock +Mattias Wadman +Michael Schuett +Michael Stapelberg +Mirco Zeiss +moraes +nvcnvn +pappz +Pontus Leitzler +QuaSoft +rcadena +rodrigo moraes +Shawn Smith +Taylor Hurt +Tortuoise +Vitor De Mario diff --git a/vendor/github.com/gorilla/sessions/LICENSE b/vendor/github.com/gorilla/sessions/LICENSE index 0e5fb87280..6903df6386 100644 --- a/vendor/github.com/gorilla/sessions/LICENSE +++ b/vendor/github.com/gorilla/sessions/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. +Copyright (c) 2012-2018 The Gorilla Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/vendor/github.com/gorilla/sessions/README.md b/vendor/github.com/gorilla/sessions/README.md new file mode 100644 index 0000000000..c9e0e92c7d --- /dev/null +++ b/vendor/github.com/gorilla/sessions/README.md @@ -0,0 +1,92 @@ +sessions +======== +[![GoDoc](https://godoc.org/github.com/gorilla/sessions?status.svg)](https://godoc.org/github.com/gorilla/sessions) [![Build Status](https://travis-ci.org/gorilla/sessions.svg?branch=master)](https://travis-ci.org/gorilla/sessions) +[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/sessions/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/sessions?badge) + + +gorilla/sessions provides cookie and filesystem sessions and infrastructure for +custom session backends. + +The key features are: + +* Simple API: use it as an easy way to set signed (and optionally + encrypted) cookies. +* Built-in backends to store sessions in cookies or the filesystem. +* Flash messages: session values that last until read. +* Convenient way to switch session persistency (aka "remember me") and set + other attributes. +* Mechanism to rotate authentication and encryption keys. +* Multiple sessions per request, even using different backends. +* Interfaces and infrastructure for custom session backends: sessions from + different stores can be retrieved and batch-saved using a common API. + +Let's start with an example that shows the sessions API in a nutshell: + +```go + import ( + "net/http" + "github.com/gorilla/sessions" + ) + + var store = sessions.NewCookieStore([]byte("something-very-secret")) + + func MyHandler(w http.ResponseWriter, r *http.Request) { + // Get a session. We're ignoring the error resulted from decoding an + // existing session: Get() always returns a session, even if empty. + session, _ := store.Get(r, "session-name") + // Set some session values. + session.Values["foo"] = "bar" + session.Values[42] = 43 + // Save it before we write to the response/return from the handler. + session.Save(r, w) + } +``` + +First we initialize a session store calling `NewCookieStore()` and passing a +secret key used to authenticate the session. Inside the handler, we call +`store.Get()` to retrieve an existing session or create a new one. Then we set +some session values in session.Values, which is a `map[interface{}]interface{}`. +And finally we call `session.Save()` to save the session in the response. + +Important Note: If you aren't using gorilla/mux, you need to wrap your handlers +with +[`context.ClearHandler`](http://www.gorillatoolkit.org/pkg/context#ClearHandler) +or else you will leak memory! An easy way to do this is to wrap the top-level +mux when calling http.ListenAndServe: + +```go + http.ListenAndServe(":8080", context.ClearHandler(http.DefaultServeMux)) +``` + +The ClearHandler function is provided by the gorilla/context package. + +More examples are available [on the Gorilla +website](http://www.gorillatoolkit.org/pkg/sessions). + +## Store Implementations + +Other implementations of the `sessions.Store` interface: + +* [github.com/starJammer/gorilla-sessions-arangodb](https://github.com/starJammer/gorilla-sessions-arangodb) - ArangoDB +* [github.com/yosssi/boltstore](https://github.com/yosssi/boltstore) - Bolt +* [github.com/srinathgs/couchbasestore](https://github.com/srinathgs/couchbasestore) - Couchbase +* [github.com/denizeren/dynamostore](https://github.com/denizeren/dynamostore) - Dynamodb on AWS +* [github.com/savaki/dynastore](https://github.com/savaki/dynastore) - DynamoDB on AWS (Official AWS library) +* [github.com/bradleypeabody/gorilla-sessions-memcache](https://github.com/bradleypeabody/gorilla-sessions-memcache) - Memcache +* [github.com/dsoprea/go-appengine-sessioncascade](https://github.com/dsoprea/go-appengine-sessioncascade) - Memcache/Datastore/Context in AppEngine +* [github.com/kidstuff/mongostore](https://github.com/kidstuff/mongostore) - MongoDB +* [github.com/srinathgs/mysqlstore](https://github.com/srinathgs/mysqlstore) - MySQL +* [github.com/EnumApps/clustersqlstore](https://github.com/EnumApps/clustersqlstore) - MySQL Cluster +* [github.com/antonlindstrom/pgstore](https://github.com/antonlindstrom/pgstore) - PostgreSQL +* [github.com/boj/redistore](https://github.com/boj/redistore) - Redis +* [github.com/boj/rethinkstore](https://github.com/boj/rethinkstore) - RethinkDB +* [github.com/boj/riakstore](https://github.com/boj/riakstore) - Riak +* [github.com/michaeljs1990/sqlitestore](https://github.com/michaeljs1990/sqlitestore) - SQLite +* [github.com/wader/gormstore](https://github.com/wader/gormstore) - GORM (MySQL, PostgreSQL, SQLite) +* [github.com/gernest/qlstore](https://github.com/gernest/qlstore) - ql +* [github.com/quasoft/memstore](https://github.com/quasoft/memstore) - In-memory implementation for use in unit tests +* [github.com/lafriks/xormstore](https://github.com/lafriks/xormstore) - XORM (MySQL, PostgreSQL, SQLite, Microsoft SQL Server, TiDB) + +## License + +BSD licensed. See the LICENSE file for details. diff --git a/vendor/github.com/gorilla/sessions/doc.go b/vendor/github.com/gorilla/sessions/doc.go index 668e05e455..57a5291773 100644 --- a/vendor/github.com/gorilla/sessions/doc.go +++ b/vendor/github.com/gorilla/sessions/doc.go @@ -29,8 +29,7 @@ Let's start with an example that shows the sessions API in a nutshell: var store = sessions.NewCookieStore([]byte("something-very-secret")) func MyHandler(w http.ResponseWriter, r *http.Request) { - // Get a session. We're ignoring the error resulted from decoding an - // existing session: Get() always returns a session, even if empty. + // Get a session. Get() always returns a session, even if empty. session, err := store.Get(r, "session-name") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -80,7 +79,7 @@ flashes, call session.Flashes(). Here is an example: return } - // Get the previously flashes, if any. + // Get the previous flashes, if any. if flashes := session.Flashes(); len(flashes) > 0 { // Use the flash values. } else { diff --git a/vendor/github.com/gorilla/sessions/go.mod b/vendor/github.com/gorilla/sessions/go.mod new file mode 100644 index 0000000000..44befd42cc --- /dev/null +++ b/vendor/github.com/gorilla/sessions/go.mod @@ -0,0 +1,6 @@ +module "github.com/gorilla/sessions" + +require ( + "github.com/gorilla/context" v1.1.1 + "github.com/gorilla/securecookie" v1.1.1 +) diff --git a/vendor/github.com/gorilla/sessions/sessions.go b/vendor/github.com/gorilla/sessions/sessions.go index fe0d2bc8fa..9870e31019 100644 --- a/vendor/github.com/gorilla/sessions/sessions.go +++ b/vendor/github.com/gorilla/sessions/sessions.go @@ -24,8 +24,9 @@ const flashesKey = "_flash" type Options struct { Path string Domain string - // MaxAge=0 means no 'Max-Age' attribute specified. - // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'. + // MaxAge=0 means no Max-Age attribute specified and the cookie will be + // deleted after the browser session ends. + // MaxAge<0 means delete cookie immediately. // MaxAge>0 means Max-Age attribute present and given in seconds. MaxAge int Secure bool @@ -37,9 +38,10 @@ type Options struct { // NewSession is called by session stores to create a new session instance. func NewSession(store Store, name string) *Session { return &Session{ - Values: make(map[interface{}]interface{}), - store: store, - name: name, + Values: make(map[interface{}]interface{}), + store: store, + name: name, + Options: new(Options), } } diff --git a/vendor/github.com/issue9/identicon/.gitignore b/vendor/github.com/issue9/identicon/.gitignore new file mode 100644 index 0000000000..295f20bf38 --- /dev/null +++ b/vendor/github.com/issue9/identicon/.gitignore @@ -0,0 +1,32 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +#vim +*.swp + +#osx +.DS_Store + +testdata diff --git a/vendor/github.com/issue9/identicon/.travis.yml b/vendor/github.com/issue9/identicon/.travis.yml new file mode 100644 index 0000000000..e990b1f23d --- /dev/null +++ b/vendor/github.com/issue9/identicon/.travis.yml @@ -0,0 +1,10 @@ +language: go +go: + - tip + - 1.6 + - 1.5 + - 1.4 + - 1.3 +install: + - go get github.com/issue9/assert + - mkdir ./testdata diff --git a/vendor/github.com/issue9/identicon/README.md b/vendor/github.com/issue9/identicon/README.md new file mode 100644 index 0000000000..a68c73bc4e --- /dev/null +++ b/vendor/github.com/issue9/identicon/README.md @@ -0,0 +1,40 @@ +identicon [![Build Status](https://travis-ci.org/issue9/identicon.svg?branch=master)](https://travis-ci.org/issue9/identicon) +====== + +根据用户的IP、邮箱名等任意数据为用户产生漂亮的随机头像。 + +![screenhost.1](https://raw.github.com/issue9/identicon/master/screenshot/1.png) +![screenhost.4](https://raw.github.com/issue9/identicon/master/screenshot/4.png) +![screenhost.5](https://raw.github.com/issue9/identicon/master/screenshot/5.png) +![screenhost.6](https://raw.github.com/issue9/identicon/master/screenshot/6.png) +![screenhost.7](https://raw.github.com/issue9/identicon/master/screenshot/7.png) + +```go +// 根据用户访问的IP,为其生成一张头像 +img, _ := identicon.Make(128, color.NRGBA{},color.NRGBA{}, []byte("192.168.1.1")) +fi, _ := os.Create("/tmp/u1.png") +png.Encode(fi, img) +fi.Close() + +// 或者 +ii, _ := identicon.New(128, color.NRGBA{}, color.NRGBA{}, color.NRGBA{}, color.NRGBA{}) +img := ii.Make([]byte("192.168.1.1")) +img = ii.Make([]byte("192.168.1.2")) +``` + +### 安装 + +```shell +go get github.com/issue9/identicon +``` + + +### 文档 + +[![Go Walker](http://gowalker.org/api/v1/badge)](http://gowalker.org/github.com/issue9/identicon) +[![GoDoc](https://godoc.org/github.com/issue9/identicon?status.svg)](https://godoc.org/github.com/issue9/identicon) + + +### 版权 + +本项目采用[MIT](http://opensource.org/licenses/MIT)开源授权许可证,完整的授权说明可在[LICENSE](LICENSE)文件中找到。 diff --git a/vendor/github.com/jaytaylor/html2text/.gitignore b/vendor/github.com/jaytaylor/html2text/.gitignore new file mode 100644 index 0000000000..daf913b1b3 --- /dev/null +++ b/vendor/github.com/jaytaylor/html2text/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/jaytaylor/html2text/.travis.yml b/vendor/github.com/jaytaylor/html2text/.travis.yml new file mode 100644 index 0000000000..6f150c2dc8 --- /dev/null +++ b/vendor/github.com/jaytaylor/html2text/.travis.yml @@ -0,0 +1,13 @@ +language: go +go: + - tip + - 1.7 + - 1.6 + - 1.5 + - 1.4 + - 1.3 + - 1.2 +notifications: + email: + on_success: change + on_failure: always diff --git a/vendor/github.com/jaytaylor/html2text/README.md b/vendor/github.com/jaytaylor/html2text/README.md new file mode 100644 index 0000000000..6e67dbcc6a --- /dev/null +++ b/vendor/github.com/jaytaylor/html2text/README.md @@ -0,0 +1,112 @@ +# html2text + +[![Documentation](https://godoc.org/github.com/jaytaylor/html2text?status.svg)](https://godoc.org/github.com/jaytaylor/html2text) +[![Build Status](https://travis-ci.org/jaytaylor/html2text.svg?branch=master)](https://travis-ci.org/jaytaylor/html2text) +[![Report Card](https://goreportcard.com/badge/github.com/jaytaylor/html2text)](https://goreportcard.com/report/github.com/jaytaylor/html2text) + +### Converts HTML into text + + +## Introduction + +html2text is a simple golang package for rendering HTML into plaintext. + +There are still lots of improvements to be had, but FWIW this has worked fine for my [basic] HTML-2-text needs. + +It requires go 1.x or newer ;) + + +## Download the package + +```bash +go get github.com/jaytaylor/html2text +``` + +## Example usage + +```go +package main + +import ( + "fmt" + + "github.com/jaytaylor/html2text" +) + +func main() { + inputHtml := ` + + + My Mega Service + + + + + + + +

Welcome to your new account on my service!

+ +

+ Here is some more information: + +

+

+ + + ` + + text, err := html2text.FromString(inputHtml) + if err != nil { + panic(err) + } + fmt.Println(text) +} +``` + +Output: +``` +Mega Service ( http://mymegaservice.com/ ) + +****************************************** +Welcome to your new account on my service! +****************************************** + +Here is some more information: + +* Link 1: Example.com ( https://example.com ) +* Link 2: Example2.com ( https://example2.com ) +* Something else +``` + + +## Unit-tests + +Running the unit-tests is straightforward and standard: + +```bash +go test +``` + + +# License + +Permissive MIT license. + + +## Contact + +You are more than welcome to open issues and send pull requests if you find a bug or want a new feature. + +If you appreciate this library please feel free to drop me a line and tell me! It's always nice to hear from people who have benefitted from my work. + +Email: jay at (my github username).com + +Twitter: [@jtaylor](https://twitter.com/jtaylor) + diff --git a/vendor/github.com/kballard/go-shellquote/README b/vendor/github.com/kballard/go-shellquote/README new file mode 100644 index 0000000000..4d34e87afc --- /dev/null +++ b/vendor/github.com/kballard/go-shellquote/README @@ -0,0 +1,36 @@ +PACKAGE + +package shellquote + import "github.com/kballard/go-shellquote" + + Shellquote provides utilities for joining/splitting strings using sh's + word-splitting rules. + +VARIABLES + +var ( + UnterminatedSingleQuoteError = errors.New("Unterminated single-quoted string") + UnterminatedDoubleQuoteError = errors.New("Unterminated double-quoted string") + UnterminatedEscapeError = errors.New("Unterminated backslash-escape") +) + + +FUNCTIONS + +func Join(args ...string) string + Join quotes each argument and joins them with a space. If passed to + /bin/sh, the resulting string will be split back into the original + arguments. + +func Split(input string) (words []string, err error) + Split splits a string according to /bin/sh's word-splitting rules. It + supports backslash-escapes, single-quotes, and double-quotes. Notably it + does not support the $'' style of quoting. It also doesn't attempt to + perform any other sort of expansion, including brace expansion, shell + expansion, or pathname expansion. + + If the given input has an unterminated quoted string or ends in a + backslash-escape, one of UnterminatedSingleQuoteError, + UnterminatedDoubleQuoteError, or UnterminatedEscapeError is returned. + + diff --git a/vendor/github.com/kevinburke/ssh_config/.gitattributes b/vendor/github.com/kevinburke/ssh_config/.gitattributes new file mode 100644 index 0000000000..44db581889 --- /dev/null +++ b/vendor/github.com/kevinburke/ssh_config/.gitattributes @@ -0,0 +1 @@ +testdata/dos-lines eol=crlf diff --git a/vendor/github.com/kevinburke/ssh_config/.gitignore b/vendor/github.com/kevinburke/ssh_config/.gitignore new file mode 100644 index 0000000000..a6ef824c1f --- /dev/null +++ b/vendor/github.com/kevinburke/ssh_config/.gitignore @@ -0,0 +1 @@ +/bazel-* diff --git a/vendor/github.com/kevinburke/ssh_config/.travis.yml b/vendor/github.com/kevinburke/ssh_config/.travis.yml new file mode 100644 index 0000000000..8b5964dd52 --- /dev/null +++ b/vendor/github.com/kevinburke/ssh_config/.travis.yml @@ -0,0 +1,15 @@ +go_import_path: github.com/kevinburke/ssh_config + +language: go + +go: + - 1.9.x + - 1.10.x + - 1.11.x + - master + +before_script: + - go get -u ./... + +script: + - make race-test diff --git a/vendor/github.com/kevinburke/ssh_config/Makefile b/vendor/github.com/kevinburke/ssh_config/Makefile new file mode 100644 index 0000000000..90c3a28616 --- /dev/null +++ b/vendor/github.com/kevinburke/ssh_config/Makefile @@ -0,0 +1,32 @@ +BUMP_VERSION := $(GOPATH)/bin/bump_version +MEGACHECK := $(GOPATH)/bin/megacheck +WRITE_MAILMAP := $(GOPATH)/bin/write_mailmap + +IGNORES := 'github.com/kevinburke/ssh_config/config.go:U1000 github.com/kevinburke/ssh_config/config.go:S1002 github.com/kevinburke/ssh_config/token.go:U1000' + +$(MEGACHECK): + go get honnef.co/go/tools/cmd/megacheck + +lint: $(MEGACHECK) + go vet ./... + $(MEGACHECK) --ignore=$(IGNORES) ./... + +test: lint + @# the timeout helps guard against infinite recursion + go test -timeout=250ms ./... + +race-test: lint + go test -timeout=500ms -race ./... + +$(BUMP_VERSION): + go get -u github.com/kevinburke/bump_version + +release: test | $(BUMP_VERSION) + $(BUMP_VERSION) minor config.go + +force: ; + +AUTHORS.txt: force | $(WRITE_MAILMAP) + $(WRITE_MAILMAP) > AUTHORS.txt + +authors: AUTHORS.txt diff --git a/vendor/github.com/kevinburke/ssh_config/README.md b/vendor/github.com/kevinburke/ssh_config/README.md new file mode 100644 index 0000000000..52cc1eac4d --- /dev/null +++ b/vendor/github.com/kevinburke/ssh_config/README.md @@ -0,0 +1,81 @@ +# ssh_config + +This is a Go parser for `ssh_config` files. Importantly, this parser attempts +to preserve comments in a given file, so you can manipulate a `ssh_config` file +from a program, if your heart desires. + +It's designed to be used with the excellent +[x/crypto/ssh](https://golang.org/x/crypto/ssh) package, which handles SSH +negotiation but isn't very easy to configure. + +The `ssh_config` `Get()` and `GetStrict()` functions will attempt to read values +from `$HOME/.ssh/config` and fall back to `/etc/ssh/ssh_config`. The first +argument is the host name to match on, and the second argument is the key you +want to retrieve. + +```go +port := ssh_config.Get("myhost", "Port") +``` + +You can also load a config file and read values from it. + +```go +var config = ` +Host *.test + Compression yes +` + +cfg, err := ssh_config.Decode(strings.NewReader(config)) +fmt.Println(cfg.Get("example.test", "Port")) +``` + +Some SSH arguments have default values - for example, the default value for +`KeyboardAuthentication` is `"yes"`. If you call Get(), and no value for the +given Host/keyword pair exists in the config, we'll return a default for the +keyword if one exists. + +### Manipulating SSH config files + +Here's how you can manipulate an SSH config file, and then write it back to +disk. + +```go +f, _ := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "config")) +cfg, _ := ssh_config.Decode(f) +for _, host := range cfg.Hosts { + fmt.Println("patterns:", host.Patterns) + for _, node := range host.Nodes { + // Manipulate the nodes as you see fit, or use a type switch to + // distinguish between Empty, KV, and Include nodes. + fmt.Println(node.String()) + } +} + +// Print the config to stdout: +fmt.Println(cfg.String()) +``` + +## Spec compliance + +Wherever possible we try to implement the specification as documented in +the `ssh_config` manpage. Unimplemented features should be present in the +[issues][issues] list. + +Notably, the `Match` directive is currently unsupported. + +[issues]: https://github.com/kevinburke/ssh_config/issues + +## Errata + +This is the second [comment-preserving configuration parser][blog] I've written, after +[an /etc/hosts parser][hostsfile]. Eventually, I will write one for every Linux +file format. + +[blog]: https://kev.inburke.com/kevin/more-comment-preserving-configuration-parsers/ +[hostsfile]: https://github.com/kevinburke/hostsfile + +## Donating + +Donations free up time to make improvements to the library, and respond to +bug reports. You can send donations via Paypal's "Send Money" feature to +kev@inburke.com. Donations are not tax deductible in the USA. diff --git a/vendor/github.com/keybase/go-crypto/openpgp/patch.sh b/vendor/github.com/keybase/go-crypto/openpgp/patch.sh new file mode 100644 index 0000000000..23cacc83d9 --- /dev/null +++ b/vendor/github.com/keybase/go-crypto/openpgp/patch.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +patch < sig-v3.patch +patch < s2k-gnu-dummy.patch +find . -type f -name '*.go' -exec sed -i'' -e 's/golang.org\/x\/crypto\/openpgp/github.com\/keybase\/go-crypto\/openpgp/' {} \; +find . -type f -name '*.go-e' -exec rm {} \; +go test ./... diff --git a/vendor/github.com/keybase/go-crypto/openpgp/sig-v3.patch b/vendor/github.com/keybase/go-crypto/openpgp/sig-v3.patch new file mode 100644 index 0000000000..bfd764afe0 --- /dev/null +++ b/vendor/github.com/keybase/go-crypto/openpgp/sig-v3.patch @@ -0,0 +1,135 @@ +diff --git a/openpgp/read.go b/openpgp/read.go +index a6cecc5..0c9397b 100644 +--- a/openpgp/read.go ++++ b/openpgp/read.go +@@ -56,8 +56,9 @@ type MessageDetails struct { + // been consumed. Once EOF has been seen, the following fields are + // valid. (An authentication code failure is reported as a + // SignatureError error when reading from UnverifiedBody.) +- SignatureError error // nil if the signature is good. +- Signature *packet.Signature // the signature packet itself. ++ SignatureError error // nil if the signature is good. ++ Signature *packet.Signature // the signature packet itself, if v4 (default) ++ SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature + + decrypted io.ReadCloser + } +@@ -334,13 +335,15 @@ func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) { + } + + var ok bool +- if scr.md.Signature, ok = p.(*packet.Signature); !ok { ++ if scr.md.Signature, ok = p.(*packet.Signature); ok { ++ scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) ++ } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok { ++ scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3) ++ } else { + scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature") + return + } + +- scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) +- + // The SymmetricallyEncrypted packet, if any, might have an + // unsigned hash of its own. In order to check this we need to + // close that Reader. +diff --git a/openpgp/read_test.go b/openpgp/read_test.go +index 52f942c..abe8d7b 100644 +--- a/openpgp/read_test.go ++++ b/openpgp/read_test.go +@@ -13,6 +13,7 @@ import ( + "strings" + "testing" + ++ "golang.org/x/crypto/openpgp/armor" + "golang.org/x/crypto/openpgp/errors" + ) + +@@ -411,6 +412,50 @@ func TestIssue11504(t *testing.T) { + testReadMessageError(t, "9303000130303030303030303030983002303030303030030000000130") + } + ++// TestSignatureV3Message tests the verification of V3 signature, generated ++// with a modern V4-style key. Some people have their clients set to generate ++// V3 signatures, so it's useful to be able to verify them. ++func TestSignatureV3Message(t *testing.T) { ++ sig, err := armor.Decode(strings.NewReader(signedMessageV3)) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ key, err := ReadArmoredKeyRing(strings.NewReader(keyV4forVerifyingSignedMessageV3)) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ md, err := ReadMessage(sig.Body, key, nil, nil) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ ++ _, err = ioutil.ReadAll(md.UnverifiedBody) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ ++ // We'll see a sig error here after reading in the UnverifiedBody above, ++ // if there was one to see. ++ if err = md.SignatureError; err != nil { ++ t.Error(err) ++ return ++ } ++ ++ if md.SignatureV3 == nil { ++ t.Errorf("No available signature after checking signature") ++ return ++ } ++ if md.Signature != nil { ++ t.Errorf("Did not expect a signature V4 back") ++ return ++ } ++ return ++} ++ + const testKey1KeyId = 0xA34D7E18C20C31BB + const testKey3KeyId = 0x338934250CCC0360 + +@@ -504,3 +549,36 @@ const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6 + const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101` + + const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000` ++ ++const keyV4forVerifyingSignedMessageV3 = `-----BEGIN PGP PUBLIC KEY BLOCK----- ++Comment: GPGTools - https://gpgtools.org ++ ++mI0EVfxoFQEEAMBIqmbDfYygcvP6Phr1wr1XI41IF7Qixqybs/foBF8qqblD9gIY ++BKpXjnBOtbkcVOJ0nljd3/sQIfH4E0vQwK5/4YRQSI59eKOqd6Fx+fWQOLG+uu6z ++tewpeCj9LLHvibx/Sc7VWRnrznia6ftrXxJ/wHMezSab3tnGC0YPVdGNABEBAAG0 ++JEdvY3J5cHRvIFRlc3QgS2V5IDx0aGVtYXhAZ21haWwuY29tPoi5BBMBCgAjBQJV ++/GgVAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQeXnQmhdGW9PFVAP+ ++K7TU0qX5ArvIONIxh/WAweyOk884c5cE8f+3NOPOOCRGyVy0FId5A7MmD5GOQh4H ++JseOZVEVCqlmngEvtHZb3U1VYtVGE5WZ+6rQhGsMcWP5qaT4soYwMBlSYxgYwQcx ++YhN9qOr292f9j2Y//TTIJmZT4Oa+lMxhWdqTfX+qMgG4jQRV/GgVAQQArhFSiij1 ++b+hT3dnapbEU+23Z1yTu1DfF6zsxQ4XQWEV3eR8v+8mEDDNcz8oyyF56k6UQ3rXi ++UMTIwRDg4V6SbZmaFbZYCOwp/EmXJ3rfhm7z7yzXj2OFN22luuqbyVhuL7LRdB0M ++pxgmjXb4tTvfgKd26x34S+QqUJ7W6uprY4sAEQEAAYifBBgBCgAJBQJV/GgVAhsM ++AAoJEHl50JoXRlvT7y8D/02ckx4OMkKBZo7viyrBw0MLG92i+DC2bs35PooHR6zz ++786mitjOp5z2QWNLBvxC70S0qVfCIz8jKupO1J6rq6Z8CcbLF3qjm6h1omUBf8Nd ++EfXKD2/2HV6zMKVknnKzIEzauh+eCKS2CeJUSSSryap/QLVAjRnckaES/OsEWhNB ++=RZia ++-----END PGP PUBLIC KEY BLOCK----- ++` ++ ++const signedMessageV3 = `-----BEGIN PGP MESSAGE----- ++Comment: GPGTools - https://gpgtools.org ++ ++owGbwMvMwMVYWXlhlrhb9GXG03JJDKF/MtxDMjKLFYAoUaEktbhEITe1uDgxPVWP ++q5NhKjMrWAVcC9evD8z/bF/uWNjqtk/X3y5/38XGRQHm/57rrDRYuGnTw597Xqka ++uM3137/hH3Os+Jf2dc0fXOITKwJvXJvecPVs0ta+Vg7ZO1MLn8w58Xx+6L58mbka ++DGHyU9yTueZE8D+QF/Tz28Y78dqtF56R1VPn9Xw4uJqrWYdd7b3vIZ1V6R4Nh05d ++iT57d/OhWwA= ++=hG7R ++-----END PGP MESSAGE----- ++` diff --git a/vendor/github.com/klauspost/compress/snappy/AUTHORS b/vendor/github.com/klauspost/compress/snappy/AUTHORS deleted file mode 100644 index fd1c6f67b3..0000000000 --- a/vendor/github.com/klauspost/compress/snappy/AUTHORS +++ /dev/null @@ -1,15 +0,0 @@ -# This is the official list of Snappy-Go authors for copyright purposes. -# This file is distinct from the CONTRIBUTORS files. -# See the latter for an explanation. - -# Names should be added to this file as -# Name or Organization -# The email address is not required for organizations. - -# Please keep the list sorted. - -Damian Gryski -Google Inc. -Jan Mercl <0xjnml@gmail.com> -Rodolfo Carvalho -Sebastien Binet diff --git a/vendor/github.com/klauspost/compress/snappy/CONTRIBUTORS b/vendor/github.com/klauspost/compress/snappy/CONTRIBUTORS deleted file mode 100644 index a29b133988..0000000000 --- a/vendor/github.com/klauspost/compress/snappy/CONTRIBUTORS +++ /dev/null @@ -1,37 +0,0 @@ -# This is the official list of people who can contribute -# (and typically have contributed) code to the Snappy-Go repository. -# The AUTHORS file lists the copyright holders; this file -# lists people. For example, Google employees are listed here -# but not in AUTHORS, because Google holds the copyright. -# -# The submission process automatically checks to make sure -# that people submitting code are listed in this file (by email address). -# -# Names should be added to this file only after verifying that -# the individual or the individual's organization has agreed to -# the appropriate Contributor License Agreement, found here: -# -# http://code.google.com/legal/individual-cla-v1.0.html -# http://code.google.com/legal/corporate-cla-v1.0.html -# -# The agreement for individuals can be filled out on the web. -# -# When adding J Random Contributor's name to this file, -# either J's name or J's organization's name should be -# added to the AUTHORS file, depending on whether the -# individual or corporate CLA was used. - -# Names should be added to this file like so: -# Name - -# Please keep the list sorted. - -Damian Gryski -Jan Mercl <0xjnml@gmail.com> -Kai Backman -Marc-Antoine Ruel -Nigel Tao -Rob Pike -Rodolfo Carvalho -Russ Cox -Sebastien Binet diff --git a/vendor/github.com/klauspost/compress/snappy/LICENSE b/vendor/github.com/klauspost/compress/snappy/LICENSE deleted file mode 100644 index 7e69e1a2f6..0000000000 --- a/vendor/github.com/klauspost/compress/snappy/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/klauspost/cpuid/.gitignore b/vendor/github.com/klauspost/cpuid/.gitignore new file mode 100644 index 0000000000..daf913b1b3 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/klauspost/cpuid/.travis.yml b/vendor/github.com/klauspost/cpuid/.travis.yml new file mode 100644 index 0000000000..bde823d8ab --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/.travis.yml @@ -0,0 +1,8 @@ +language: go + +go: + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - tip diff --git a/vendor/github.com/klauspost/cpuid/README.md b/vendor/github.com/klauspost/cpuid/README.md new file mode 100644 index 0000000000..b2b6bee879 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/README.md @@ -0,0 +1,145 @@ +# cpuid +Package cpuid provides information about the CPU running the current program. + +CPU features are detected on startup, and kept for fast access through the life of the application. +Currently x86 / x64 (AMD64) is supported, and no external C (cgo) code is used, which should make the library very easy to use. + +You can access the CPU information by accessing the shared CPU variable of the cpuid library. + +Package home: https://github.com/klauspost/cpuid + +[![GoDoc][1]][2] [![Build Status][3]][4] + +[1]: https://godoc.org/github.com/klauspost/cpuid?status.svg +[2]: https://godoc.org/github.com/klauspost/cpuid +[3]: https://travis-ci.org/klauspost/cpuid.svg +[4]: https://travis-ci.org/klauspost/cpuid + +# features +## CPU Instructions +* **CMOV** (i686 CMOV) +* **NX** (NX (No-Execute) bit) +* **AMD3DNOW** (AMD 3DNOW) +* **AMD3DNOWEXT** (AMD 3DNowExt) +* **MMX** (standard MMX) +* **MMXEXT** (SSE integer functions or AMD MMX ext) +* **SSE** (SSE functions) +* **SSE2** (P4 SSE functions) +* **SSE3** (Prescott SSE3 functions) +* **SSSE3** (Conroe SSSE3 functions) +* **SSE4** (Penryn SSE4.1 functions) +* **SSE4A** (AMD Barcelona microarchitecture SSE4a instructions) +* **SSE42** (Nehalem SSE4.2 functions) +* **AVX** (AVX functions) +* **AVX2** (AVX2 functions) +* **FMA3** (Intel FMA 3) +* **FMA4** (Bulldozer FMA4 functions) +* **XOP** (Bulldozer XOP functions) +* **F16C** (Half-precision floating-point conversion) +* **BMI1** (Bit Manipulation Instruction Set 1) +* **BMI2** (Bit Manipulation Instruction Set 2) +* **TBM** (AMD Trailing Bit Manipulation) +* **LZCNT** (LZCNT instruction) +* **POPCNT** (POPCNT instruction) +* **AESNI** (Advanced Encryption Standard New Instructions) +* **CLMUL** (Carry-less Multiplication) +* **HTT** (Hyperthreading (enabled)) +* **HLE** (Hardware Lock Elision) +* **RTM** (Restricted Transactional Memory) +* **RDRAND** (RDRAND instruction is available) +* **RDSEED** (RDSEED instruction is available) +* **ADX** (Intel ADX (Multi-Precision Add-Carry Instruction Extensions)) +* **SHA** (Intel SHA Extensions) +* **AVX512F** (AVX-512 Foundation) +* **AVX512DQ** (AVX-512 Doubleword and Quadword Instructions) +* **AVX512IFMA** (AVX-512 Integer Fused Multiply-Add Instructions) +* **AVX512PF** (AVX-512 Prefetch Instructions) +* **AVX512ER** (AVX-512 Exponential and Reciprocal Instructions) +* **AVX512CD** (AVX-512 Conflict Detection Instructions) +* **AVX512BW** (AVX-512 Byte and Word Instructions) +* **AVX512VL** (AVX-512 Vector Length Extensions) +* **AVX512VBMI** (AVX-512 Vector Bit Manipulation Instructions) +* **MPX** (Intel MPX (Memory Protection Extensions)) +* **ERMS** (Enhanced REP MOVSB/STOSB) +* **RDTSCP** (RDTSCP Instruction) +* **CX16** (CMPXCHG16B Instruction) +* **SGX** (Software Guard Extensions, with activation details) + +## Performance +* **RDTSCP()** Returns current cycle count. Can be used for benchmarking. +* **SSE2SLOW** (SSE2 is supported, but usually not faster) +* **SSE3SLOW** (SSE3 is supported, but usually not faster) +* **ATOM** (Atom processor, some SSSE3 instructions are slower) +* **Cache line** (Probable size of a cache line). +* **L1, L2, L3 Cache size** on newer Intel/AMD CPUs. + +## Cpu Vendor/VM +* **Intel** +* **AMD** +* **VIA** +* **Transmeta** +* **NSC** +* **KVM** (Kernel-based Virtual Machine) +* **MSVM** (Microsoft Hyper-V or Windows Virtual PC) +* **VMware** +* **XenHVM** + +# installing + +```go get github.com/klauspost/cpuid``` + +# example + +```Go +package main + +import ( + "fmt" + "github.com/klauspost/cpuid" +) + +func main() { + // Print basic CPU information: + fmt.Println("Name:", cpuid.CPU.BrandName) + fmt.Println("PhysicalCores:", cpuid.CPU.PhysicalCores) + fmt.Println("ThreadsPerCore:", cpuid.CPU.ThreadsPerCore) + fmt.Println("LogicalCores:", cpuid.CPU.LogicalCores) + fmt.Println("Family", cpuid.CPU.Family, "Model:", cpuid.CPU.Model) + fmt.Println("Features:", cpuid.CPU.Features) + fmt.Println("Cacheline bytes:", cpuid.CPU.CacheLine) + fmt.Println("L1 Data Cache:", cpuid.CPU.Cache.L1D, "bytes") + fmt.Println("L1 Instruction Cache:", cpuid.CPU.Cache.L1D, "bytes") + fmt.Println("L2 Cache:", cpuid.CPU.Cache.L2, "bytes") + fmt.Println("L3 Cache:", cpuid.CPU.Cache.L3, "bytes") + + // Test if we have a specific feature: + if cpuid.CPU.SSE() { + fmt.Println("We have Streaming SIMD Extensions") + } +} +``` + +Sample output: +``` +>go run main.go +Name: Intel(R) Core(TM) i5-2540M CPU @ 2.60GHz +PhysicalCores: 2 +ThreadsPerCore: 2 +LogicalCores: 4 +Family 6 Model: 42 +Features: CMOV,MMX,MMXEXT,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,AVX,AESNI,CLMUL +Cacheline bytes: 64 +We have Streaming SIMD Extensions +``` + +# private package + +In the "private" folder you can find an autogenerated version of the library you can include in your own packages. + +For this purpose all exports are removed, and functions and constants are lowercased. + +This is not a recommended way of using the library, but provided for convenience, if it is difficult for you to use external packages. + +# license + +This code is published under an MIT license. See LICENSE file for more information. diff --git a/vendor/github.com/klauspost/crc32/.gitignore b/vendor/github.com/klauspost/crc32/.gitignore new file mode 100644 index 0000000000..daf913b1b3 --- /dev/null +++ b/vendor/github.com/klauspost/crc32/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/klauspost/crc32/.travis.yml b/vendor/github.com/klauspost/crc32/.travis.yml new file mode 100644 index 0000000000..de64ae491f --- /dev/null +++ b/vendor/github.com/klauspost/crc32/.travis.yml @@ -0,0 +1,13 @@ +language: go + +go: + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - 1.7 + - tip + +script: + - go test -v . + - go test -v -race . diff --git a/vendor/github.com/klauspost/crc32/README.md b/vendor/github.com/klauspost/crc32/README.md new file mode 100644 index 0000000000..029625d360 --- /dev/null +++ b/vendor/github.com/klauspost/crc32/README.md @@ -0,0 +1,87 @@ +# crc32 +CRC32 hash with x64 optimizations + +This package is a drop-in replacement for the standard library `hash/crc32` package, that features SSE 4.2 optimizations on x64 platforms, for a 10x speedup. + +[![Build Status](https://travis-ci.org/klauspost/crc32.svg?branch=master)](https://travis-ci.org/klauspost/crc32) + +# usage + +Install using `go get github.com/klauspost/crc32`. This library is based on Go 1.5 code and requires Go 1.3 or newer. + +Replace `import "hash/crc32"` with `import "github.com/klauspost/crc32"` and you are good to go. + +# changes +* Oct 20, 2016: Changes have been merged to upstream Go. Package updated to match. +* Dec 4, 2015: Uses the "slice-by-8" trick more extensively, which gives a 1.5 to 2.5x speedup if assembler is unavailable. + + +# performance + +For *Go 1.7* performance is equivalent to the standard library. So if you use this package for Go 1.7 you can switch back. + + +For IEEE tables (the most common), there is approximately a factor 10 speedup with "CLMUL" (Carryless multiplication) instruction: +``` +benchmark old ns/op new ns/op delta +BenchmarkCrc32KB 99955 10258 -89.74% + +benchmark old MB/s new MB/s speedup +BenchmarkCrc32KB 327.83 3194.20 9.74x +``` + +For other tables and "CLMUL" capable machines the performance is the same as the standard library. + +Here are some detailed benchmarks, comparing to go 1.5 standard library with and without assembler enabled. + +``` +Std: Standard Go 1.5 library +Crc: Indicates IEEE type CRC. +40B: Size of each slice encoded. +NoAsm: Assembler was disabled (ie. not an AMD64 or SSE 4.2+ capable machine). +Castagnoli: Castagnoli CRC type. + +BenchmarkStdCrc40B-4 10000000 158 ns/op 252.88 MB/s +BenchmarkCrc40BNoAsm-4 20000000 105 ns/op 377.38 MB/s (slice8) +BenchmarkCrc40B-4 20000000 105 ns/op 378.77 MB/s (slice8) + +BenchmarkStdCrc1KB-4 500000 3604 ns/op 284.10 MB/s +BenchmarkCrc1KBNoAsm-4 1000000 1463 ns/op 699.79 MB/s (slice8) +BenchmarkCrc1KB-4 3000000 396 ns/op 2583.69 MB/s (asm) + +BenchmarkStdCrc8KB-4 200000 11417 ns/op 717.48 MB/s (slice8) +BenchmarkCrc8KBNoAsm-4 200000 11317 ns/op 723.85 MB/s (slice8) +BenchmarkCrc8KB-4 500000 2919 ns/op 2805.73 MB/s (asm) + +BenchmarkStdCrc32KB-4 30000 45749 ns/op 716.24 MB/s (slice8) +BenchmarkCrc32KBNoAsm-4 30000 45109 ns/op 726.42 MB/s (slice8) +BenchmarkCrc32KB-4 100000 11497 ns/op 2850.09 MB/s (asm) + +BenchmarkStdNoAsmCastagnol40B-4 10000000 161 ns/op 246.94 MB/s +BenchmarkStdCastagnoli40B-4 50000000 28.4 ns/op 1410.69 MB/s (asm) +BenchmarkCastagnoli40BNoAsm-4 20000000 100 ns/op 398.01 MB/s (slice8) +BenchmarkCastagnoli40B-4 50000000 28.2 ns/op 1419.54 MB/s (asm) + +BenchmarkStdNoAsmCastagnoli1KB-4 500000 3622 ns/op 282.67 MB/s +BenchmarkStdCastagnoli1KB-4 10000000 144 ns/op 7099.78 MB/s (asm) +BenchmarkCastagnoli1KBNoAsm-4 1000000 1475 ns/op 694.14 MB/s (slice8) +BenchmarkCastagnoli1KB-4 10000000 146 ns/op 6993.35 MB/s (asm) + +BenchmarkStdNoAsmCastagnoli8KB-4 50000 28781 ns/op 284.63 MB/s +BenchmarkStdCastagnoli8KB-4 1000000 1029 ns/op 7957.89 MB/s (asm) +BenchmarkCastagnoli8KBNoAsm-4 200000 11410 ns/op 717.94 MB/s (slice8) +BenchmarkCastagnoli8KB-4 1000000 1000 ns/op 8188.71 MB/s (asm) + +BenchmarkStdNoAsmCastagnoli32KB-4 10000 115426 ns/op 283.89 MB/s +BenchmarkStdCastagnoli32KB-4 300000 4065 ns/op 8059.13 MB/s (asm) +BenchmarkCastagnoli32KBNoAsm-4 30000 45171 ns/op 725.41 MB/s (slice8) +BenchmarkCastagnoli32KB-4 500000 4077 ns/op 8035.89 MB/s (asm) +``` + +The IEEE assembler optimizations has been submitted and will be part of the Go 1.6 standard library. + +However, the improved use of slice-by-8 has not, but will probably be submitted for Go 1.7. + +# license + +Standard Go license. Changes are Copyright (c) 2015 Klaus Post under same conditions. diff --git a/vendor/github.com/lafriks/xormstore/.gitignore b/vendor/github.com/lafriks/xormstore/.gitignore new file mode 100644 index 0000000000..862a81f5f9 --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/.gitignore @@ -0,0 +1,3 @@ +vendor/ +debug.test +coverage.txt \ No newline at end of file diff --git a/vendor/github.com/lafriks/xormstore/.travis.yml b/vendor/github.com/lafriks/xormstore/.travis.yml new file mode 100644 index 0000000000..9b46d82a65 --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/.travis.yml @@ -0,0 +1,19 @@ +sudo: required +services: + - docker + +branches: + only: + - master + +language: go +go: + - "tip" + - "1.8" + - "1.9" + - "1.10" + +script: ./test + +after_success: + - bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/vendor/github.com/lafriks/xormstore/Gopkg.lock b/vendor/github.com/lafriks/xormstore/Gopkg.lock new file mode 100644 index 0000000000..0d2cf03cba --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/Gopkg.lock @@ -0,0 +1,75 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/denisenkom/go-mssqldb" + packages = ["."] + revision = "ee492709d4324cdcb051d2ac266b77ddc380f5c5" + +[[projects]] + name = "github.com/go-sql-driver/mysql" + packages = ["."] + revision = "a0583e0143b1624142adab07e0e97fe106d99561" + version = "v1.3" + +[[projects]] + branch = "master" + name = "github.com/go-xorm/builder" + packages = ["."] + revision = "488224409dd8aa2ce7a5baf8d10d55764a913738" + +[[projects]] + name = "github.com/go-xorm/core" + packages = ["."] + revision = "da1adaf7a28ca792961721a34e6e04945200c890" + version = "v0.5.7" + +[[projects]] + name = "github.com/go-xorm/xorm" + packages = ["."] + revision = "1933dd69e294c0a26c0266637067f24dbb25770c" + version = "v0.6.4" + +[[projects]] + name = "github.com/gorilla/context" + packages = ["."] + revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a" + version = "v1.1" + +[[projects]] + name = "github.com/gorilla/securecookie" + packages = ["."] + revision = "e59506cc896acb7f7bf732d4fdf5e25f7ccd8983" + version = "v1.1.1" + +[[projects]] + name = "github.com/gorilla/sessions" + packages = ["."] + revision = "ca9ada44574153444b00d3fd9c8559e4cc95f896" + version = "v1.1" + +[[projects]] + branch = "master" + name = "github.com/lib/pq" + packages = [".","oid"] + revision = "88edab0803230a3898347e77b474f8c1820a1f20" + +[[projects]] + name = "github.com/mattn/go-sqlite3" + packages = ["."] + revision = "6c771bb9887719704b210e87e934f08be014bdb1" + version = "v1.6.0" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = ["md4"] + revision = "c7dcf104e3a7a1417abc0230cb0d5240d764159d" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "bba98a94e8c6668ae9556b4978bbffdfc5d4d535d522c8865465335bfaa2fc70" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/lafriks/xormstore/Gopkg.toml b/vendor/github.com/lafriks/xormstore/Gopkg.toml new file mode 100644 index 0000000000..ea71d50eaf --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/Gopkg.toml @@ -0,0 +1,50 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + name = "github.com/go-sql-driver/mysql" + version = "1.3.0" + +[[constraint]] + name = "github.com/go-xorm/xorm" + version = "0.6.4" + +[[constraint]] + name = "github.com/gorilla/context" + version = "1.1.0" + +[[constraint]] + name = "github.com/gorilla/securecookie" + version = "1.1.1" + +[[constraint]] + name = "github.com/gorilla/sessions" + version = "1.1.0" + +[[constraint]] + branch = "master" + name = "github.com/lib/pq" + +[[constraint]] + name = "github.com/mattn/go-sqlite3" + version = "1.6.0" diff --git a/vendor/github.com/lafriks/xormstore/README.md b/vendor/github.com/lafriks/xormstore/README.md new file mode 100644 index 0000000000..361c5871fc --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/README.md @@ -0,0 +1,48 @@ +[![GoDoc](https://godoc.org/github.com/lafriks/xormstore?status.svg)](https://godoc.org/github.com/lafriks/xormstore) +[![Build Status](https://travis-ci.org/lafriks/xormstore.svg?branch=master)](https://travis-ci.org/lafriks/xormstore) +[![codecov](https://codecov.io/gh/lafriks/xormstore/branch/master/graph/badge.svg)](https://codecov.io/gh/lafriks/xormstore) + +#### XORM backend for gorilla sessions + + go get github.com/lafriks/xormstore + +#### Example + +```go +// initialize and setup cleanup +store := xormstore.New(engine, []byte("secret")) +// db cleanup every hour +// close quit channel to stop cleanup +quit := make(chan struct{}) +go store.PeriodicCleanup(1*time.Hour, quit) +``` + +```go +// in HTTP handler +func handlerFunc(w http.ResponseWriter, r *http.Request) { + session, err := store.Get(r, "session") + session.Values["user_id"] = 123 + store.Save(r, w, session) + http.Error(w, "", http.StatusOK) +} +``` + +For more details see [xormstore godoc documentation](https://godoc.org/github.com/lafriks/xormstore). + +#### Testing + +Just sqlite3 tests: + + go test + +All databases using docker: + + ./test + +If docker is not local (docker-machine etc): + + DOCKER_IP=$(docker-machine ip dev) ./test + +#### License + +xormstore is licensed under the MIT license. See [LICENSE](LICENSE) for the full license text. diff --git a/vendor/github.com/lafriks/xormstore/test b/vendor/github.com/lafriks/xormstore/test new file mode 100644 index 0000000000..4b06eae4e7 --- /dev/null +++ b/vendor/github.com/lafriks/xormstore/test @@ -0,0 +1,70 @@ +#!/bin/bash + +DOCKER_IP=${DOCKER_IP:-127.0.0.1} + +sqlite3() { + DATABASE_URI="sqlite3://file:dummy?mode=memory&cache=shared" go test -v -race -cover -coverprofile=coverage.txt -covermode=atomic + return $? +} + +postgres10() { + ID=$(docker run -p 5432 -d postgres:10-alpine) + PORT=$(docker port "$ID" 5432 | cut -d : -f 2) + DATABASE_URI="postgres://user=postgres password=postgres dbname=postgres host=$DOCKER_IP port=$PORT sslmode=disable" go test -v -race -cover + S=$? + docker rm -vf "$ID" > /dev/null + return $S +} + +postgres96() { + ID=$(docker run -p 5432 -d postgres:9.6-alpine) + PORT=$(docker port "$ID" 5432 | cut -d : -f 2) + DATABASE_URI="postgres://user=postgres password=postgres dbname=postgres host=$DOCKER_IP port=$PORT sslmode=disable" go test -v -race -cover + S=$? + docker rm -vf "$ID" > /dev/null + return $S +} + +postgres94() { + ID=$(docker run -p 5432 -d postgres:9.4-alpine) + PORT=$(docker port "$ID" 5432 | cut -d : -f 2) + DATABASE_URI="postgres://user=postgres password=postgres dbname=postgres host=$DOCKER_IP port=$PORT sslmode=disable" go test -v -race -cover + S=$? + docker rm -vf "$ID" > /dev/null + return $S +} + +mysql57() { + ID=$(docker run \ + -e MYSQL_ROOT_PASSWORD=root \ + -e MYSQL_USER=mysql \ + -e MYSQL_PASSWORD=mysql \ + -e MYSQL_DATABASE=mysql \ + -p 3306 -d mysql:5.7) + PORT=$(docker port "$ID" 3306 | cut -d : -f 2) + DATABASE_URI="mysql://mysql:mysql@tcp($DOCKER_IP:$PORT)/mysql?charset=utf8&parseTime=True" go test -v -race -cover + S=$? + docker rm -vf "$ID" > /dev/null + return $S +} + +mariadb10() { + ID=$(docker run \ + -e MYSQL_ROOT_PASSWORD=root \ + -e MYSQL_USER=mysql \ + -e MYSQL_PASSWORD=mysql \ + -e MYSQL_DATABASE=mysql \ + -p 3306 -d mariadb:10) + PORT=$(docker port "$ID" 3306 | cut -d : -f 2) + DATABASE_URI="mysql://mysql:mysql@tcp($DOCKER_IP:$PORT)/mysql?charset=utf8&parseTime=True" go test -v -race -cover + S=$? + docker rm -vf "$ID" > /dev/null + return $S +} + +sqlite3 || exit 1 +postgres94 || exit 1 +postgres96 || exit 1 +postgres10 || exit 1 +mysql57 || exit 1 +mariadb10 || exit 1 diff --git a/vendor/github.com/lib/pq/.gitignore b/vendor/github.com/lib/pq/.gitignore new file mode 100644 index 0000000000..0f1d00e119 --- /dev/null +++ b/vendor/github.com/lib/pq/.gitignore @@ -0,0 +1,4 @@ +.db +*.test +*~ +*.swp diff --git a/vendor/github.com/lib/pq/.travis.sh b/vendor/github.com/lib/pq/.travis.sh new file mode 100644 index 0000000000..a297dc4520 --- /dev/null +++ b/vendor/github.com/lib/pq/.travis.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +set -eu + +client_configure() { + sudo chmod 600 $PQSSLCERTTEST_PATH/postgresql.key +} + +pgdg_repository() { + local sourcelist='sources.list.d/postgresql.list' + + curl -sS 'https://www.postgresql.org/media/keys/ACCC4CF8.asc' | sudo apt-key add - + echo deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main $PGVERSION | sudo tee "/etc/apt/$sourcelist" + sudo apt-get -o Dir::Etc::sourcelist="$sourcelist" -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0' update +} + +postgresql_configure() { + sudo tee /etc/postgresql/$PGVERSION/main/pg_hba.conf > /dev/null <<-config + local all all trust + hostnossl all pqgossltest 127.0.0.1/32 reject + hostnossl all pqgosslcert 127.0.0.1/32 reject + hostssl all pqgossltest 127.0.0.1/32 trust + hostssl all pqgosslcert 127.0.0.1/32 cert + host all all 127.0.0.1/32 trust + hostnossl all pqgossltest ::1/128 reject + hostnossl all pqgosslcert ::1/128 reject + hostssl all pqgossltest ::1/128 trust + hostssl all pqgosslcert ::1/128 cert + host all all ::1/128 trust + config + + xargs sudo install -o postgres -g postgres -m 600 -t /var/lib/postgresql/$PGVERSION/main/ <<-certificates + certs/root.crt + certs/server.crt + certs/server.key + certificates + + sort -VCu <<-versions || + $PGVERSION + 9.2 + versions + sudo tee -a /etc/postgresql/$PGVERSION/main/postgresql.conf > /dev/null <<-config + ssl_ca_file = 'root.crt' + ssl_cert_file = 'server.crt' + ssl_key_file = 'server.key' + config + + echo 127.0.0.1 postgres | sudo tee -a /etc/hosts > /dev/null + + sudo service postgresql restart +} + +postgresql_install() { + xargs sudo apt-get -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confnew' install <<-packages + postgresql-$PGVERSION + postgresql-server-dev-$PGVERSION + postgresql-contrib-$PGVERSION + packages +} + +postgresql_uninstall() { + sudo service postgresql stop + xargs sudo apt-get -y --purge remove <<-packages + libpq-dev + libpq5 + postgresql + postgresql-client-common + postgresql-common + packages + sudo rm -rf /var/lib/postgresql +} + +megacheck_install() { + # Lock megacheck version at $MEGACHECK_VERSION to prevent spontaneous + # new error messages in old code. + go get -d honnef.co/go/tools/... + git -C $GOPATH/src/honnef.co/go/tools/ checkout $MEGACHECK_VERSION + go install honnef.co/go/tools/cmd/megacheck + megacheck --version +} + +golint_install() { + go get github.com/golang/lint/golint +} + +$1 diff --git a/vendor/github.com/lib/pq/.travis.yml b/vendor/github.com/lib/pq/.travis.yml new file mode 100644 index 0000000000..18556e0896 --- /dev/null +++ b/vendor/github.com/lib/pq/.travis.yml @@ -0,0 +1,50 @@ +language: go + +go: + - 1.8.x + - 1.9.x + - 1.10.x + - master + +sudo: true + +env: + global: + - PGUSER=postgres + - PQGOSSLTESTS=1 + - PQSSLCERTTEST_PATH=$PWD/certs + - PGHOST=127.0.0.1 + - MEGACHECK_VERSION=2017.2.2 + matrix: + - PGVERSION=10 + - PGVERSION=9.6 + - PGVERSION=9.5 + - PGVERSION=9.4 + - PGVERSION=9.3 + - PGVERSION=9.2 + - PGVERSION=9.1 + - PGVERSION=9.0 + +before_install: + - ./.travis.sh postgresql_uninstall + - ./.travis.sh pgdg_repository + - ./.travis.sh postgresql_install + - ./.travis.sh postgresql_configure + - ./.travis.sh client_configure + - ./.travis.sh megacheck_install + - ./.travis.sh golint_install + - go get golang.org/x/tools/cmd/goimports + +before_script: + - createdb pqgotest + - createuser -DRS pqgossltest + - createuser -DRS pqgosslcert + +script: + - > + goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }' + - go vet ./... + - megacheck -go 1.8 ./... + - golint ./... + - PQTEST_BINARY_PARAMETERS=no go test -race -v ./... + - PQTEST_BINARY_PARAMETERS=yes go test -race -v ./... diff --git a/vendor/github.com/lib/pq/CONTRIBUTING.md b/vendor/github.com/lib/pq/CONTRIBUTING.md new file mode 100644 index 0000000000..84c937f156 --- /dev/null +++ b/vendor/github.com/lib/pq/CONTRIBUTING.md @@ -0,0 +1,29 @@ +## Contributing to pq + +`pq` has a backlog of pull requests, but contributions are still very +much welcome. You can help with patch review, submitting bug reports, +or adding new functionality. There is no formal style guide, but +please conform to the style of existing code and general Go formatting +conventions when submitting patches. + +### Patch review + +Help review existing open pull requests by commenting on the code or +proposed functionality. + +### Bug reports + +We appreciate any bug reports, but especially ones with self-contained +(doesn't depend on code outside of pq), minimal (can't be simplified +further) test cases. It's especially helpful if you can submit a pull +request with just the failing test case (you'll probably want to +pattern it after the tests in +[conn_test.go](https://github.com/lib/pq/blob/master/conn_test.go). + +### New functionality + +There are a number of pending patches for new functionality, so +additional feature patches will take a while to merge. Still, patches +are generally reviewed based on usefulness and complexity in addition +to time-in-queue, so if you have a knockout idea, take a shot. Feel +free to open an issue discussion your proposed patch beforehand. diff --git a/vendor/github.com/lib/pq/README.md b/vendor/github.com/lib/pq/README.md new file mode 100644 index 0000000000..d71f3c2c39 --- /dev/null +++ b/vendor/github.com/lib/pq/README.md @@ -0,0 +1,95 @@ +# pq - A pure Go postgres driver for Go's database/sql package + +[![GoDoc](https://godoc.org/github.com/lib/pq?status.svg)](https://godoc.org/github.com/lib/pq) +[![Build Status](https://travis-ci.org/lib/pq.svg?branch=master)](https://travis-ci.org/lib/pq) + +## Install + + go get github.com/lib/pq + +## Docs + +For detailed documentation and basic usage examples, please see the package +documentation at . + +## Tests + +`go test` is used for testing. See [TESTS.md](TESTS.md) for more details. + +## Features + +* SSL +* Handles bad connections for `database/sql` +* Scan `time.Time` correctly (i.e. `timestamp[tz]`, `time[tz]`, `date`) +* Scan binary blobs correctly (i.e. `bytea`) +* Package for `hstore` support +* COPY FROM support +* pq.ParseURL for converting urls to connection strings for sql.Open. +* Many libpq compatible environment variables +* Unix socket support +* Notifications: `LISTEN`/`NOTIFY` +* pgpass support + +## Future / Things you can help with + +* Better COPY FROM / COPY TO (see discussion in #181) + +## Thank you (alphabetical) + +Some of these contributors are from the original library `bmizerany/pq.go` whose +code still exists in here. + +* Andy Balholm (andybalholm) +* Ben Berkert (benburkert) +* Benjamin Heatwole (bheatwole) +* Bill Mill (llimllib) +* Bjørn Madsen (aeons) +* Blake Gentry (bgentry) +* Brad Fitzpatrick (bradfitz) +* Charlie Melbye (cmelbye) +* Chris Bandy (cbandy) +* Chris Gilling (cgilling) +* Chris Walsh (cwds) +* Dan Sosedoff (sosedoff) +* Daniel Farina (fdr) +* Eric Chlebek (echlebek) +* Eric Garrido (minusnine) +* Eric Urban (hydrogen18) +* Everyone at The Go Team +* Evan Shaw (edsrzf) +* Ewan Chou (coocood) +* Fazal Majid (fazalmajid) +* Federico Romero (federomero) +* Fumin (fumin) +* Gary Burd (garyburd) +* Heroku (heroku) +* James Pozdena (jpoz) +* Jason McVetta (jmcvetta) +* Jeremy Jay (pbnjay) +* Joakim Sernbrant (serbaut) +* John Gallagher (jgallagher) +* Jonathan Rudenberg (titanous) +* Joël Stemmer (jstemmer) +* Kamil Kisiel (kisielk) +* Kelly Dunn (kellydunn) +* Keith Rarick (kr) +* Kir Shatrov (kirs) +* Lann Martin (lann) +* Maciek Sakrejda (uhoh-itsmaciek) +* Marc Brinkmann (mbr) +* Marko Tiikkaja (johto) +* Matt Newberry (MattNewberry) +* Matt Robenolt (mattrobenolt) +* Martin Olsen (martinolsen) +* Mike Lewis (mikelikespie) +* Nicolas Patry (Narsil) +* Oliver Tonnhofer (olt) +* Patrick Hayes (phayes) +* Paul Hammond (paulhammond) +* Ryan Smith (ryandotsmith) +* Samuel Stauffer (samuel) +* Timothée Peignier (cyberdelia) +* Travis Cline (tmc) +* TruongSinh Tran-Nguyen (truongsinh) +* Yaismel Miranda (ympons) +* notedit (notedit) diff --git a/vendor/github.com/lib/pq/TESTS.md b/vendor/github.com/lib/pq/TESTS.md new file mode 100644 index 0000000000..f05021115b --- /dev/null +++ b/vendor/github.com/lib/pq/TESTS.md @@ -0,0 +1,33 @@ +# Tests + +## Running Tests + +`go test` is used for testing. A running PostgreSQL +server is required, with the ability to log in. The +database to connect to test with is "pqgotest," on +"localhost" but these can be overridden using [environment +variables](https://www.postgresql.org/docs/9.3/static/libpq-envars.html). + +Example: + + PGHOST=/run/postgresql go test + +## Benchmarks + +A benchmark suite can be run as part of the tests: + + go test -bench . + +## Example setup (Docker) + +Run a postgres container: + +``` +docker run --expose 5432:5432 postgres +``` + +Run tests: + +``` +PGHOST=localhost PGPORT=5432 PGUSER=postgres PGSSLMODE=disable PGDATABASE=postgres go test +``` diff --git a/vendor/github.com/lib/pq/conn.go b/vendor/github.com/lib/pq/conn.go index df6b565f73..43c8df29f1 100644 --- a/vendor/github.com/lib/pq/conn.go +++ b/vendor/github.com/lib/pq/conn.go @@ -35,8 +35,12 @@ var ( errNoLastInsertID = errors.New("no LastInsertId available after the empty statement") ) +// Driver is the Postgres database driver. type Driver struct{} +// Open opens a new connection to the database. name is a connection string. +// Most users should only use it through database/sql package from the standard +// library. func (d *Driver) Open(name string) (driver.Conn, error) { return Open(name) } @@ -78,6 +82,8 @@ func (s transactionStatus) String() string { panic("not reached") } +// Dialer is the dialer interface. It can be used to obtain more control over +// how pq creates network connections. type Dialer interface { Dial(network, address string) (net.Conn, error) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) @@ -238,10 +244,14 @@ func (cn *conn) writeBuf(b byte) *writeBuf { } } +// Open opens a new connection to the database. name is a connection string. +// Most users should only use it through database/sql package from the standard +// library. func Open(name string) (_ driver.Conn, err error) { return DialOpen(defaultDialer{}, name) } +// DialOpen opens a new connection to the database using a dialer. func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { // Handle any panics during connection initialization. Note that we // specifically do *not* want to use errRecover(), as that would turn any @@ -329,7 +339,20 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { if err != nil { return nil, err } - cn.ssl(o) + + err = cn.ssl(o) + if err != nil { + return nil, err + } + + // cn.startup panics on error. Make sure we don't leak cn.c. + panicking := true + defer func() { + if panicking { + cn.c.Close() + } + }() + cn.buf = bufio.NewReader(cn.c) cn.startup(o) @@ -337,6 +360,7 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { if timeout, ok := o["connect_timeout"]; ok && timeout != "0" { err = cn.c.SetDeadline(time.Time{}) } + panicking = false return cn, err } @@ -1009,30 +1033,35 @@ func (cn *conn) recv1() (t byte, r *readBuf) { return t, r } -func (cn *conn) ssl(o values) { - upgrade := ssl(o) +func (cn *conn) ssl(o values) error { + upgrade, err := ssl(o) + if err != nil { + return err + } + if upgrade == nil { // Nothing to do - return + return nil } w := cn.writeBuf(0) w.int32(80877103) - if err := cn.sendStartupPacket(w); err != nil { - panic(err) + if err = cn.sendStartupPacket(w); err != nil { + return err } b := cn.scratch[:1] - _, err := io.ReadFull(cn.c, b) + _, err = io.ReadFull(cn.c, b) if err != nil { - panic(err) + return err } if b[0] != 'S' { - panic(ErrSSLNotSupported) + return ErrSSLNotSupported } - cn.c = upgrade(cn.c) + cn.c, err = upgrade(cn.c) + return err } // isDriverSetting returns true iff a setting is purely for configuring the @@ -1432,7 +1461,8 @@ func (rs *rows) NextResultSet() error { // // tblname := "my_table" // data := "my_data" -// err = db.Exec(fmt.Sprintf("INSERT INTO %s VALUES ($1)", pq.QuoteIdentifier(tblname)), data) +// quoted := pq.QuoteIdentifier(tblname) +// err := db.Exec(fmt.Sprintf("INSERT INTO %s VALUES ($1)", quoted), data) // // Any double quotes in name will be escaped. The quoted identifier will be // case sensitive when used in a query. If the input string contains a zero diff --git a/vendor/github.com/lib/pq/conn_go18.go b/vendor/github.com/lib/pq/conn_go18.go index ab97a104d8..a5254f2b47 100644 --- a/vendor/github.com/lib/pq/conn_go18.go +++ b/vendor/github.com/lib/pq/conn_go18.go @@ -108,7 +108,10 @@ func (cn *conn) cancel() error { can := conn{ c: c, } - can.ssl(cn.opts) + err = can.ssl(cn.opts) + if err != nil { + return err + } w := can.writeBuf(0) w.int32(80877102) // cancel request code diff --git a/vendor/github.com/lib/pq/connector.go b/vendor/github.com/lib/pq/connector.go new file mode 100644 index 0000000000..9e66eb5df8 --- /dev/null +++ b/vendor/github.com/lib/pq/connector.go @@ -0,0 +1,43 @@ +// +build go1.10 + +package pq + +import ( + "context" + "database/sql/driver" +) + +// Connector represents a fixed configuration for the pq driver with a given +// name. Connector satisfies the database/sql/driver Connector interface and +// can be used to create any number of DB Conn's via the database/sql OpenDB +// function. +// +// See https://golang.org/pkg/database/sql/driver/#Connector. +// See https://golang.org/pkg/database/sql/#OpenDB. +type connector struct { + name string +} + +// Connect returns a connection to the database using the fixed configuration +// of this Connector. Context is not used. +func (c *connector) Connect(_ context.Context) (driver.Conn, error) { + return (&Driver{}).Open(c.name) +} + +// Driver returnst the underlying driver of this Connector. +func (c *connector) Driver() driver.Driver { + return &Driver{} +} + +var _ driver.Connector = &connector{} + +// NewConnector returns a connector for the pq driver in a fixed configuration +// with the given name. The returned connector can be used to create any number +// of equivalent Conn's. The returned connector is intended to be used with +// database/sql.OpenDB. +// +// See https://golang.org/pkg/database/sql/driver/#Connector. +// See https://golang.org/pkg/database/sql/#OpenDB. +func NewConnector(name string) (driver.Connector, error) { + return &connector{name: name}, nil +} diff --git a/vendor/github.com/lib/pq/doc.go b/vendor/github.com/lib/pq/doc.go index 6d252ecee2..a1b0297138 100644 --- a/vendor/github.com/lib/pq/doc.go +++ b/vendor/github.com/lib/pq/doc.go @@ -11,7 +11,8 @@ using this package directly. For example: ) func main() { - db, err := sql.Open("postgres", "user=pqgotest dbname=pqgotest sslmode=verify-full") + connStr := "user=pqgotest dbname=pqgotest sslmode=verify-full" + db, err := sql.Open("postgres", connStr) if err != nil { log.Fatal(err) } @@ -23,7 +24,8 @@ using this package directly. For example: You can also connect to a database using a URL. For example: - db, err := sql.Open("postgres", "postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full") + connStr := "postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full" + db, err := sql.Open("postgres", connStr) Connection String Parameters @@ -43,21 +45,28 @@ supported: * dbname - The name of the database to connect to * user - The user to sign in as * password - The user's password - * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) + * host - The host to connect to. Values that start with / are for unix + domain sockets. (default is localhost) * port - The port to bind to. (default is 5432) - * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) + * sslmode - Whether or not to use SSL (default is require, this is not + the default for libpq) * fallback_application_name - An application_name to fall back to if one isn't provided. - * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. + * connect_timeout - Maximum wait for connection, in seconds. Zero or + not specified means wait indefinitely. * sslcert - Cert file location. The file must contain PEM encoded data. * sslkey - Key file location. The file must contain PEM encoded data. - * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. + * sslrootcert - The location of the root certificate file. The file + must contain PEM encoded data. Valid values for sslmode are: * disable - No SSL * require - Always SSL (skip verification) - * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) - * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) + * verify-ca - Always SSL (verify that the certificate presented by the + server was signed by a trusted CA) + * verify-full - Always SSL (verify that the certification presented by + the server was signed by a trusted CA and the server host name + matches the one in the certificate) See http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING for more information about connection string parameters. @@ -68,7 +77,7 @@ Use single quotes for values that contain whitespace: A backslash will escape the next character in values: - "user=space\ man password='it\'s valid' + "user=space\ man password='it\'s valid'" Note that the connection parameter client_encoding (which sets the text encoding for the connection) may be set but must be "UTF8", @@ -129,7 +138,8 @@ This package returns the following types for values from the PostgreSQL backend: - integer types smallint, integer, and bigint are returned as int64 - floating-point types real and double precision are returned as float64 - character types char, varchar, and text are returned as string - - temporal types date, time, timetz, timestamp, and timestamptz are returned as time.Time + - temporal types date, time, timetz, timestamp, and timestamptz are + returned as time.Time - the boolean type is returned as bool - the bytea type is returned as []byte @@ -229,7 +239,7 @@ for more information). Note that the channel name will be truncated to 63 bytes by the PostgreSQL server. You can find a complete, working example of Listener usage at -http://godoc.org/github.com/lib/pq/listen_example. +http://godoc.org/github.com/lib/pq/example/listen. */ package pq diff --git a/vendor/github.com/lib/pq/error.go b/vendor/github.com/lib/pq/error.go index b4bb44cee3..96aae29c65 100644 --- a/vendor/github.com/lib/pq/error.go +++ b/vendor/github.com/lib/pq/error.go @@ -153,6 +153,7 @@ var errorCodeNames = map[ErrorCode]string{ "22004": "null_value_not_allowed", "22002": "null_value_no_indicator_parameter", "22003": "numeric_value_out_of_range", + "2200H": "sequence_generator_limit_exceeded", "22026": "string_data_length_mismatch", "22001": "string_data_right_truncation", "22011": "substring_error", @@ -459,6 +460,11 @@ func errorf(s string, args ...interface{}) { panic(fmt.Errorf("pq: %s", fmt.Sprintf(s, args...))) } +// TODO(ainar-g) Rename to errorf after removing panics. +func fmterrorf(s string, args ...interface{}) error { + return fmt.Errorf("pq: %s", fmt.Sprintf(s, args...)) +} + func errRecoverNoErrBadConn(err *error) { e := recover() if e == nil { @@ -487,7 +493,8 @@ func (c *conn) errRecover(err *error) { *err = v } case *net.OpError: - *err = driver.ErrBadConn + c.bad = true + *err = v case error: if v == io.EOF || v.(error).Error() == "remote error: handshake failure" { *err = driver.ErrBadConn diff --git a/vendor/github.com/lib/pq/go.mod b/vendor/github.com/lib/pq/go.mod new file mode 100644 index 0000000000..edf0b343fd --- /dev/null +++ b/vendor/github.com/lib/pq/go.mod @@ -0,0 +1 @@ +module github.com/lib/pq diff --git a/vendor/github.com/lib/pq/notify.go b/vendor/github.com/lib/pq/notify.go index a171651577..850bb9040c 100644 --- a/vendor/github.com/lib/pq/notify.go +++ b/vendor/github.com/lib/pq/notify.go @@ -60,7 +60,7 @@ type ListenerConn struct { replyChan chan message } -// Creates a new ListenerConn. Use NewListener instead. +// NewListenerConn creates a new ListenerConn. Use NewListener instead. func NewListenerConn(name string, notificationChan chan<- *Notification) (*ListenerConn, error) { return newDialListenerConn(defaultDialer{}, name, notificationChan) } @@ -214,17 +214,17 @@ func (l *ListenerConn) listenerConnMain() { // this ListenerConn is done } -// Send a LISTEN query to the server. See ExecSimpleQuery. +// Listen sends a LISTEN query to the server. See ExecSimpleQuery. func (l *ListenerConn) Listen(channel string) (bool, error) { return l.ExecSimpleQuery("LISTEN " + QuoteIdentifier(channel)) } -// Send an UNLISTEN query to the server. See ExecSimpleQuery. +// Unlisten sends an UNLISTEN query to the server. See ExecSimpleQuery. func (l *ListenerConn) Unlisten(channel string) (bool, error) { return l.ExecSimpleQuery("UNLISTEN " + QuoteIdentifier(channel)) } -// Send `UNLISTEN *` to the server. See ExecSimpleQuery. +// UnlistenAll sends an `UNLISTEN *` query to the server. See ExecSimpleQuery. func (l *ListenerConn) UnlistenAll() (bool, error) { return l.ExecSimpleQuery("UNLISTEN *") } @@ -267,8 +267,8 @@ func (l *ListenerConn) sendSimpleQuery(q string) (err error) { return nil } -// Execute a "simple query" (i.e. one with no bindable parameters) on the -// connection. The possible return values are: +// ExecSimpleQuery executes a "simple query" (i.e. one with no bindable +// parameters) on the connection. The possible return values are: // 1) "executed" is true; the query was executed to completion on the // database server. If the query failed, err will be set to the error // returned by the database, otherwise err will be nil. @@ -333,6 +333,7 @@ func (l *ListenerConn) ExecSimpleQuery(q string) (executed bool, err error) { } } +// Close closes the connection. func (l *ListenerConn) Close() error { l.connectionLock.Lock() if l.err != nil { @@ -346,7 +347,7 @@ func (l *ListenerConn) Close() error { return l.cn.c.Close() } -// Err() returns the reason the connection was closed. It is not safe to call +// Err returns the reason the connection was closed. It is not safe to call // this function until l.Notify has been closed. func (l *ListenerConn) Err() error { return l.err @@ -354,32 +355,43 @@ func (l *ListenerConn) Err() error { var errListenerClosed = errors.New("pq: Listener has been closed") +// ErrChannelAlreadyOpen is returned from Listen when a channel is already +// open. var ErrChannelAlreadyOpen = errors.New("pq: channel is already open") + +// ErrChannelNotOpen is returned from Unlisten when a channel is not open. var ErrChannelNotOpen = errors.New("pq: channel is not open") +// ListenerEventType is an enumeration of listener event types. type ListenerEventType int const ( - // Emitted only when the database connection has been initially - // initialized. err will always be nil. + // ListenerEventConnected is emitted only when the database connection + // has been initially initialized. The err argument of the callback + // will always be nil. ListenerEventConnected ListenerEventType = iota - // Emitted after a database connection has been lost, either because of an - // error or because Close has been called. err will be set to the reason - // the database connection was lost. + // ListenerEventDisconnected is emitted after a database connection has + // been lost, either because of an error or because Close has been + // called. The err argument will be set to the reason the database + // connection was lost. ListenerEventDisconnected - // Emitted after a database connection has been re-established after - // connection loss. err will always be nil. After this event has been - // emitted, a nil pq.Notification is sent on the Listener.Notify channel. + // ListenerEventReconnected is emitted after a database connection has + // been re-established after connection loss. The err argument of the + // callback will always be nil. After this event has been emitted, a + // nil pq.Notification is sent on the Listener.Notify channel. ListenerEventReconnected - // Emitted after a connection to the database was attempted, but failed. - // err will be set to an error describing why the connection attempt did - // not succeed. + // ListenerEventConnectionAttemptFailed is emitted after a connection + // to the database was attempted, but failed. The err argument will be + // set to an error describing why the connection attempt did not + // succeed. ListenerEventConnectionAttemptFailed ) +// EventCallbackType is the event callback type. See also ListenerEventType +// constants' documentation. type EventCallbackType func(event ListenerEventType, err error) // Listener provides an interface for listening to notifications from a @@ -454,9 +466,9 @@ func NewDialListener(d Dialer, return l } -// Returns the notification channel for this listener. This is the same -// channel as Notify, and will not be recreated during the life time of the -// Listener. +// NotificationChannel returns the notification channel for this listener. +// This is the same channel as Notify, and will not be recreated during the +// life time of the Listener. func (l *Listener) NotificationChannel() <-chan *Notification { return l.Notify } @@ -625,7 +637,7 @@ func (l *Listener) disconnectCleanup() error { // after the connection has been established. func (l *Listener) resync(cn *ListenerConn, notificationChan <-chan *Notification) error { doneChan := make(chan error) - go func() { + go func(notificationChan <-chan *Notification) { for channel := range l.channels { // If we got a response, return that error to our caller as it's // going to be more descriptive than cn.Err(). @@ -646,7 +658,7 @@ func (l *Listener) resync(cn *ListenerConn, notificationChan <-chan *Notificatio } } doneChan <- nil - }() + }(notificationChan) // Ignore notifications while synchronization is going on to avoid // deadlocks. We have to send a nil notification over Notify anyway as @@ -713,6 +725,9 @@ func (l *Listener) Close() error { } l.isClosed = true + // Unblock calls to Listen() + l.reconnectCond.Broadcast() + return nil } @@ -772,7 +787,7 @@ func (l *Listener) listenerConnLoop() { } l.emitEvent(ListenerEventDisconnected, err) - time.Sleep(nextReconnect.Sub(time.Now())) + time.Sleep(time.Until(nextReconnect)) } } diff --git a/vendor/github.com/lib/pq/ssl.go b/vendor/github.com/lib/pq/ssl.go index 7deb304366..e1a326a0d5 100644 --- a/vendor/github.com/lib/pq/ssl.go +++ b/vendor/github.com/lib/pq/ssl.go @@ -12,7 +12,7 @@ import ( // ssl generates a function to upgrade a net.Conn based on the "sslmode" and // related settings. The function is nil when no upgrade should take place. -func ssl(o values) func(net.Conn) net.Conn { +func ssl(o values) (func(net.Conn) (net.Conn, error), error) { verifyCaOnly := false tlsConf := tls.Config{} switch mode := o["sslmode"]; mode { @@ -45,29 +45,38 @@ func ssl(o values) func(net.Conn) net.Conn { case "verify-full": tlsConf.ServerName = o["host"] case "disable": - return nil + return nil, nil default: - errorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode) + return nil, fmterrorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode) } - sslClientCertificates(&tlsConf, o) - sslCertificateAuthority(&tlsConf, o) + err := sslClientCertificates(&tlsConf, o) + if err != nil { + return nil, err + } + err = sslCertificateAuthority(&tlsConf, o) + if err != nil { + return nil, err + } sslRenegotiation(&tlsConf) - return func(conn net.Conn) net.Conn { + return func(conn net.Conn) (net.Conn, error) { client := tls.Client(conn, &tlsConf) if verifyCaOnly { - sslVerifyCertificateAuthority(client, &tlsConf) + err := sslVerifyCertificateAuthority(client, &tlsConf) + if err != nil { + return nil, err + } } - return client - } + return client, nil + }, nil } // sslClientCertificates adds the certificate specified in the "sslcert" and // "sslkey" settings, or if they aren't set, from the .postgresql directory // in the user's home directory. The configured files must exist and have // the correct permissions. -func sslClientCertificates(tlsConf *tls.Config, o values) { +func sslClientCertificates(tlsConf *tls.Config, o values) error { // user.Current() might fail when cross-compiling. We have to ignore the // error and continue without home directory defaults, since we wouldn't // know from where to load them. @@ -82,13 +91,13 @@ func sslClientCertificates(tlsConf *tls.Config, o values) { } // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1045 if len(sslcert) == 0 { - return + return nil } // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1050:L1054 if _, err := os.Stat(sslcert); os.IsNotExist(err) { - return + return nil } else if err != nil { - panic(err) + return err } // In libpq, the ssl key is only loaded if the setting is not blank. @@ -101,19 +110,21 @@ func sslClientCertificates(tlsConf *tls.Config, o values) { if len(sslkey) > 0 { if err := sslKeyPermissions(sslkey); err != nil { - panic(err) + return err } } cert, err := tls.LoadX509KeyPair(sslcert, sslkey) if err != nil { - panic(err) + return err } + tlsConf.Certificates = []tls.Certificate{cert} + return nil } // sslCertificateAuthority adds the RootCA specified in the "sslrootcert" setting. -func sslCertificateAuthority(tlsConf *tls.Config, o values) { +func sslCertificateAuthority(tlsConf *tls.Config, o values) error { // In libpq, the root certificate is only loaded if the setting is not blank. // // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L950-L951 @@ -122,22 +133,24 @@ func sslCertificateAuthority(tlsConf *tls.Config, o values) { cert, err := ioutil.ReadFile(sslrootcert) if err != nil { - panic(err) + return err } if !tlsConf.RootCAs.AppendCertsFromPEM(cert) { - errorf("couldn't parse pem in sslrootcert") + return fmterrorf("couldn't parse pem in sslrootcert") } } + + return nil } // sslVerifyCertificateAuthority carries out a TLS handshake to the server and // verifies the presented certificate against the CA, i.e. the one specified in // sslrootcert or the system CA if sslrootcert was not specified. -func sslVerifyCertificateAuthority(client *tls.Conn, tlsConf *tls.Config) { +func sslVerifyCertificateAuthority(client *tls.Conn, tlsConf *tls.Config) error { err := client.Handshake() if err != nil { - panic(err) + return err } certs := client.ConnectionState().PeerCertificates opts := x509.VerifyOptions{ @@ -152,7 +165,5 @@ func sslVerifyCertificateAuthority(client *tls.Conn, tlsConf *tls.Config) { opts.Intermediates.AddCert(cert) } _, err = certs[0].Verify(opts) - if err != nil { - panic(err) - } + return err } diff --git a/vendor/github.com/lunny/dingtalk_webhook/README.md b/vendor/github.com/lunny/dingtalk_webhook/README.md new file mode 100644 index 0000000000..5625d36e23 --- /dev/null +++ b/vendor/github.com/lunny/dingtalk_webhook/README.md @@ -0,0 +1,18 @@ +# 非官方 Dingtalk webhook Golang SDK + +## 此工程仅封装了 Dingtalk 的 webhook 部分的请求 + +## 使用 + +首先在dingtalk中创建一个机器人,将accessToken拷贝出来,然后执行下面方法即可 + +```Go +webhook := dingtalk.Webhook(accessToken) +webhook.SendTextMsg("这是一个没有AT的文本消息", false) +``` + +## License + +This project is licensed under the MIT License. +See the [LICENSE](https://github.com/lunny/webhook_dingtalk/blob/master/LICENSE) file +for the full license text. \ No newline at end of file diff --git a/vendor/github.com/lunny/levelqueue/.gitignore b/vendor/github.com/lunny/levelqueue/.gitignore new file mode 100644 index 0000000000..59a8bdee30 --- /dev/null +++ b/vendor/github.com/lunny/levelqueue/.gitignore @@ -0,0 +1,3 @@ +queue/ +queue_pop/ +queue_push/ \ No newline at end of file diff --git a/vendor/github.com/lunny/levelqueue/README.md b/vendor/github.com/lunny/levelqueue/README.md new file mode 100644 index 0000000000..3d9fc097b8 --- /dev/null +++ b/vendor/github.com/lunny/levelqueue/README.md @@ -0,0 +1,23 @@ +# levelqueue + +Level queue is a simple queue golang library base on go-leveldb. + +[![CircleCI](https://circleci.com/gh/lunny/levelqueue.svg?style=shield)](https://circleci.com/gh/lunny/levelqueue) +[![codecov](https://codecov.io/gh/lunny/levelqueue/branch/master/graph/badge.svg)](https://codecov.io/gh/lunny/levelqueue) +[![](https://goreportcard.com/badge/github.com/lunny/levelqueue)](https://goreportcard.com/report/github.com/lunny/levelqueue) + +## Installation + +``` +go get github.com/lunny/levelqueue +``` + +## Usage + +```Go +queue, err := levelqueue.Open("./queue") + +err = queue.RPush([]byte("test")) + +data, err = queue.LPop() +``` \ No newline at end of file diff --git a/vendor/github.com/lunny/levelqueue/go.mod b/vendor/github.com/lunny/levelqueue/go.mod new file mode 100644 index 0000000000..7d060fc099 --- /dev/null +++ b/vendor/github.com/lunny/levelqueue/go.mod @@ -0,0 +1,3 @@ +module github.com/lunny/levelqueue + +require github.com/syndtr/goleveldb v0.0.0-20190203031304-2f17a3356c66 diff --git a/vendor/github.com/lunny/levelqueue/go.sum b/vendor/github.com/lunny/levelqueue/go.sum new file mode 100644 index 0000000000..5936aa865e --- /dev/null +++ b/vendor/github.com/lunny/levelqueue/go.sum @@ -0,0 +1,18 @@ +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +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/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/syndtr/goleveldb v0.0.0-20190203031304-2f17a3356c66 h1:AwmkkZT+TucFotNCL+aNJ/0KCMsRtlXN9fs8uoOMSRk= +github.com/syndtr/goleveldb v0.0.0-20190203031304-2f17a3356c66/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/lunny/log/.gitignore b/vendor/github.com/lunny/log/.gitignore new file mode 100644 index 0000000000..3a11644b45 --- /dev/null +++ b/vendor/github.com/lunny/log/.gitignore @@ -0,0 +1,26 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +log.db +*.log +logs +.vscode \ No newline at end of file diff --git a/vendor/github.com/lunny/log/README.md b/vendor/github.com/lunny/log/README.md new file mode 100644 index 0000000000..da21fa4618 --- /dev/null +++ b/vendor/github.com/lunny/log/README.md @@ -0,0 +1,49 @@ +## log +[![GoDoc](https://godoc.org/github.com/lunny/log?status.png)](https://godoc.org/github.com/lunny/log) + +[简体中文](https://github.com/lunny/log/blob/master/README_CN.md) + +# Installation + +``` +go get github.com/lunny/log +``` + +# Features + +* Add color support for unix console +* Implemented dbwriter to save log to database +* Implemented FileWriter to save log to file by date or time. +* Location configuration + +# Example + +For Single File: +```Go +f, _ := os.Create("my.log") +log.Std.SetOutput(f) +``` + +For Multiple Writer: +```Go +f, _ := os.Create("my.log") +log.Std.SetOutput(io.MultiWriter(f, os.Stdout)) +``` + +For log files by date or time: +```Go +w := log.NewFileWriter(log.FileOptions{ + ByType:log.ByDay, + Dir:"./logs", +}) +log.Std.SetOutput(w) +``` + +# About + +This repo is an extension of Golang log. + +# LICENSE + + BSD License + [http://creativecommons.org/licenses/BSD/](http://creativecommons.org/licenses/BSD/) diff --git a/vendor/github.com/lunny/log/README_CN.md b/vendor/github.com/lunny/log/README_CN.md new file mode 100644 index 0000000000..0fc7db59e2 --- /dev/null +++ b/vendor/github.com/lunny/log/README_CN.md @@ -0,0 +1,52 @@ +## log +[![GoDoc](https://godoc.org/github.com/lunny/log?status.png)](https://godoc.org/github.com/lunny/log) + +[English](https://github.com/lunny/log/blob/master/README.md) + +# 安装 + +``` +go get github.com/lunny/log +``` + +# 特性 + +* 对unix增加控制台颜色支持 +* 实现了保存log到数据库支持 +* 实现了保存log到按日期的文件支持 +* 实现了设置日期的地区 + +# 例子 + +保存到单个文件: + +```Go +f, _ := os.Create("my.log") +log.Std.SetOutput(f) +``` + +保存到数据库: + +```Go +f, _ := os.Create("my.log") +log.Std.SetOutput(io.MultiWriter(f, os.Stdout)) +``` + +保存到按时间分隔的文件: + +```Go +w := log.NewFileWriter(log.FileOptions{ + ByType:log.ByDay, + Dir:"./logs", +}) +log.Std.SetOutput(w) +``` + +# 关于 + +本 Log 是在 golang 的 log 之上的扩展 + +# LICENSE + + BSD License + [http://creativecommons.org/licenses/BSD/](http://creativecommons.org/licenses/BSD/) diff --git a/vendor/github.com/lunny/nodb/.gitignore b/vendor/github.com/lunny/nodb/.gitignore new file mode 100644 index 0000000000..8f4051772a --- /dev/null +++ b/vendor/github.com/lunny/nodb/.gitignore @@ -0,0 +1,7 @@ +build +*.pyc +.DS_Store +nohup.out +build_config.mk +var +.vscode diff --git a/vendor/github.com/lunny/nodb/README.md b/vendor/github.com/lunny/nodb/README.md new file mode 100644 index 0000000000..ebba36b158 --- /dev/null +++ b/vendor/github.com/lunny/nodb/README.md @@ -0,0 +1,84 @@ +# NoDB + +[中文](https://github.com/lunny/nodb/blob/master/README_CN.md) + +Nodb is a fork of [ledisdb](https://github.com/siddontang/ledisdb) and shrink version. It's get rid of all C or other language codes and only keep Go's. It aims to provide a nosql database library rather than a redis like server. So if you want a redis like server, ledisdb is the best choose. + +Nodb is a pure Go and high performance NoSQL database library. It supports some data structure like kv, list, hash, zset, bitmap, set. + +Nodb now use [goleveldb](https://github.com/syndtr/goleveldb) as backend to store data. + +## Features + ++ Rich data structure: KV, List, Hash, ZSet, Bitmap, Set. ++ Stores lots of data, over the memory limit. ++ Supports expiration and ttl. ++ Easy to embed in your own Go application. + +## Install + + go get github.com/lunny/nodb + +## Package Example + +### Open And Select database +```go +import( + "github.com/lunny/nodb" + "github.com/lunny/nodb/config" +) + +cfg := new(config.Config) +cfg.DataDir = "./" +dbs, err := nodb.Open(cfg) +if err != nil { + fmt.Printf("nodb: error opening db: %v", err) +} + +db, _ := dbs.Select(0) +``` +### KV + +KV is the most basic nodb type like any other key-value database. +```go +err := db.Set(key, value) +value, err := db.Get(key) +``` +### List + +List is simply lists of values, sorted by insertion order. +You can push or pop value on the list head (left) or tail (right). +```go +err := db.LPush(key, value1) +err := db.RPush(key, value2) +value1, err := db.LPop(key) +value2, err := db.RPop(key) +``` +### Hash + +Hash is a map between fields and values. +```go +n, err := db.HSet(key, field1, value1) +n, err := db.HSet(key, field2, value2) +value1, err := db.HGet(key, field1) +value2, err := db.HGet(key, field2) +``` +### ZSet + +ZSet is a sorted collections of values. +Every member of zset is associated with score, a int64 value which used to sort, from smallest to greatest score. +Members are unique, but score may be same. +```go +n, err := db.ZAdd(key, ScorePair{score1, member1}, ScorePair{score2, member2}) +ay, err := db.ZRangeByScore(key, minScore, maxScore, 0, -1) +``` +## Links + ++ [Ledisdb Official Website](http://ledisdb.com) ++ [GoDoc](https://godoc.org/github.com/lunny/nodb) ++ [GoWalker](https://gowalker.org/github.com/lunny/nodb) + + +## Thanks + +Gmail: siddontang@gmail.com diff --git a/vendor/github.com/lunny/nodb/README_CN.md b/vendor/github.com/lunny/nodb/README_CN.md new file mode 100644 index 0000000000..6fa286e393 --- /dev/null +++ b/vendor/github.com/lunny/nodb/README_CN.md @@ -0,0 +1,81 @@ +# NoDB + +[English](https://github.com/lunny/nodb/blob/master/README.md) + +Nodb 是 [ledisdb](https://github.com/siddontang/ledisdb) 的克隆和缩减版本。该版本去掉了所有C和其它语言的依赖,只保留Go语言的。目标是提供一个Nosql数据库的开发库而不是提供一个像Redis那样的服务器。因此如果你想要的是一个独立服务器,你可以直接选择ledisdb。 + +Nodb 是一个纯Go的高性能 NoSQL 数据库。他支持 kv, list, hash, zset, bitmap, set 等数据结构。 + +Nodb 当前底层使用 (goleveldb)[https://github.com/syndtr/goleveldb] 来存储数据。 + +## 特性 + ++ 丰富的数据结构支持: KV, List, Hash, ZSet, Bitmap, Set。 ++ 永久存储并且不受内存的限制。 ++ 高性能那个。 ++ 可以方便的嵌入到你的应用程序中。 + +## 安装 + + go get github.com/lunny/nodb + +## 例子 + +### 打开和选择数据库 +```go +import( + "github.com/lunny/nodb" + "github.com/lunny/nodb/config" +) + +cfg := new(config.Config) +cfg.DataDir = "./" +dbs, err := nodb.Open(cfg) +if err != nil { + fmt.Printf("nodb: error opening db: %v", err) +} +db, _ := dbs.Select(0) +``` +### KV + +KV 是最基础的功能,和其它Nosql一样。 +```go +err := db.Set(key, value) +value, err := db.Get(key) +``` +### List + +List 是一些值的简单列表,按照插入的顺序排列。你可以从左或右push和pop值。 +```go +err := db.LPush(key, value1) +err := db.RPush(key, value2) +value1, err := db.LPop(key) +value2, err := db.RPop(key) +``` +### Hash + +Hash 是一个field和value对应的map。 +```go +n, err := db.HSet(key, field1, value1) +n, err := db.HSet(key, field2, value2) +value1, err := db.HGet(key, field1) +value2, err := db.HGet(key, field2) +``` +### ZSet + +ZSet 是一个排序的值集合。zset的每个成员对应一个score,这是一个int64的值用于从小到大排序。成员不可重复,但是score可以相同。 +```go +n, err := db.ZAdd(key, ScorePair{score1, member1}, ScorePair{score2, member2}) +ay, err := db.ZRangeByScore(key, minScore, maxScore, 0, -1) +``` + +## 链接 + ++ [Ledisdb Official Website](http://ledisdb.com) ++ [GoDoc](https://godoc.org/github.com/lunny/nodb) ++ [GoWalker](https://gowalker.org/github.com/lunny/nodb) + + +## 感谢 + +Gmail: siddontang@gmail.com diff --git a/vendor/github.com/lunny/nodb/config/config.toml b/vendor/github.com/lunny/nodb/config/config.toml new file mode 100644 index 0000000000..2a3a2466e0 --- /dev/null +++ b/vendor/github.com/lunny/nodb/config/config.toml @@ -0,0 +1,45 @@ +# LedisDB configuration + +# Server listen address +addr = "127.0.0.1:6380" + +# Server http listen address, set empty to disable +http_addr = "127.0.0.1:11181" + +# Data store path, all ledisdb's data will be saved here +data_dir = "/tmp/ledis_server" + +# Log server command, set empty to disable +access_log = "" + +# Set slaveof to enable replication from master, empty, no replication +slaveof = "" + +# Choose which backend storage to use, now support: +# +# leveldb +# rocksdb +# goleveldb +# lmdb +# boltdb +# hyperleveldb +# memory +# +db_name = "leveldb" + +[leveldb] +compression = false +block_size = 32768 +write_buffer_size = 67108864 +cache_size = 524288000 +max_open_files = 1024 + +[lmdb] +map_size = 524288000 +nosync = true + +[binlog] +max_file_size = 0 +max_file_num = 0 + + diff --git a/vendor/github.com/markbates/goth/.gitignore b/vendor/github.com/markbates/goth/.gitignore new file mode 100644 index 0000000000..4f39cfc631 --- /dev/null +++ b/vendor/github.com/markbates/goth/.gitignore @@ -0,0 +1,30 @@ +*.log +.DS_Store +doc +tmp +pkg +*.gem +*.pid +coverage +coverage.data +build/* +*.pbxuser +*.mode1v3 +.svn +profile +.console_history +.sass-cache/* +.rake_tasks~ +*.log.lck +solr/ +.jhw-cache/ +jhw.* +*.sublime* +node_modules/ +dist/ +generated/ +.vendor/ +*.swp +.vscode/launch.json +.vscode/settings.json +.idea diff --git a/vendor/github.com/markbates/goth/.travis.yml b/vendor/github.com/markbates/goth/.travis.yml new file mode 100644 index 0000000000..5b2f9fe132 --- /dev/null +++ b/vendor/github.com/markbates/goth/.travis.yml @@ -0,0 +1,16 @@ +language: go + +sudo: false + +go: + - 1.7 + - 1.8 + - 1.9 + - "1.10" + - "1.11" + - tip + +matrix: + allow_failures: + - go: 'tip' + diff --git a/vendor/github.com/markbates/goth/README.md b/vendor/github.com/markbates/goth/README.md new file mode 100644 index 0000000000..c74f8773c6 --- /dev/null +++ b/vendor/github.com/markbates/goth/README.md @@ -0,0 +1,141 @@ +# Goth: Multi-Provider Authentication for Go [![GoDoc](https://godoc.org/github.com/markbates/goth?status.svg)](https://godoc.org/github.com/markbates/goth) [![Build Status](https://travis-ci.org/markbates/goth.svg)](https://travis-ci.org/markbates/goth) + +Package goth provides a simple, clean, and idiomatic way to write authentication +packages for Go web applications. + +Unlike other similar packages, Goth, lets you write OAuth, OAuth2, or any other +protocol providers, as long as they implement the `Provider` and `Session` interfaces. + +This package was inspired by [https://github.com/intridea/omniauth](https://github.com/intridea/omniauth). + +## Installation + +```text +$ go get github.com/markbates/goth +``` + +## Supported Providers + +* Amazon +* Auth0 +* Azure AD +* Battle.net +* Bitbucket +* Box +* Cloud Foundry +* Dailymotion +* Deezer +* Digital Ocean +* Discord +* Dropbox +* Eve Online +* Facebook +* Fitbit +* GitHub +* Gitlab +* Google +* Google+ (deprecated) +* Heroku +* InfluxCloud +* Instagram +* Intercom +* Lastfm +* Linkedin +* Meetup +* MicrosoftOnline +* Naver +* OneDrive +* OpenID Connect (auto discovery) +* Paypal +* SalesForce +* Slack +* Soundcloud +* Spotify +* Steam +* Stripe +* Tumblr +* Twitch +* Twitter +* Typetalk +* Uber +* VK +* Wepay +* Xero +* Yahoo +* Yammer +* Yandex + +## Examples + +See the [examples](examples) folder for a working application that lets users authenticate +through Twitter, Facebook, Google Plus etc. + +To run the example either clone the source from GitHub + +```text +$ git clone git@github.com:markbates/goth.git +``` +or use +```text +$ go get github.com/markbates/goth +``` +```text +$ cd goth/examples +$ go get -v +$ go build +$ ./examples +``` + +Now open up your browser and go to [http://localhost:3000](http://localhost:3000) to see the example. + +To actually use the different providers, please make sure you set environment variables. Example given in the examples/main.go file + +## Security Notes + +By default, gothic uses a `CookieStore` from the `gorilla/sessions` package to store session data. + +As configured, this default store (`gothic.Store`) will generate cookies with `Options`: + +```go +&Options{ + Path: "/", + Domain: "", + MaxAge: 86400 * 30, + HttpOnly: true, + Secure: false, + } +``` + +To tailor these fields for your application, you can override the `gothic.Store` variable at startup. + +The following snippet shows one way to do this: + +```go +key := "" // Replace with your SESSION_SECRET or similar +maxAge := 86400 * 30 // 30 days +isProd := false // Set to true when serving over https + +store := sessions.NewCookieStore([]byte(key)) +store.MaxAge(maxAge) +store.Options.Path = "/" +store.Options.HttpOnly = true // HttpOnly should always be enabled +store.Options.Secure = isProd + +gothic.Store = store +``` + +## Issues + +Issues always stand a significantly better chance of getting fixed if they are accompanied by a +pull request. + +## Contributing + +Would I love to see more providers? Certainly! Would you love to contribute one? Hopefully, yes! + +1. Fork it +2. Create your feature branch (git checkout -b my-new-feature) +3. Write Tests! +4. Commit your changes (git commit -am 'Add some feature') +5. Push to the branch (git push origin my-new-feature) +6. Create new Pull Request diff --git a/vendor/github.com/markbates/goth/go.mod b/vendor/github.com/markbates/goth/go.mod new file mode 100644 index 0000000000..11b3857d79 --- /dev/null +++ b/vendor/github.com/markbates/goth/go.mod @@ -0,0 +1,17 @@ +module github.com/markbates/goth + +require ( + cloud.google.com/go v0.30.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gorilla/mux v1.6.2 + github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 + github.com/gorilla/sessions v1.1.1 + github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da + github.com/markbates/going v1.0.0 + github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.2.2 + golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd + golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect + google.golang.org/appengine v1.2.0 // indirect +) diff --git a/vendor/github.com/markbates/goth/go.sum b/vendor/github.com/markbates/goth/go.sum new file mode 100644 index 0000000000..ae43832953 --- /dev/null +++ b/vendor/github.com/markbates/goth/go.sum @@ -0,0 +1,35 @@ +cloud.google.com/go v0.30.0 h1:xKvyLgk56d0nksWq49J0UyGEeUIicTl4+UBiX1NPX9g= +cloud.google.com/go v0.30.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +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/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY= +github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY= +github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.1.1 h1:YMDmfaK68mUixINzY/XjscuJ47uXFWSSHzFbBQM0PrE= +github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= +github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da h1:FjHUJJ7oBW4G/9j1KzlHaXL09LyMVM9rupS39lncbXk= +github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= +github.com/markbates/going v1.0.0 h1:DQw0ZP7NbNlFGcKbcE/IVSOAFzScxRtLpd0rLMzLhq0= +github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA= +github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c h1:3wkDRdxK92dF+c1ke2dtj7ZzemFWBHB9plnJOtlwdFA= +github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= +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/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225 h1:kNX+jCowfMYzvlSvJu5pQWEmyWFrBXJ3PBy10xKMXK8= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd h1:QQhib242ErYDSMitlBm8V7wYCm/1a25hV8qMadIKLPA= +golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +google.golang.org/appengine v1.2.0 h1:S0iUepdCWODXRvtE+gcRDd15L+k+k1AiHlMiMjefH24= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/vendor/github.com/mattn/go-sqlite3/.gitignore b/vendor/github.com/mattn/go-sqlite3/.gitignore new file mode 100644 index 0000000000..fa0e6b5818 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/.gitignore @@ -0,0 +1,14 @@ +*.db +*.exe +*.dll +*.o + +# VSCode +.vscode + +# Exclude from upgrade +upgrade/*.c +upgrade/*.h + +# Exclude upgrade binary +upgrade/upgrade diff --git a/vendor/github.com/mattn/go-sqlite3/.travis.yml b/vendor/github.com/mattn/go-sqlite3/.travis.yml new file mode 100644 index 0000000000..2ae08beb4d --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/.travis.yml @@ -0,0 +1,41 @@ +language: go + +os: + - linux + - osx + +addons: + apt: + update: true + +env: + matrix: + - GOTAGS= + - GOTAGS=libsqlite3 + - GOTAGS="sqlite_allow_uri_authority sqlite_app_armor sqlite_foreign_keys sqlite_fts5 sqlite_icu sqlite_introspect sqlite_json sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_userauth sqlite_vacuum_incr sqlite_vtable sqlite_unlock_notify" + - GOTAGS=sqlite_vacuum_full + +go: + - 1.9.x + - 1.10.x + - 1.11.x + +before_install: + - | + if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then + brew update + fi + - | + go get github.com/smartystreets/goconvey + if [[ "${GOOS}" != "windows" ]]; then + go get github.com/mattn/goveralls + go get golang.org/x/tools/cmd/cover + fi + +script: + - GOOS=$(go env GOOS) GOARCH=$(go env GOARCH) go build -v -tags "${GOTAGS}" . + - | + if [[ "${GOOS}" != "windows" ]]; then + $HOME/gopath/bin/goveralls -repotoken 3qJVUE0iQwqnCbmNcDsjYu1nh4J4KIFXx + go test -race -v . -tags "${GOTAGS}" + fi diff --git a/vendor/github.com/mattn/go-sqlite3/README.md b/vendor/github.com/mattn/go-sqlite3/README.md new file mode 100644 index 0000000000..207f1cd1eb --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/README.md @@ -0,0 +1,519 @@ +go-sqlite3 +========== + +[![GoDoc Reference](https://godoc.org/github.com/mattn/go-sqlite3?status.svg)](http://godoc.org/github.com/mattn/go-sqlite3) +[![Build Status](https://travis-ci.org/mattn/go-sqlite3.svg?branch=master)](https://travis-ci.org/mattn/go-sqlite3) +[![Coverage Status](https://coveralls.io/repos/mattn/go-sqlite3/badge.svg?branch=master)](https://coveralls.io/r/mattn/go-sqlite3?branch=master) +[![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-sqlite3)](https://goreportcard.com/report/github.com/mattn/go-sqlite3) + +# Description + +sqlite3 driver conforming to the built-in database/sql interface + +Supported Golang version: +- 1.9.x +- 1.10.x + +[This package follows the official Golang Release Policy.](https://golang.org/doc/devel/release.html#policy) + +### Overview + +- [Installation](#installation) +- [API Reference](#api-reference) +- [Connection String](#connection-string) +- [Features](#features) +- [Compilation](#compilation) + - [Android](#android) + - [ARM](#arm) + - [Cross Compile](#cross-compile) + - [Google Cloud Platform](#google-cloud-platform) + - [Linux](#linux) + - [Alpine](#alpine) + - [Fedora](#fedora) + - [Ubuntu](#ubuntu) + - [Mac OSX](#mac-osx) + - [Windows](#windows) + - [Errors](#errors) +- [User Authentication](#user-authentication) + - [Compile](#compile) + - [Usage](#usage) +- [Extensions](#extensions) + - [Spatialite](#spatialite) +- [FAQ](#faq) +- [License](#license) + +# Installation + +This package can be installed with the go get command: + + go get github.com/mattn/go-sqlite3 + +_go-sqlite3_ is *cgo* package. +If you want to build your app using go-sqlite3, you need gcc. +However, after you have built and installed _go-sqlite3_ with `go install github.com/mattn/go-sqlite3` (which requires gcc), you can build your app without relying on gcc in future. + +***Important: because this is a `CGO` enabled package you are required to set the environment variable `CGO_ENABLED=1` and have a `gcc` compile present within your path.*** + +# API Reference + +API documentation can be found here: http://godoc.org/github.com/mattn/go-sqlite3 + +Examples can be found under the [examples](./_example) directory + +# Connection String + +When creating a new SQLite database or connection to an existing one, with the file name additional options can be given. +This is also known as a DSN string. (Data Source Name). + +Options are append after the filename of the SQLite database. +The database filename and options are seperated by an `?` (Question Mark). +Options should be URL-encoded (see [url.QueryEscape](https://golang.org/pkg/net/url/#QueryEscape)). + +This also applies when using an in-memory database instead of a file. + +Options can be given using the following format: `KEYWORD=VALUE` and multiple options can be combined with the `&` ampersand. + +This library supports dsn options of SQLite itself and provides additional options. + +Boolean values can be one of: +* `0` `no` `false` `off` +* `1` `yes` `true` `on` + +| Name | Key | Value(s) | Description | +|------|-----|----------|-------------| +| UA - Create | `_auth` | - | Create User Authentication, for more information see [User Authentication](#user-authentication) | +| UA - Username | `_auth_user` | `string` | Username for User Authentication, for more information see [User Authentication](#user-authentication) | +| UA - Password | `_auth_pass` | `string` | Password for User Authentication, for more information see [User Authentication](#user-authentication) | +| UA - Crypt | `_auth_crypt` |
  • SHA1
  • SSHA1
  • SHA256
  • SSHA256
  • SHA384
  • SSHA384
  • SHA512
  • SSHA512
| Password encoder to use for User Authentication, for more information see [User Authentication](#user-authentication) | +| UA - Salt | `_auth_salt` | `string` | Salt to use if the configure password encoder requires a salt, for User Authentication, for more information see [User Authentication](#user-authentication) | +| Auto Vacuum | `_auto_vacuum` \| `_vacuum` |
  • `0` \| `none`
  • `1` \| `full`
  • `2` \| `incremental`
| For more information see [PRAGMA auto_vacuum](https://www.sqlite.org/pragma.html#pragma_auto_vacuum) | +| Busy Timeout | `_busy_timeout` \| `_timeout` | `int` | Specify value for sqlite3_busy_timeout. For more information see [PRAGMA busy_timeout](https://www.sqlite.org/pragma.html#pragma_busy_timeout) | +| Case Sensitive LIKE | `_case_sensitive_like` \| `_cslike` | `boolean` | For more information see [PRAGMA case_sensitive_like](https://www.sqlite.org/pragma.html#pragma_case_sensitive_like) | +| Defer Foreign Keys | `_defer_foreign_keys` \| `_defer_fk` | `boolean` | For more information see [PRAGMA defer_foreign_keys](https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys) | +| Foreign Keys | `_foreign_keys` \| `_fk` | `boolean` | For more information see [PRAGMA foreign_keys](https://www.sqlite.org/pragma.html#pragma_foreign_keys) | +| Ignore CHECK Constraints | `_ignore_check_constraints` | `boolean` | For more information see [PRAGMA ignore_check_constraints](https://www.sqlite.org/pragma.html#pragma_ignore_check_constraints) | +| Immutable | `immutable` | `boolean` | For more information see [Immutable](https://www.sqlite.org/c3ref/open.html) | +| Journal Mode | `_journal_mode` \| `_journal` |
  • DELETE
  • TRUNCATE
  • PERSIST
  • MEMORY
  • WAL
  • OFF
| For more information see [PRAGMA journal_mode](https://www.sqlite.org/pragma.html#pragma_journal_mode) | +| Locking Mode | `_locking_mode` \| `_locking` |
  • NORMAL
  • EXCLUSIVE
| For more information see [PRAGMA locking_mode](https://www.sqlite.org/pragma.html#pragma_locking_mode) | +| Mode | `mode` |
  • ro
  • rw
  • rwc
  • memory
| Access Mode of the database. For more information see [SQLite Open](https://www.sqlite.org/c3ref/open.html) | +| Mutex Locking | `_mutex` |
  • no
  • full
| Specify mutex mode. | +| Query Only | `_query_only` | `boolean` | For more information see [PRAGMA query_only](https://www.sqlite.org/pragma.html#pragma_query_only) | +| Recursive Triggers | `_recursive_triggers` \| `_rt` | `boolean` | For more information see [PRAGMA recursive_triggers](https://www.sqlite.org/pragma.html#pragma_recursive_triggers) | +| Secure Delete | `_secure_delete` | `boolean` \| `FAST` | For more information see [PRAGMA secure_delete](https://www.sqlite.org/pragma.html#pragma_secure_delete) | +| Shared-Cache Mode | `cache` |
  • shared
  • private
| Set cache mode for more information see [sqlite.org](https://www.sqlite.org/sharedcache.html) | +| Synchronous | `_synchronous` \| `_sync` |
  • 0 \| OFF
  • 1 \| NORMAL
  • 2 \| FULL
  • 3 \| EXTRA
| For more information see [PRAGMA synchronous](https://www.sqlite.org/pragma.html#pragma_synchronous) | +| Time Zone Location | `_loc` | auto | Specify location of time format. | +| Transaction Lock | `_txlock` |
  • immediate
  • deferred
  • exclusive
| Specify locking behavior for transactions. | +| Writable Schema | `_writable_schema` | `Boolean` | When this pragma is on, the SQLITE_MASTER tables in which database can be changed using ordinary UPDATE, INSERT, and DELETE statements. Warning: misuse of this pragma can easily result in a corrupt database file. | + +## DSN Examples + +``` +file:test.db?cache=shared&mode=memory +``` + +# Features + +This package allows additional configuration of features available within SQLite3 to be enabled or disabled by golang build constraints also known as build `tags`. + +[Click here for more information about build tags / constraints.](https://golang.org/pkg/go/build/#hdr-Build_Constraints) + +### Usage + +If you wish to build this library with additional extensions / features. +Use the following command. + +```bash +go build --tags "" +``` + +For available features see the extension list. +When using multiple build tags, all the different tags should be space delimted. + +Example: + +```bash +go build --tags "icu json1 fts5 secure_delete" +``` + +### Feature / Extension List + +| Extension | Build Tag | Description | +|-----------|-----------|-------------| +| Additional Statistics | sqlite_stat4 | This option adds additional logic to the ANALYZE command and to the query planner that can help SQLite to chose a better query plan under certain situations. The ANALYZE command is enhanced to collect histogram data from all columns of every index and store that data in the sqlite_stat4 table.

The query planner will then use the histogram data to help it make better index choices. The downside of this compile-time option is that it violates the query planner stability guarantee making it more difficult to ensure consistent performance in mass-produced applications.

SQLITE_ENABLE_STAT4 is an enhancement of SQLITE_ENABLE_STAT3. STAT3 only recorded histogram data for the left-most column of each index whereas the STAT4 enhancement records histogram data from all columns of each index.

The SQLITE_ENABLE_STAT3 compile-time option is a no-op and is ignored if the SQLITE_ENABLE_STAT4 compile-time option is used | +| Allow URI Authority | sqlite_allow_uri_authority | URI filenames normally throws an error if the authority section is not either empty or "localhost".

However, if SQLite is compiled with the SQLITE_ALLOW_URI_AUTHORITY compile-time option, then the URI is converted into a Uniform Naming Convention (UNC) filename and passed down to the underlying operating system that way | +| App Armor | sqlite_app_armor | When defined, this C-preprocessor macro activates extra code that attempts to detect misuse of the SQLite API, such as passing in NULL pointers to required parameters or using objects after they have been destroyed.

App Armor is not available under `Windows`. | +| Disable Load Extensions | sqlite_omit_load_extension | Loading of external extensions is enabled by default.

To disable extension loading add the build tag `sqlite_omit_load_extension`. | +| Foreign Keys | sqlite_foreign_keys | This macro determines whether enforcement of foreign key constraints is enabled or disabled by default for new database connections.

Each database connection can always turn enforcement of foreign key constraints on and off and run-time using the foreign_keys pragma.

Enforcement of foreign key constraints is normally off by default, but if this compile-time parameter is set to 1, enforcement of foreign key constraints will be on by default | +| Full Auto Vacuum | sqlite_vacuum_full | Set the default auto vacuum to full | +| Incremental Auto Vacuum | sqlite_vacuum_incr | Set the default auto vacuum to incremental | +| Full Text Search Engine | sqlite_fts5 | When this option is defined in the amalgamation, versions 5 of the full-text search engine (fts5) is added to the build automatically | +| International Components for Unicode | sqlite_icu | This option causes the International Components for Unicode or "ICU" extension to SQLite to be added to the build | +| Introspect PRAGMAS | sqlite_introspect | This option adds some extra PRAGMA statements.
  • PRAGMA function_list
  • PRAGMA module_list
  • PRAGMA pragma_list
| +| JSON SQL Functions | sqlite_json | When this option is defined in the amalgamation, the JSON SQL functions are added to the build automatically | +| Secure Delete | sqlite_secure_delete | This compile-time option changes the default setting of the secure_delete pragma.

When this option is not used, secure_delete defaults to off. When this option is present, secure_delete defaults to on.

The secure_delete setting causes deleted content to be overwritten with zeros. There is a small performance penalty since additional I/O must occur.

On the other hand, secure_delete can prevent fragments of sensitive information from lingering in unused parts of the database file after it has been deleted. See the documentation on the secure_delete pragma for additional information | +| Secure Delete (FAST) | sqlite_secure_delete_fast | For more information see [PRAGMA secure_delete](https://www.sqlite.org/pragma.html#pragma_secure_delete) | +| Tracing / Debug | sqlite_trace | Activate trace functions | +| User Authentication | sqlite_userauth | SQLite User Authentication see [User Authentication](#user-authentication) for more information. | + +# Compilation + +This package requires `CGO_ENABLED=1` ennvironment variable if not set by default, and the presence of the `gcc` compiler. + +If you need to add additional CFLAGS or LDFLAGS to the build command, and do not want to modify this package. Then this can be achieved by using the `CGO_CFLAGS` and `CGO_LDFLAGS` environment variables. + +## Android + +This package can be compiled for android. +Compile with: + +```bash +go build --tags "android" +``` + +For more information see [#201](https://github.com/mattn/go-sqlite3/issues/201) + +# ARM + +To compile for `ARM` use the following environment. + +```bash +env CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ \ + CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 \ + go build -v +``` + +Additional information: +- [#242](https://github.com/mattn/go-sqlite3/issues/242) +- [#504](https://github.com/mattn/go-sqlite3/issues/504) + +# Cross Compile + +This library can be cross-compiled. + +In some cases you are required to the `CC` environment variable with the cross compiler. + +Additional information: +- [#491](https://github.com/mattn/go-sqlite3/issues/491) +- [#560](https://github.com/mattn/go-sqlite3/issues/560) + +# Google Cloud Platform + +Building on GCP is not possible because Google Cloud Platform does not allow `gcc` to be executed. + +Please work only with compiled final binaries. + +## Linux + +To compile this package on Linux you must install the development tools for your linux distribution. + +To compile under linux use the build tag `linux`. + +```bash +go build --tags "linux" +``` + +If you wish to link directly to libsqlite3 then you can use the `libsqlite3` build tag. + +``` +go build --tags "libsqlite3 linux" +``` + +### Alpine + +When building in an `alpine` container run the following command before building. + +``` +apk add --update gcc musl-dev +``` + +### Fedora + +```bash +sudo yum groupinstall "Development Tools" "Development Libraries" +``` + +### Ubuntu + +```bash +sudo apt-get install build-essential +``` + +## Mac OSX + +OSX should have all the tools present to compile this package, if not install XCode this will add all the developers tools. + +Required dependency + +```bash +brew install sqlite3 +``` + +For OSX there is an additional package install which is required if you whish to build the `icu` extension. + +This additional package can be installed with `homebrew`. + +```bash +brew upgrade icu4c +``` + +To compile for Mac OSX. + +```bash +go build --tags "darwin" +``` + +If you wish to link directly to libsqlite3 then you can use the `libsqlite3` build tag. + +``` +go build --tags "libsqlite3 darwin" +``` + +Additional information: +- [#206](https://github.com/mattn/go-sqlite3/issues/206) +- [#404](https://github.com/mattn/go-sqlite3/issues/404) + +## Windows + +To compile this package on Windows OS you must have the `gcc` compiler installed. + +1) Install a Windows `gcc` toolchain. +2) Add the `bin` folders to the Windows path if the installer did not do this by default. +3) Open a terminal for the TDM-GCC toolchain, can be found in the Windows Start menu. +4) Navigate to your project folder and run the `go build ...` command for this package. + +For example the TDM-GCC Toolchain can be found [here](ttps://sourceforge.net/projects/tdm-gcc/). + +## Errors + +- Compile error: `can not be used when making a shared object; recompile with -fPIC` + + When receiving a compile time error referencing recompile with `-FPIC` then you + are probably using a hardend system. + + You can compile the library on a hardend system with the following command. + + ```bash + go build -ldflags '-extldflags=-fno-PIC' + ``` + + More details see [#120](https://github.com/mattn/go-sqlite3/issues/120) + +- Can't build go-sqlite3 on windows 64bit. + + > Probably, you are using go 1.0, go1.0 has a problem when it comes to compiling/linking on windows 64bit. + > See: [#27](https://github.com/mattn/go-sqlite3/issues/27) + +- `go get github.com/mattn/go-sqlite3` throws compilation error. + + `gcc` throws: `internal compiler error` + + Remove the download repository from your disk and try re-install with: + + ```bash + go install github.com/mattn/go-sqlite3 + ``` + +# User Authentication + +This package supports the SQLite User Authentication module. + +## Compile + +To use the User authentication module the package has to be compiled with the tag `sqlite_userauth`. See [Features](#features). + +## Usage + +### Create protected database + +To create a database protected by user authentication provide the following argument to the connection string `_auth`. +This will enable user authentication within the database. This option however requires two additional arguments: + +- `_auth_user` +- `_auth_pass` + +When `_auth` is present on the connection string user authentication will be enabled and the provided user will be created +as an `admin` user. After initial creation, the parameter `_auth` has no effect anymore and can be omitted from the connection string. + +Example connection string: + +Create an user authentication database with user `admin` and password `admin`. + +`file:test.s3db?_auth&_auth_user=admin&_auth_pass=admin` + +Create an user authentication database with user `admin` and password `admin` and use `SHA1` for the password encoding. + +`file:test.s3db?_auth&_auth_user=admin&_auth_pass=admin&_auth_crypt=sha1` + +### Password Encoding + +The passwords within the user authentication module of SQLite are encoded with the SQLite function `sqlite_cryp`. +This function uses a ceasar-cypher which is quite insecure. +This library provides several additional password encoders which can be configured through the connection string. + +The password cypher can be configured with the key `_auth_crypt`. And if the configured password encoder also requires an +salt this can be configured with `_auth_salt`. + +#### Available Encoders + +- SHA1 +- SSHA1 (Salted SHA1) +- SHA256 +- SSHA256 (salted SHA256) +- SHA384 +- SSHA384 (salted SHA384) +- SHA512 +- SSHA512 (salted SHA512) + +### Restrictions + +Operations on the database regarding to user management can only be preformed by an administrator user. + +### Support + +The user authentication supports two kinds of users + +- administrators +- regular users + +### User Management + +User management can be done by directly using the `*SQLiteConn` or by SQL. + +#### SQL + +The following sql functions are available for user management. + +| Function | Arguments | Description | +|----------|-----------|-------------| +| `authenticate` | username `string`, password `string` | Will authenticate an user, this is done by the connection; and should not be used manually. | +| `auth_user_add` | username `string`, password `string`, admin `int` | This function will add an user to the database.
if the database is not protected by user authentication it will enable it. Argument `admin` is an integer identifying if the added user should be an administrator. Only Administrators can add administrators. | +| `auth_user_change` | username `string`, password `string`, admin `int` | Function to modify an user. Users can change their own password, but only an administrator can change the administrator flag. | +| `authUserDelete` | username `string` | Delete an user from the database. Can only be used by an administrator. The current logged in administrator cannot be deleted. This is to make sure their is always an administrator remaining. | + +These functions will return an integer. + +- 0 (SQLITE_OK) +- 23 (SQLITE_AUTH) Failed to perform due to authentication or insufficient privileges + +##### Examples + +```sql +// Autheticate user +// Create Admin User +SELECT auth_user_add('admin2', 'admin2', 1); + +// Change password for user +SELECT auth_user_change('user', 'userpassword', 0); + +// Delete user +SELECT user_delete('user'); +``` + +#### *SQLiteConn + +The following functions are available for User authentication from the `*SQLiteConn`. + +| Function | Description | +|----------|-------------| +| `Authenticate(username, password string) error` | Authenticate user | +| `AuthUserAdd(username, password string, admin bool) error` | Add user | +| `AuthUserChange(username, password string, admin bool) error` | Modify user | +| `AuthUserDelete(username string) error` | Delete user | + +### Attached database + +When using attached databases. SQLite will use the authentication from the `main` database for the attached database(s). + +# Extensions + +If you want your own extension to be listed here or you want to add a reference to an extension; please submit an Issue for this. + +## Spatialite + +Spatialite is available as an extension to SQLite, and can be used in combination with this repository. +For an example see [shaxbee/go-spatialite](https://github.com/shaxbee/go-spatialite). + +# FAQ + +- Getting insert error while query is opened. + + > You can pass some arguments into the connection string, for example, a URI. + > See: [#39](https://github.com/mattn/go-sqlite3/issues/39) + +- Do you want to cross compile? mingw on Linux or Mac? + + > See: [#106](https://github.com/mattn/go-sqlite3/issues/106) + > See also: http://www.limitlessfx.com/cross-compile-golang-app-for-windows-from-linux.html + +- Want to get time.Time with current locale + + Use `_loc=auto` in SQLite3 filename schema like `file:foo.db?_loc=auto`. + +- Can I use this in multiple routines concurrently? + + Yes for readonly. But, No for writable. See [#50](https://github.com/mattn/go-sqlite3/issues/50), [#51](https://github.com/mattn/go-sqlite3/issues/51), [#209](https://github.com/mattn/go-sqlite3/issues/209), [#274](https://github.com/mattn/go-sqlite3/issues/274). + +- Why I'm getting `no such table` error? + + Why is it racy if I use a `sql.Open("sqlite3", ":memory:")` database? + + Each connection to :memory: opens a brand new in-memory sql database, so if + the stdlib's sql engine happens to open another connection and you've only + specified ":memory:", that connection will see a brand new database. A + workaround is to use "file::memory:?mode=memory&cache=shared". Every + connection to this string will point to the same in-memory database. + + For more information see + * [#204](https://github.com/mattn/go-sqlite3/issues/204) + * [#511](https://github.com/mattn/go-sqlite3/issues/511) + +- Reading from database with large amount of goroutines fails on OSX. + + OS X limits OS-wide to not have more than 1000 files open simultaneously by default. + + For more information see [#289](https://github.com/mattn/go-sqlite3/issues/289) + +- Trying to execute a `.` (dot) command throws an error. + + Error: `Error: near ".": syntax error` + Dot command are part of SQLite3 CLI not of this library. + + You need to implement the feature or call the sqlite3 cli. + + More infomation see [#305](https://github.com/mattn/go-sqlite3/issues/305) + +- Error: `database is locked` + + When you get an database is locked. Please use the following options. + + Add to DSN: `cache=shared` + + Example: + ```go + db, err := sql.Open("sqlite3", "file:locked.sqlite?cache=shared") + ``` + + Second please set the database connections of the SQL package to 1. + + ```go + db.SetMaxOpenConn(1) + ``` + + More information see [#209](https://github.com/mattn/go-sqlite3/issues/209) + +# License + +MIT: http://mattn.mit-license.org/2018 + +sqlite3-binding.c, sqlite3-binding.h, sqlite3ext.h + +The -binding suffix was added to avoid build failures under gccgo. + +In this repository, those files are an amalgamation of code that was copied from SQLite3. The license of that code is the same as the license of SQLite3. + +# Author + +Yasuhiro Matsumoto (a.k.a mattn) + +G.J.R. Timmer diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/.gitignore b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/.gitignore new file mode 100644 index 0000000000..e16fb946bb --- /dev/null +++ b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/.gitignore @@ -0,0 +1 @@ +cover.dat diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/Makefile b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/Makefile new file mode 100644 index 0000000000..81be214370 --- /dev/null +++ b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/Makefile @@ -0,0 +1,7 @@ +all: + +cover: + go test -cover -v -coverprofile=cover.dat ./... + go tool cover -func cover.dat + +.PHONY: cover diff --git a/vendor/github.com/mcuadros/go-version/.gitignore b/vendor/github.com/mcuadros/go-version/.gitignore new file mode 100644 index 0000000000..00268614f0 --- /dev/null +++ b/vendor/github.com/mcuadros/go-version/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/mcuadros/go-version/.travis.yml b/vendor/github.com/mcuadros/go-version/.travis.yml new file mode 100644 index 0000000000..4f2ee4d973 --- /dev/null +++ b/vendor/github.com/mcuadros/go-version/.travis.yml @@ -0,0 +1 @@ +language: go diff --git a/vendor/github.com/mcuadros/go-version/README.md b/vendor/github.com/mcuadros/go-version/README.md new file mode 100644 index 0000000000..a64c0a68d9 --- /dev/null +++ b/vendor/github.com/mcuadros/go-version/README.md @@ -0,0 +1,80 @@ +go-version [![Build Status](https://travis-ci.org/mcuadros/go-version.svg?branch=master)](https://travis-ci.org/mcuadros/go-version) [![GoDoc](https://godoc.org/github.com/mcuadros/go-version?status.svg)](http://godoc.org/github.com/mcuadros/go-version) +============================== + +Version normalizer and comparison library for go, heavy based on PHP version_compare function and Version comparsion libs from [Composer](https://github.com/composer/composer) PHP project + +Installation +------------ + +The recommended way to install go-version + +``` +go get github.com/mcuadros/go-version +``` + +Examples +-------- + +How import the package + +```go +import ( + "github.com/mcuadros/go-version" +) +``` + +`version.Normalize()`: Normalizes a version string to be able to perform comparisons on it + +```go +version.Normalize("10.4.13-b") +//Returns: 10.4.13.0-beta +``` + + +`version.CompareSimple()`: Compares two normalizated version number strings + +```go +version.CompareSimple("1.2", "1.0.1") +//Returns: 1 + +version.CompareSimple("1.0rc1", "1.0") +//Returns: -1 +``` + + +`version.Compare()`: Compares two normalizated version number strings, for a particular relationship + +```go +version.Compare("1.0-dev", "1.0", "<") +//Returns: true + +version.Compare("1.0rc1", "1.0", ">=") +//Returns: false + +version.Compare("2.3.4", "v3.1.2", "<") +//Returns: true +``` + +`version.ConstrainGroup.Match()`: Match a given version againts a group of constrains, read about constraint string format at [Composer documentation](http://getcomposer.org/doc/01-basic-usage.md#package-versions) + +```go +c := version.NewConstrainGroupFromString(">2.0,<=3.0") +c.Match("2.5.0beta") +//Returns: true + +c := version.NewConstrainGroupFromString("~1.2.3") +c.Match("1.2.3.5") +//Returns: true +``` + +`version.Sort()`: Sorts a string slice of version number strings using version.CompareSimple() + +```go +version.Sort([]string{"1.10-dev", "1.0rc1", "1.0", "1.0-dev"}) +//Returns []string{"1.0-dev", "1.0rc1", "1.0", "1.10-dev"} +``` + +License +------- + +MIT, see [LICENSE](LICENSE) diff --git a/vendor/github.com/microcosm-cc/bluemonday/.coveralls.yml b/vendor/github.com/microcosm-cc/bluemonday/.coveralls.yml new file mode 100644 index 0000000000..e0c87602f0 --- /dev/null +++ b/vendor/github.com/microcosm-cc/bluemonday/.coveralls.yml @@ -0,0 +1 @@ +repo_token: x2wlA1x0X8CK45ybWpZRCVRB4g7vtkhaw diff --git a/vendor/github.com/microcosm-cc/bluemonday/.gitignore b/vendor/github.com/microcosm-cc/bluemonday/.gitignore new file mode 100644 index 0000000000..00268614f0 --- /dev/null +++ b/vendor/github.com/microcosm-cc/bluemonday/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/microcosm-cc/bluemonday/.travis.yml b/vendor/github.com/microcosm-cc/bluemonday/.travis.yml new file mode 100644 index 0000000000..5694dace7f --- /dev/null +++ b/vendor/github.com/microcosm-cc/bluemonday/.travis.yml @@ -0,0 +1,18 @@ +language: go +go: + - 1.1 + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - 1.7 + - tip +matrix: + allow_failures: + - go: tip + fast_finish: true +install: + - go get golang.org/x/net/html +script: + - go test -v ./... diff --git a/vendor/github.com/microcosm-cc/bluemonday/CONTRIBUTING.md b/vendor/github.com/microcosm-cc/bluemonday/CONTRIBUTING.md new file mode 100644 index 0000000000..e0e0c815f6 --- /dev/null +++ b/vendor/github.com/microcosm-cc/bluemonday/CONTRIBUTING.md @@ -0,0 +1,47 @@ +# Contributing to bluemonday + +Third-party patches are essential for keeping bluemonday secure and offering the features developers want. However there are a few guidelines that we need contributors to follow so that we can maintain the quality of work that developers who use bluemonday expect. + +## Getting Started + +* Make sure you have a [Github account](https://github.com/signup/free) + +## Submitting an Issue + +* Submit a ticket for your issue, assuming one does not already exist +* Clearly describe the issue including the steps to reproduce (with sample input and output) if it is a bug + +If you are reporting a security flaw, you may expect that we will provide the code to fix it for you. Otherwise you may want to submit a pull request to ensure the resolution is applied sooner rather than later: + +* Fork the repository on Github +* Issue a pull request containing code to resolve the issue + +## Submitting a Pull Request + +* Submit a ticket for your issue, assuming one does not already exist +* Describe the reason for the pull request and if applicable show some example inputs and outputs to demonstrate what the patch does +* Fork the repository on Github +* Before submitting the pull request you should + 1. Include tests for your patch, 1 test should encapsulate the entire patch and should refer to the Github issue + 1. If you have added new exposed/public functionality, you should ensure it is documented appropriately + 1. If you have added new exposed/public functionality, you should consider demonstrating how to use it within one of the helpers or shipped policies if appropriate or within a test if modifying a helper or policy is not appropriate + 1. Run all of the tests `go test -v ./...` or `make test` and ensure all tests pass + 1. Run gofmt `gofmt -w ./$*` or `make fmt` + 1. Run vet `go tool vet *.go` or `make vet` and resolve any issues + 1. Install golint using `go get -u github.com/golang/lint/golint` and run vet `golint *.go` or `make lint` and resolve every warning +* When submitting the pull request you should + 1. Note the issue(s) it resolves, i.e. `Closes #6` in the pull request comment to close issue #6 when the pull request is accepted + +Once you have submitted a pull request, we *may* merge it without changes. If we have any comments or feedback, or need you to make changes to your pull request we will update the Github pull request or the associated issue. We expect responses from you within two weeks, and we may close the pull request is there is no activity. + +### Contributor Licence Agreement + +We haven't gone for the formal "Sign a Contributor Licence Agreement" thing that projects like [puppet](https://cla.puppetlabs.com/), [Mojito](https://developer.yahoo.com/cocktails/mojito/cla/) and companies like [Google](http://code.google.com/legal/individual-cla-v1.0.html) are using. + +But we do need to know that we can accept and merge your contributions, so for now the act of contributing a pull request should be considered equivalent to agreeing to a contributor licence agreement, specifically: + +You accept that the act of submitting code to the bluemonday project is to grant a copyright licence to the project that is perpetual, worldwide, non-exclusive, no-charge, royalty free and irrevocable. + +You accept that all who comply with the licence of the project (BSD 3-clause) are permitted to use your contributions to the project. + +You accept, and by submitting code do declare, that you have the legal right to grant such a licence to the project and that each of the contributions is your own original creation. diff --git a/vendor/github.com/microcosm-cc/bluemonday/CREDITS.md b/vendor/github.com/microcosm-cc/bluemonday/CREDITS.md new file mode 100644 index 0000000000..4422905a3f --- /dev/null +++ b/vendor/github.com/microcosm-cc/bluemonday/CREDITS.md @@ -0,0 +1,6 @@ + +1. John Graham-Cumming http://jgc.org/ +1. Mike Samuel mikesamuel@gmail.com +1. Dmitri Shuralyov shurcooL@gmail.com +1. https://github.com/opennota +1. https://github.com/Gufran \ No newline at end of file diff --git a/vendor/github.com/microcosm-cc/bluemonday/Makefile b/vendor/github.com/microcosm-cc/bluemonday/Makefile new file mode 100644 index 0000000000..b15dc74f37 --- /dev/null +++ b/vendor/github.com/microcosm-cc/bluemonday/Makefile @@ -0,0 +1,42 @@ +# Targets: +# +# all: Builds the code locally after testing +# +# fmt: Formats the source files +# build: Builds the code locally +# vet: Vets the code +# lint: Runs lint over the code (you do not need to fix everything) +# test: Runs the tests +# cover: Gives you the URL to a nice test coverage report +# +# install: Builds, tests and installs the code locally + +.PHONY: all fmt build vet lint test cover install + +# The first target is always the default action if `make` is called without +# args we build and install into $GOPATH so that it can just be run + +all: fmt vet test install + +fmt: + @gofmt -s -w ./$* + +build: + @go build + +vet: + @go vet *.go + +lint: + @golint *.go + +test: + @go test -v ./... + +cover: COVERAGE_FILE := coverage.out +cover: + @go test -coverprofile=$(COVERAGE_FILE) && \ + cover -html=$(COVERAGE_FILE) && rm $(COVERAGE_FILE) + +install: + @go install ./... diff --git a/vendor/github.com/microcosm-cc/bluemonday/README.md b/vendor/github.com/microcosm-cc/bluemonday/README.md new file mode 100644 index 0000000000..b8508ff04a --- /dev/null +++ b/vendor/github.com/microcosm-cc/bluemonday/README.md @@ -0,0 +1,346 @@ +# bluemonday [![Build Status](https://travis-ci.org/microcosm-cc/bluemonday.svg?branch=master)](https://travis-ci.org/microcosm-cc/bluemonday) [![GoDoc](https://godoc.org/github.com/microcosm-cc/bluemonday?status.png)](https://godoc.org/github.com/microcosm-cc/bluemonday) + +bluemonday is a HTML sanitizer implemented in Go. It is fast and highly configurable. + +bluemonday takes untrusted user generated content as an input, and will return HTML that has been sanitised against a whitelist of approved HTML elements and attributes so that you can safely include the content in your web page. + +If you accept user generated content, and your server uses Go, you **need** bluemonday. + +The default policy for user generated content (`bluemonday.UGCPolicy().Sanitize()`) turns this: +```html +Hello World +``` + +Into a harmless: +```html +Hello World +``` + +And it turns this: +```html +XSS +``` + +Into this: +```html +XSS +``` + +Whilst still allowing this: +```html + + + +``` + +To pass through mostly unaltered (it gained a rel="nofollow" which is a good thing for user generated content): +```html + + + +``` + +It protects sites from [XSS](http://en.wikipedia.org/wiki/Cross-site_scripting) attacks. There are many [vectors for an XSS attack](https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet) and the best way to mitigate the risk is to sanitize user input against a known safe list of HTML elements and attributes. + +You should **always** run bluemonday **after** any other processing. + +If you use [blackfriday](https://github.com/russross/blackfriday) or [Pandoc](http://johnmacfarlane.net/pandoc/) then bluemonday should be run after these steps. This ensures that no insecure HTML is introduced later in your process. + +bluemonday is heavily inspired by both the [OWASP Java HTML Sanitizer](https://code.google.com/p/owasp-java-html-sanitizer/) and the [HTML Purifier](http://htmlpurifier.org/). + +## Technical Summary + +Whitelist based, you need to either build a policy describing the HTML elements and attributes to permit (and the `regexp` patterns of attributes), or use one of the supplied policies representing good defaults. + +The policy containing the whitelist is applied using a fast non-validating, forward only, token-based parser implemented in the [Go net/html library](https://godoc.org/golang.org/x/net/html) by the core Go team. + +We expect to be supplied with well-formatted HTML (closing elements for every applicable open element, nested correctly) and so we do not focus on repairing badly nested or incomplete HTML. We focus on simply ensuring that whatever elements do exist are described in the policy whitelist and that attributes and links are safe for use on your web page. [GIGO](http://en.wikipedia.org/wiki/Garbage_in,_garbage_out) does apply and if you feed it bad HTML bluemonday is not tasked with figuring out how to make it good again. + +### Supported Go Versions + +bluemonday is regularly tested against Go 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7 and tip. + +We do not support Go 1.0 as we depend on `golang.org/x/net/html` which includes a reference to `io.ErrNoProgress` which did not exist in Go 1.0. + +## Is it production ready? + +*Yes* + +We are using bluemonday in production having migrated from the widely used and heavily field tested OWASP Java HTML Sanitizer. + +We are passing our extensive test suite (including AntiSamy tests as well as tests for any issues raised). Check for any [unresolved issues](https://github.com/microcosm-cc/bluemonday/issues?page=1&state=open) to see whether anything may be a blocker for you. + +We invite pull requests and issues to help us ensure we are offering comprehensive protection against various attacks via user generated content. + +## Usage + +Install in your `${GOPATH}` using `go get -u github.com/microcosm-cc/bluemonday` + +Then call it: +```go +package main + +import ( + "fmt" + + "github.com/microcosm-cc/bluemonday" +) + +func main() { + p := bluemonday.UGCPolicy() + html := p.Sanitize( + `Google`, + ) + + // Output: + // Google + fmt.Println(html) +} +``` + +We offer three ways to call Sanitize: +```go +p.Sanitize(string) string +p.SanitizeBytes([]byte) []byte +p.SanitizeReader(io.Reader) bytes.Buffer +``` + +If you are obsessed about performance, `p.SanitizeReader(r).Bytes()` will return a `[]byte` without performing any unnecessary casting of the inputs or outputs. Though the difference is so negligible you should never need to care. + +You can build your own policies: +```go +package main + +import ( + "fmt" + + "github.com/microcosm-cc/bluemonday" +) + +func main() { + p := bluemonday.NewPolicy() + + // Require URLs to be parseable by net/url.Parse and either: + // mailto: http:// or https:// + p.AllowStandardURLs() + + // We only allow

and + p.AllowAttrs("href").OnElements("a") + p.AllowElements("p") + + html := p.Sanitize( + `Google`, + ) + + // Output: + // Google + fmt.Println(html) +} +``` + +We ship two default policies: + +1. `bluemonday.StrictPolicy()` which can be thought of as equivalent to stripping all HTML elements and their attributes as it has nothing on it's whitelist. An example usage scenario would be blog post titles where HTML tags are not expected at all and if they are then the elements *and* the content of the elements should be stripped. This is a *very* strict policy. +2. `bluemonday.UGCPolicy()` which allows a broad selection of HTML elements and attributes that are safe for user generated content. Note that this policy does *not* whitelist iframes, object, embed, styles, script, etc. An example usage scenario would be blog post bodies where a variety of formatting is expected along with the potential for TABLEs and IMGs. + +## Policy Building + +The essence of building a policy is to determine which HTML elements and attributes are considered safe for your scenario. OWASP provide an [XSS prevention cheat sheet](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet) to help explain the risks, but essentially: + +1. Avoid anything other than the standard HTML elements +1. Avoid `script`, `style`, `iframe`, `object`, `embed`, `base` elements that allow code to be executed by the client or third party content to be included that can execute code +1. Avoid anything other than plain HTML attributes with values matched to a regexp + +Basically, you should be able to describe what HTML is fine for your scenario. If you do not have confidence that you can describe your policy please consider using one of the shipped policies such as `bluemonday.UGCPolicy()`. + +To create a new policy: +```go +p := bluemonday.NewPolicy() +``` + +To add elements to a policy either add just the elements: +```go +p.AllowElements("b", "strong") +``` + +Or add elements as a virtue of adding an attribute: +```go +// Not the recommended pattern, see the recommendation on using .Matching() below +p.AllowAttrs("nowrap").OnElements("td", "th") +``` + +Attributes can either be added to all elements: +```go +p.AllowAttrs("dir").Matching(regexp.MustCompile("(?i)rtl|ltr")).Globally() +``` + +Or attributes can be added to specific elements: +```go +// Not the recommended pattern, see the recommendation on using .Matching() below +p.AllowAttrs("value").OnElements("li") +``` + +It is **always** recommended that an attribute be made to match a pattern. XSS in HTML attributes is very easy otherwise: +```go +// \p{L} matches unicode letters, \p{N} matches unicode numbers +p.AllowAttrs("title").Matching(regexp.MustCompile(`[\p{L}\p{N}\s\-_',:\[\]!\./\\\(\)&]*`)).Globally() +``` + +You can stop at any time and call .Sanitize(): +```go +// string htmlIn passed in from a HTTP POST +htmlOut := p.Sanitize(htmlIn) +``` + +And you can take any existing policy and extend it: +```go +p := bluemonday.UGCPolicy() +p.AllowElements("fieldset", "select", "option") +``` + +### Links + +Links are difficult beasts to sanitise safely and also one of the biggest attack vectors for malicious content. + +It is possible to do this: +```go +p.AllowAttrs("href").Matching(regexp.MustCompile(`(?i)mailto|https?`)).OnElements("a") +``` + +But that will not protect you as the regular expression is insufficient in this case to have prevented a malformed value doing something unexpected. + +We provide some additional global options for safely working with links. + +`RequireParseableURLs` will ensure that URLs are parseable by Go's `net/url` package: +```go +p.RequireParseableURLs(true) +``` + +If you have enabled parseable URLs then the following option will `AllowRelativeURLs`. By default this is disabled (bluemonday is a whitelist tool... you need to explicitly tell us to permit things) and when disabled it will prevent all local and scheme relative URLs (i.e. `href="localpage.html"`, `href="../home.html"` and even `href="//www.google.com"` are relative): +```go +p.AllowRelativeURLs(true) +``` + +If you have enabled parseable URLs then you can whitelist the schemes (commonly called protocol when thinking of `http` and `https`) that are permitted. Bear in mind that allowing relative URLs in the above option will allow for a blank scheme: +```go +p.AllowURLSchemes("mailto", "http", "https") +``` + +Regardless of whether you have enabled parseable URLs, you can force all URLs to have a rel="nofollow" attribute. This will be added if it does not exist, but only when the `href` is valid: +```go +// This applies to "a" "area" "link" elements that have a "href" attribute +p.RequireNoFollowOnLinks(true) +``` + +We provide a convenience method that applies all of the above, but you will still need to whitelist the linkable elements for the URL rules to be applied to: +```go +p.AllowStandardURLs() +p.AllowAttrs("cite").OnElements("blockquote", "q") +p.AllowAttrs("href").OnElements("a", "area") +p.AllowAttrs("src").OnElements("img") +``` + +An additional complexity regarding links is the data URI as defined in [RFC2397](http://tools.ietf.org/html/rfc2397). The data URI allows for images to be served inline using this format: + +```html + +``` + +We have provided a helper to verify the mimetype followed by base64 content of data URIs links: + +```go +p.AllowDataURIImages() +``` + +That helper will enable GIF, JPEG, PNG and WEBP images. + +It should be noted that there is a potential [security](http://palizine.plynt.com/issues/2010Oct/bypass-xss-filters/) [risk](https://capec.mitre.org/data/definitions/244.html) with the use of data URI links. You should only enable data URI links if you already trust the content. + +We also have some features to help deal with user generated content: +```go +p.AddTargetBlankToFullyQualifiedLinks(true) +``` + +This will ensure that anchor `` links that are fully qualified (the href destination includes a host name) will get `target="_blank"` added to them. + +Additionally any link that has `target="_blank"` after the policy has been applied will also have the `rel` attribute adjusted to add `noopener`. This means a link may start like `` and will end up as ``. It is important to note that the addition of `noopener` is a security feature and not an issue. There is an unfortunate feature to browsers that a browser window opened as a result of `target="_blank"` can still control the opener (your web page) and this protects against that. The background to this can be found here: [https://dev.to/ben/the-targetblank-vulnerability-by-example](https://dev.to/ben/the-targetblank-vulnerability-by-example) + +### Policy Building Helpers + +We also bundle some helpers to simplify policy building: +```go + +// Permits the "dir", "id", "lang", "title" attributes globally +p.AllowStandardAttributes() + +// Permits the "img" element and it's standard attributes +p.AllowImages() + +// Permits ordered and unordered lists, and also definition lists +p.AllowLists() + +// Permits HTML tables and all applicable elements and non-styling attributes +p.AllowTables() +``` + +### Invalid Instructions + +The following are invalid: +```go +// This does not say where the attributes are allowed, you need to add +// .Globally() or .OnElements(...) +// This will be ignored without error. +p.AllowAttrs("value") + +// This does not say where the attributes are allowed, you need to add +// .Globally() or .OnElements(...) +// This will be ignored without error. +p.AllowAttrs( + "type", +).Matching( + regexp.MustCompile("(?i)^(circle|disc|square|a|A|i|I|1)$"), +) +``` + +Both examples exhibit the same issue, they declare attributes but do not then specify whether they are whitelisted globally or only on specific elements (and which elements). Attributes belong to one or more elements, and the policy needs to declare this. + +## Limitations + +We are not yet including any tools to help whitelist and sanitize CSS. Which means that unless you wish to do the heavy lifting in a single regular expression (inadvisable), **you should not allow the "style" attribute anywhere**. + +It is not the job of bluemonday to fix your bad HTML, it is merely the job of bluemonday to prevent malicious HTML getting through. If you have mismatched HTML elements, or non-conforming nesting of elements, those will remain. But if you have well-structured HTML bluemonday will not break it. + +## TODO + +* Add support for CSS sanitisation to allow some CSS properties based on a whitelist, possibly using the [Gorilla CSS3 scanner](http://www.gorillatoolkit.org/pkg/css/scanner) +* Investigate whether devs want to blacklist elements and attributes. This would allow devs to take an existing policy (such as the `bluemonday.UGCPolicy()` ) that encapsulates 90% of what they're looking for but does more than they need, and to remove the extra things they do not want to make it 100% what they want +* Investigate whether devs want a validating HTML mode, in which the HTML elements are not just transformed into a balanced tree (every start tag has a closing tag at the correct depth) but also that elements and character data appear only in their allowed context (i.e. that a `table` element isn't a descendent of a `caption`, that `colgroup`, `thead`, `tbody`, `tfoot` and `tr` are permitted, and that character data is not permitted) + +## Development + +If you have cloned this repo you will probably need the dependency: + +`go get golang.org/x/net/html` + +Gophers can use their familiar tools: + +`go build` + +`go test` + +I personally use a Makefile as it spares typing the same args over and over whilst providing consistency for those of us who jump from language to language and enjoy just typing `make` in a project directory and watch magic happen. + +`make` will build, vet, test and install the library. + +`make clean` will remove the library from a *single* `${GOPATH}/pkg` directory tree + +`make test` will run the tests + +`make cover` will run the tests and *open a browser window* with the coverage report + +`make lint` will run golint (install via `go get github.com/golang/lint/golint`) + +## Long term goals + +1. Open the code to adversarial peer review similar to the [Attack Review Ground Rules](https://code.google.com/p/owasp-java-html-sanitizer/wiki/AttackReviewGroundRules) +1. Raise funds and pay for an external security review diff --git a/vendor/github.com/mitchellh/go-homedir/README.md b/vendor/github.com/mitchellh/go-homedir/README.md new file mode 100644 index 0000000000..d70706d5b3 --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/README.md @@ -0,0 +1,14 @@ +# go-homedir + +This is a Go library for detecting the user's home directory without +the use of cgo, so the library can be used in cross-compilation environments. + +Usage is incredibly simple, just call `homedir.Dir()` to get the home directory +for a user, and `homedir.Expand()` to expand the `~` in a path to the home +directory. + +**Why not just use `os/user`?** The built-in `os/user` package requires +cgo on Darwin systems. This means that any Go code that uses that package +cannot cross compile. But 99% of the time the use for `os/user` is just to +retrieve the home directory, which we can do for the current user without +cgo. This library does that, enabling cross-compilation. diff --git a/vendor/github.com/mitchellh/go-homedir/go.mod b/vendor/github.com/mitchellh/go-homedir/go.mod new file mode 100644 index 0000000000..7efa09a043 --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/go.mod @@ -0,0 +1 @@ +module github.com/mitchellh/go-homedir diff --git a/vendor/github.com/mrjones/oauth/MIT-LICENSE.txt b/vendor/github.com/mrjones/oauth/MIT-LICENSE.txt new file mode 100644 index 0000000000..6c9461e6c6 --- /dev/null +++ b/vendor/github.com/mrjones/oauth/MIT-LICENSE.txt @@ -0,0 +1,7 @@ +Copyright (C) 2013 Matthew R. Jones + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/mrjones/oauth/README.md b/vendor/github.com/mrjones/oauth/README.md new file mode 100644 index 0000000000..c0f7eb5479 --- /dev/null +++ b/vendor/github.com/mrjones/oauth/README.md @@ -0,0 +1,51 @@ +OAuth 1.0 Library for [Go](http://golang.org) +======================== + +[![GoDoc](http://godoc.org/github.com/mrjones/oauth?status.png)](http://godoc.org/github.com/mrjones/oauth) + +[![CircleCI](https://circleci.com/gh/mrjones/oauth/tree/master.svg?style=svg)](https://circleci.com/gh/mrjones/oauth/tree/master) + +(If you need an OAuth 2.0 library, check out: https://godoc.org/golang.org/x/oauth2) + +Developing your own apps, with this library +------------------------------------------- + +* First, install the library + + go get github.com/mrjones/oauth + +* Then, check out the comments in oauth.go + +* Or, have a look at the examples: + + * Netflix + + go run examples/netflix/netflix.go --consumerkey [key] --consumersecret [secret] --appname [appname] + + * Twitter + + Command line: + + go run examples/twitter/twitter.go --consumerkey [key] --consumersecret [secret] + + Or, in the browser (using an HTTP server): + + go run examples/twitterserver/twitterserver.go --consumerkey [key] --consumersecret [secret] --port 8888 + + * The Google Latitude example is broken, now that Google uses OAuth 2.0 + +Contributing to this library +---------------------------- + +* Please install the pre-commit hook, which will run tests, and go-fmt before committing. + + ln -s $PWD/pre-commit.sh .git/hooks/pre-commit + +* Running tests and building is as you'd expect: + + go test *.go + go build *.go + + + + diff --git a/vendor/github.com/mrjones/oauth/oauth.go b/vendor/github.com/mrjones/oauth/oauth.go index 95eee64abd..f16edb83dd 100644 --- a/vendor/github.com/mrjones/oauth/oauth.go +++ b/vendor/github.com/mrjones/oauth/oauth.go @@ -142,7 +142,7 @@ type ServiceProvider struct { // Allow parameters to be passed in the query string rather // than the body. // See https://github.com/mrjones/oauth/pull/63 - SignQueryParams bool + SignQueryParams bool } func (sp *ServiceProvider) httpMethod() string { @@ -451,8 +451,10 @@ func (c *Consumer) AuthorizeToken(rtoken *RequestToken, verificationCode string) func (c *Consumer) AuthorizeTokenWithParams(rtoken *RequestToken, verificationCode string, additionalParams map[string]string) (atoken *AccessToken, err error) { params := map[string]string{ - VERIFIER_PARAM: verificationCode, - TOKEN_PARAM: rtoken.Token, + TOKEN_PARAM: rtoken.Token, + } + if verificationCode != "" { + params[VERIFIER_PARAM] = verificationCode } return c.makeAccessTokenRequestWithParams(params, rtoken.Secret, additionalParams) } @@ -674,8 +676,12 @@ func (c *Consumer) makeAuthorizedRequestReader(method string, urlString string, } else { // TODO(mrjones): validate that we're not overrideing an exising body? - request.Body = ioutil.NopCloser(strings.NewReader(vals.Encode())) request.ContentLength = int64(len(vals.Encode())) + if request.ContentLength == 0 { + request.Body = nil + } else { + request.Body = ioutil.NopCloser(strings.NewReader(vals.Encode())) + } } for k, vs := range c.AdditionalHeaders { @@ -781,6 +787,25 @@ func canonicalizeUrl(u *url.URL) string { return buf.String() } +func getBody(request *http.Request) ([]byte, error) { + if request.Body == nil { + return nil, nil + } + defer request.Body.Close() + originalBody, err := ioutil.ReadAll(request.Body) + if err != nil { + return nil, err + } + + // We have to re-install the body (because we've ruined it by reading it). + if len(originalBody) > 0 { + request.Body = ioutil.NopCloser(bytes.NewReader(originalBody)) + } else { + request.Body = nil + } + return originalBody, nil +} + func parseBody(request *http.Request) (map[string]string, error) { userParams := map[string]string{} @@ -797,17 +822,12 @@ func parseBody(request *http.Request) (map[string]string, error) { } } else { // x-www-form-urlencoded parameters come from the body instead: - defer request.Body.Close() - originalBody, err := ioutil.ReadAll(request.Body) + body, err := getBody(request) if err != nil { return nil, err } - // If there was a body, we have to re-install it - // (because we've ruined it by reading it). - request.Body = ioutil.NopCloser(bytes.NewReader(originalBody)) - - params, err := url.ParseQuery(string(originalBody)) + params, err := url.ParseQuery(string(body)) if err != nil { return nil, err } @@ -843,24 +863,18 @@ func calculateBodyHash(request *http.Request, s signer) (string, error) { return "", nil } - var originalBody []byte + var body []byte if request.Body != nil { var err error - - defer request.Body.Close() - originalBody, err = ioutil.ReadAll(request.Body) + body, err = getBody(request) if err != nil { return "", err } - - // If there was a body, we have to re-install it - // (because we've ruined it by reading it). - request.Body = ioutil.NopCloser(bytes.NewReader(originalBody)) } h := s.HashFunc().New() - h.Write(originalBody) + h.Write(body) rawSignature := h.Sum(nil) return base64.StdEncoding.EncodeToString(rawSignature), nil diff --git a/vendor/github.com/mrjones/oauth/pre-commit.sh b/vendor/github.com/mrjones/oauth/pre-commit.sh new file mode 100644 index 0000000000..91b9e88236 --- /dev/null +++ b/vendor/github.com/mrjones/oauth/pre-commit.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# ln -s $PWD/pre-commit.sh .git/hooks/pre-commit +go test *.go +RESULT=$? +if [[ $RESULT != 0 ]]; then + echo "REJECTING COMMIT (test failed with status: $RESULT)" + exit 1; +fi + +go fmt *.go +for e in $(ls examples); do + go build examples/$e/*.go + RESULT=$? + if [[ $RESULT != 0 ]]; then + echo "REJECTING COMMIT (Examples failed to compile)" + exit $RESULT; + fi + go fmt examples/$e/*.go +done + +exit 0 diff --git a/vendor/github.com/mschoch/smat/.gitignore b/vendor/github.com/mschoch/smat/.gitignore new file mode 100644 index 0000000000..eee880759d --- /dev/null +++ b/vendor/github.com/mschoch/smat/.gitignore @@ -0,0 +1,14 @@ +#* +*.sublime-* +*~ +.#* +.project +.settings +**/.idea/ +**/*.iml +/examples/bolt/boltsmat-fuzz.zip +/examples/bolt/workdir/ +.DS_Store +coverage.out +*.test +tags diff --git a/vendor/github.com/mschoch/smat/.travis.yml b/vendor/github.com/mschoch/smat/.travis.yml new file mode 100644 index 0000000000..3c9c346365 --- /dev/null +++ b/vendor/github.com/mschoch/smat/.travis.yml @@ -0,0 +1,16 @@ +sudo: false +language: go +go: +- 1.6 +script: +- go get golang.org/x/tools/cmd/cover +- go get github.com/mattn/goveralls +- go get github.com/kisielk/errcheck +- go test -v -race +- go vet +- errcheck ./... +- go test -coverprofile=profile.out -covermode=count +- goveralls -service=travis-ci -coverprofile=profile.out -repotoken $COVERALLS +notifications: + email: + - marty.schoch@gmail.com diff --git a/vendor/github.com/mschoch/smat/README.md b/vendor/github.com/mschoch/smat/README.md new file mode 100644 index 0000000000..f5ca1c5440 --- /dev/null +++ b/vendor/github.com/mschoch/smat/README.md @@ -0,0 +1,166 @@ +# smat – State Machine Assisted Testing + +The concept is simple, describe valid uses of your library as states and actions. States describe which actions are possible, and with what probability they should occur. Actions mutate the context and transition to another state. + +By doing this, two things are possible: + +1. Use [go-fuzz](https://github.com/dvyukov/go-fuzz) to find/test interesting sequences of operations on your library. + +2. Automate longevity testing of your application by performing long sequences of valid operations. + +**NOTE**: both of these can also incorporate validation logic (not just failure detection by building validation into the state machine) + +## Status + +The API is still not stable. This is brand new and we'll probably change things we don't like... + +[![Build Status](https://travis-ci.org/mschoch/smat.svg?branch=master)](https://travis-ci.org/mschoch/smat) +[![Coverage Status](https://coveralls.io/repos/github/mschoch/smat/badge.svg?branch=master)](https://coveralls.io/github/mschoch/smat?branch=master) +[![GoDoc](https://godoc.org/github.com/mschoch/smat?status.svg)](https://godoc.org/github.com/mschoch/smat) +[![codebeat badge](https://codebeat.co/badges/c3ff6180-a241-4128-97f0-fa6bf6f48752)](https://codebeat.co/projects/github-com-mschoch-smat) +[![Go Report Card](https://goreportcard.com/badge/github.com/mschoch/smat)](https://goreportcard.com/report/github.com/mschoch/smat) + +## License + +Apache 2.0 + +## How do I use it? + +### smat.Context + +Choose a structure to keep track of any state. You pass in an instance of this when you start, and it will be passed to every action when it executes. The actions may mutate this context. + +For example, consider a database library, once you open a database handle, you need to use it inside of the other actions. So you might use a structure like: + +``` +type context struct { + db *DB +} +``` + +### smat.State + +A state represents a state that your application/library can be in, and the probabilities thats certain actions should be taken. + +For example, consider a database library, in a state where the database is open, there many things you can do. Let's consider just two right now, you can set a value, or you can delete a value. + +``` +func dbOpen(next byte) smat.ActionID { + return smat.PercentExecute(next, + smat.PercentAction{50, setValue}, + smat.PercentAction{50, deleteValue}, + ) +} +``` + +This says that in the open state, there are two valid actions, 50% of the time you should set a value and 50% of the time you should delete a value. **NOTE**: these percentages are just for characterizing the test workload. + +### smat.Action + +Actions are functions that do some work, optionally mutate the context, and indicate the next state to transition to. Below we see an example action to set value in a database. + +``` +func setValueFunc(ctx smat.Context) (next smat.State, err error) { + // type assert to our custom context type + context := ctx.(*context) + // perform the operation + err = context.db.Set("k", "v") + if err != nil { + return nil, err + } + // return the new state + return dbOpen, nil +} +``` + +### smat.ActionID and smat.ActionMap + +Actions are just functions, and since we can't compare functions in Go, we need to introduce an external identifier for them. This allows us to build a bi-directional mapping which we'll take advantage of later. + +``` +const ( + setup smat.ActionID = iota + teardown + setValue + deleteValue +) + +var actionMap = smat.ActionMap{ + setup: setupFunc, + teardown: teardownFunc, + setValue: setValueFunc, + deleteValue: deleteValueFunc, +} +``` + +### smat.ActionSeq + +A common way that many users think about a library is as a sequence of actions to be performed. Using the ActionID's that we've already seen we can build up sequences of operations. + +``` + actionSeq := smat.ActionSeq{ + open, + setValue, + setValue, + setValue, + } +``` + +Notice that we build these actions using the constants we defined above, and because of this we can have a bi-directional mapping between a stream of bytes (driving the state machine) and a sequence of actions to be performed. + +## Fuzzing + +We've built a lot of pieces, lets wire it up to go-fuzz. + +``` +func Fuzz(data []byte) int { + return smat.Fuzz(&context{}, setup, teardown, actionMap, data) +} +``` + +* The first argument is an instance of context structure. +* The second argument is the ActionID of our setup function. The setup function does not consume any of the input stream and is used to initialize the context and determine the start state. +* The third argument is the teardown function. This will be called unconditionally to clean up any resources associated with the test. +* The fourth argument is the actionMap which maps all ActionIDs to Actions. +* The fifth argument is the data passed in from the go-fuzz application. + +### Generating Initial go-fuzz Corpus + +Earlier we mentioned the bi-directional mapping between Actions and the byte stream driving the state machine. We can now leverage this to build the inital go-fuzz corpus. + +Using the `ActinSeq`s we learned about earlier we can build up a list of them as: + + var actionSeqs = []smat.ActionSeq{...} + +Then, we can write them out to disk using: + +``` +for i, actionSeq := range actionSeqs { + byteSequence, err := actionSeq.ByteEncoding(&context{}, setup, teardown, actionMap) + if err != nil { + // handle error + } + os.MkdirAll("workdir/corpus", 0700) + ioutil.WriteFile(fmt.Sprintf("workdir/corpus/%d", i), byteSequence, 0600) +} +``` + +You can then either put this into a test case or a main application depending on your needs. + +## Longevity Testing + +Fuzzing is great, but most of your corpus is likely to be shorter meaningful sequences. And go-fuzz works to find shortest sequences that cause problems, but sometimes you actually want to explore longer sequences that appear to go-fuzz as not triggering additional code coverage. + +For these cases we have another helper you can use: + +``` + Longevity(ctx, setup, teardown, actionMap, 0, closeChan) +``` + +The first four arguments are the same, the last two are: +* random seed used to ensure repeatable tests +* closeChan (chan struct{}) - close this channel if you want the function to stop and return ErrClosed, otherwise it will run forever + +## Examples + +See the examples directory for a working example that tests some BoltDB functionality. diff --git a/vendor/github.com/msteinert/pam/.gitignore b/vendor/github.com/msteinert/pam/.gitignore new file mode 100644 index 0000000000..2d830686d4 --- /dev/null +++ b/vendor/github.com/msteinert/pam/.gitignore @@ -0,0 +1 @@ +coverage.out diff --git a/vendor/github.com/msteinert/pam/.travis.yml b/vendor/github.com/msteinert/pam/.travis.yml new file mode 100644 index 0000000000..f48afdc4c1 --- /dev/null +++ b/vendor/github.com/msteinert/pam/.travis.yml @@ -0,0 +1,18 @@ +language: go + +go: + - 1.4 + - 1.5 + - tip + +before_install: + - sudo apt-get update -qq + - sudo apt-get install -qq --no-install-recommends libpam0g-dev + - sudo useradd -d /tmp/test -p '$1$Qd8H95T5$RYSZQeoFbEB.gS19zS99A0' -s /bin/false test + - go get github.com/axw/gocov/gocov + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover + +script: + - sudo GOROOT=$GOROOT GOPATH=$GOPATH $(which go) test -v -covermode=count -coverprofile=coverage.out . + - goveralls -coverprofile=coverage.out -service travis-ci -repotoken $REPO_TOKEN diff --git a/vendor/github.com/msteinert/pam/README.md b/vendor/github.com/msteinert/pam/README.md new file mode 100644 index 0000000000..66b3820662 --- /dev/null +++ b/vendor/github.com/msteinert/pam/README.md @@ -0,0 +1,30 @@ +[![Build Status](https://travis-ci.org/msteinert/pam.svg?branch=master)](https://travis-ci.org/msteinert/pam) +[![GoDoc](https://godoc.org/github.com/msteinert/pam?status.svg)](http://godoc.org/github.com/msteinert/pam) +[![Coverage Status](https://coveralls.io/repos/msteinert/pam/badge.svg?branch=master)](https://coveralls.io/r/msteinert/pam?branch=master) +[![Go Report Card](http://goreportcard.com/badge/msteinert/pam)](http://goreportcard.com/report/msteinert/pam) + +# Go PAM + +This is a Go wrapper for the PAM application API. + +## Testing + +To run the full suite, the tests must be run as the root user. To setup your +system for testing, create a user named "test" with the password "secret". For +example: + +``` +$ sudo useradd test \ + -d /tmp/test \ + -p '$1$Qd8H95T5$RYSZQeoFbEB.gS19zS99A0' \ + -s /bin/false +``` + +Then execute the tests: + +``` +$ sudo GOPATH=$GOPATH $(which go) test -v +``` + +[1]: http://godoc.org/github.com/msteinert/pam +[2]: http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_ADG.html diff --git a/vendor/github.com/nfnt/resize/.travis.yml b/vendor/github.com/nfnt/resize/.travis.yml new file mode 100644 index 0000000000..57bd4a76e8 --- /dev/null +++ b/vendor/github.com/nfnt/resize/.travis.yml @@ -0,0 +1,7 @@ +language: go + +go: + - 1.1 + - 1.2 + - 1.3 + - tip diff --git a/vendor/github.com/nfnt/resize/README.md b/vendor/github.com/nfnt/resize/README.md new file mode 100644 index 0000000000..2aefa75c94 --- /dev/null +++ b/vendor/github.com/nfnt/resize/README.md @@ -0,0 +1,149 @@ +Resize +====== + +Image resizing for the [Go programming language](http://golang.org) with common interpolation methods. + +[![Build Status](https://travis-ci.org/nfnt/resize.svg)](https://travis-ci.org/nfnt/resize) + +Installation +------------ + +```bash +$ go get github.com/nfnt/resize +``` + +It's that easy! + +Usage +----- + +This package needs at least Go 1.1. Import package with + +```go +import "github.com/nfnt/resize" +``` + +The resize package provides 2 functions: + +* `resize.Resize` creates a scaled image with new dimensions (`width`, `height`) using the interpolation function `interp`. + If either `width` or `height` is set to 0, it will be set to an aspect ratio preserving value. +* `resize.Thumbnail` downscales an image preserving its aspect ratio to the maximum dimensions (`maxWidth`, `maxHeight`). + It will return the original image if original sizes are smaller than the provided dimensions. + +```go +resize.Resize(width, height uint, img image.Image, interp resize.InterpolationFunction) image.Image +resize.Thumbnail(maxWidth, maxHeight uint, img image.Image, interp resize.InterpolationFunction) image.Image +``` + +The provided interpolation functions are (from fast to slow execution time) + +- `NearestNeighbor`: [Nearest-neighbor interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation) +- `Bilinear`: [Bilinear interpolation](http://en.wikipedia.org/wiki/Bilinear_interpolation) +- `Bicubic`: [Bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation) +- `MitchellNetravali`: [Mitchell-Netravali interpolation](http://dl.acm.org/citation.cfm?id=378514) +- `Lanczos2`: [Lanczos resampling](http://en.wikipedia.org/wiki/Lanczos_resampling) with a=2 +- `Lanczos3`: [Lanczos resampling](http://en.wikipedia.org/wiki/Lanczos_resampling) with a=3 + +Which of these methods gives the best results depends on your use case. + +Sample usage: + +```go +package main + +import ( + "github.com/nfnt/resize" + "image/jpeg" + "log" + "os" +) + +func main() { + // open "test.jpg" + file, err := os.Open("test.jpg") + if err != nil { + log.Fatal(err) + } + + // decode jpeg into image.Image + img, err := jpeg.Decode(file) + if err != nil { + log.Fatal(err) + } + file.Close() + + // resize to width 1000 using Lanczos resampling + // and preserve aspect ratio + m := resize.Resize(1000, 0, img, resize.Lanczos3) + + out, err := os.Create("test_resized.jpg") + if err != nil { + log.Fatal(err) + } + defer out.Close() + + // write new image to file + jpeg.Encode(out, m, nil) +} +``` + +Caveats +------- + +* Optimized access routines are used for `image.RGBA`, `image.NRGBA`, `image.RGBA64`, `image.NRGBA64`, `image.YCbCr`, `image.Gray`, and `image.Gray16` types. All other image types are accessed in a generic way that will result in slow processing speed. +* JPEG images are stored in `image.YCbCr`. This image format stores data in a way that will decrease processing speed. A resize may be up to 2 times slower than with `image.RGBA`. + + +Downsizing Samples +------- + +Downsizing is not as simple as it might look like. Images have to be filtered before they are scaled down, otherwise aliasing might occur. +Filtering is highly subjective: Applying too much will blur the whole image, too little will make aliasing become apparent. +Resize tries to provide sane defaults that should suffice in most cases. + +### Artificial sample + +Original image +![Rings](http://nfnt.github.com/img/rings_lg_orig.png) + + + + + + + + + + + + + + +

Nearest-Neighbor

Bilinear

Bicubic

Mitchell-Netravali

Lanczos2

Lanczos3
+ +### Real-Life sample + +Original image +![Original](http://nfnt.github.com/img/IMG_3694_720.jpg) + + + + + + + + + + + + + + +

Nearest-Neighbor

Bilinear

Bicubic

Mitchell-Netravali

Lanczos2

Lanczos3
+ + +License +------- + +Copyright (c) 2012 Jan Schlicht +Resize is released under a MIT style license. diff --git a/vendor/github.com/pelletier/go-buffruneio/.gitignore b/vendor/github.com/pelletier/go-buffruneio/.gitignore new file mode 100644 index 0000000000..c56069fe26 --- /dev/null +++ b/vendor/github.com/pelletier/go-buffruneio/.gitignore @@ -0,0 +1 @@ +*.test \ No newline at end of file diff --git a/vendor/github.com/pelletier/go-buffruneio/.travis.yml b/vendor/github.com/pelletier/go-buffruneio/.travis.yml new file mode 100644 index 0000000000..9720442cd8 --- /dev/null +++ b/vendor/github.com/pelletier/go-buffruneio/.travis.yml @@ -0,0 +1,7 @@ +language: go +sudo: false +go: + - 1.3.3 + - 1.4.3 + - 1.5.3 + - tip diff --git a/vendor/github.com/pelletier/go-buffruneio/README.md b/vendor/github.com/pelletier/go-buffruneio/README.md new file mode 100644 index 0000000000..ff608b3ab8 --- /dev/null +++ b/vendor/github.com/pelletier/go-buffruneio/README.md @@ -0,0 +1,62 @@ +# buffruneio + +[![Tests Status](https://travis-ci.org/pelletier/go-buffruneio.svg?branch=master)](https://travis-ci.org/pelletier/go-buffruneio) +[![GoDoc](https://godoc.org/github.com/pelletier/go-buffruneio?status.svg)](https://godoc.org/github.com/pelletier/go-buffruneio) + +Buffruneio is a wrapper around bufio to provide buffered runes access with +unlimited unreads. + +```go +import "github.com/pelletier/go-buffruneio" +``` + +## Examples + +```go +import ( + "fmt" + "github.com/pelletier/go-buffruneio" + "strings" +) + +reader := buffruneio.NewReader(strings.NewReader("abcd")) +fmt.Println(reader.ReadRune()) // 'a' +fmt.Println(reader.ReadRune()) // 'b' +fmt.Println(reader.ReadRune()) // 'c' +reader.UnreadRune() +reader.UnreadRune() +fmt.Println(reader.ReadRune()) // 'b' +fmt.Println(reader.ReadRune()) // 'c' +``` + +## Documentation + +The documentation and additional examples are available at +[godoc.org](http://godoc.org/github.com/pelletier/go-buffruneio). + +## Contribute + +Feel free to report bugs and patches using GitHub's pull requests system on +[pelletier/go-toml](https://github.com/pelletier/go-buffruneio). Any feedback is +much appreciated! + +## LICENSE + +Copyright (c) 2016 Thomas Pelletier + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/philhofer/fwd/README.md b/vendor/github.com/philhofer/fwd/README.md new file mode 100644 index 0000000000..38349af34d --- /dev/null +++ b/vendor/github.com/philhofer/fwd/README.md @@ -0,0 +1,315 @@ + +# fwd + import "github.com/philhofer/fwd" + +The `fwd` package provides a buffered reader +and writer. Each has methods that help improve +the encoding/decoding performance of some binary +protocols. + +The `fwd.Writer` and `fwd.Reader` type provide similar +functionality to their counterparts in `bufio`, plus +a few extra utility methods that simplify read-ahead +and write-ahead. I wrote this package to improve serialization +performance for
http://github.com/tinylib/msgp, +where it provided about a 2x speedup over `bufio` for certain +workloads. However, care must be taken to understand the semantics of the +extra methods provided by this package, as they allow +the user to access and manipulate the buffer memory +directly. + +The extra methods for `fwd.Reader` are `Peek`, `Skip` +and `Next`. `(*fwd.Reader).Peek`, unlike `(*bufio.Reader).Peek`, +will re-allocate the read buffer in order to accommodate arbitrarily +large read-ahead. `(*fwd.Reader).Skip` skips the next `n` bytes +in the stream, and uses the `io.Seeker` interface if the underlying +stream implements it. `(*fwd.Reader).Next` returns a slice pointing +to the next `n` bytes in the read buffer (like `Peek`), but also +increments the read position. This allows users to process streams +in arbitrary block sizes without having to manage appropriately-sized +slices. Additionally, obviating the need to copy the data from the +buffer to another location in memory can improve performance dramatically +in CPU-bound applications. + +`fwd.Writer` only has one extra method, which is `(*fwd.Writer).Next`, which +returns a slice pointing to the next `n` bytes of the writer, and increments +the write position by the length of the returned slice. This allows users +to write directly to the end of the buffer. + + + + +## Constants +``` go +const ( + // DefaultReaderSize is the default size of the read buffer + DefaultReaderSize = 2048 +) +``` +``` go +const ( + // DefaultWriterSize is the + // default write buffer size. + DefaultWriterSize = 2048 +) +``` + + + +## type Reader +``` go +type Reader struct { + // contains filtered or unexported fields +} +``` +Reader is a buffered look-ahead reader + + + + + + + + + +### func NewReader +``` go +func NewReader(r io.Reader) *Reader +``` +NewReader returns a new *Reader that reads from 'r' + + +### func NewReaderSize +``` go +func NewReaderSize(r io.Reader, n int) *Reader +``` +NewReaderSize returns a new *Reader that +reads from 'r' and has a buffer size 'n' + + + + +### func (\*Reader) BufferSize +``` go +func (r *Reader) BufferSize() int +``` +BufferSize returns the total size of the buffer + + + +### func (\*Reader) Buffered +``` go +func (r *Reader) Buffered() int +``` +Buffered returns the number of bytes currently in the buffer + + + +### func (\*Reader) Next +``` go +func (r *Reader) Next(n int) ([]byte, error) +``` +Next returns the next 'n' bytes in the stream. +Unlike Peek, Next advances the reader position. +The returned bytes point to the same +data as the buffer, so the slice is +only valid until the next reader method call. +An EOF is considered an unexpected error. +If an the returned slice is less than the +length asked for, an error will be returned, +and the reader position will not be incremented. + + + +### func (\*Reader) Peek +``` go +func (r *Reader) Peek(n int) ([]byte, error) +``` +Peek returns the next 'n' buffered bytes, +reading from the underlying reader if necessary. +It will only return a slice shorter than 'n' bytes +if it also returns an error. Peek does not advance +the reader. EOF errors are *not* returned as +io.ErrUnexpectedEOF. + + + +### func (\*Reader) Read +``` go +func (r *Reader) Read(b []byte) (int, error) +``` +Read implements `io.Reader` + + + +### func (\*Reader) ReadByte +``` go +func (r *Reader) ReadByte() (byte, error) +``` +ReadByte implements `io.ByteReader` + + + +### func (\*Reader) ReadFull +``` go +func (r *Reader) ReadFull(b []byte) (int, error) +``` +ReadFull attempts to read len(b) bytes into +'b'. It returns the number of bytes read into +'b', and an error if it does not return len(b). +EOF is considered an unexpected error. + + + +### func (\*Reader) Reset +``` go +func (r *Reader) Reset(rd io.Reader) +``` +Reset resets the underlying reader +and the read buffer. + + + +### func (\*Reader) Skip +``` go +func (r *Reader) Skip(n int) (int, error) +``` +Skip moves the reader forward 'n' bytes. +Returns the number of bytes skipped and any +errors encountered. It is analogous to Seek(n, 1). +If the underlying reader implements io.Seeker, then +that method will be used to skip forward. + +If the reader encounters +an EOF before skipping 'n' bytes, it +returns io.ErrUnexpectedEOF. If the +underlying reader implements io.Seeker, then +those rules apply instead. (Many implementations +will not return `io.EOF` until the next call +to Read.) + + + +### func (\*Reader) WriteTo +``` go +func (r *Reader) WriteTo(w io.Writer) (int64, error) +``` +WriteTo implements `io.WriterTo` + + + +## type Writer +``` go +type Writer struct { + // contains filtered or unexported fields +} +``` +Writer is a buffered writer + + + + + + + + + +### func NewWriter +``` go +func NewWriter(w io.Writer) *Writer +``` +NewWriter returns a new writer +that writes to 'w' and has a buffer +that is `DefaultWriterSize` bytes. + + +### func NewWriterSize +``` go +func NewWriterSize(w io.Writer, size int) *Writer +``` +NewWriterSize returns a new writer +that writes to 'w' and has a buffer +that is 'size' bytes. + + + + +### func (\*Writer) BufferSize +``` go +func (w *Writer) BufferSize() int +``` +BufferSize returns the maximum size of the buffer. + + + +### func (\*Writer) Buffered +``` go +func (w *Writer) Buffered() int +``` +Buffered returns the number of buffered bytes +in the reader. + + + +### func (\*Writer) Flush +``` go +func (w *Writer) Flush() error +``` +Flush flushes any buffered bytes +to the underlying writer. + + + +### func (\*Writer) Next +``` go +func (w *Writer) Next(n int) ([]byte, error) +``` +Next returns the next 'n' free bytes +in the write buffer, flushing the writer +as necessary. Next will return `io.ErrShortBuffer` +if 'n' is greater than the size of the write buffer. +Calls to 'next' increment the write position by +the size of the returned buffer. + + + +### func (\*Writer) ReadFrom +``` go +func (w *Writer) ReadFrom(r io.Reader) (int64, error) +``` +ReadFrom implements `io.ReaderFrom` + + + +### func (\*Writer) Write +``` go +func (w *Writer) Write(p []byte) (int, error) +``` +Write implements `io.Writer` + + + +### func (\*Writer) WriteByte +``` go +func (w *Writer) WriteByte(b byte) error +``` +WriteByte implements `io.ByteWriter` + + + +### func (\*Writer) WriteString +``` go +func (w *Writer) WriteString(s string) (int, error) +``` +WriteString is analogous to Write, but it takes a string. + + + + + + + + + +- - - +Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md) \ No newline at end of file diff --git a/vendor/github.com/pkg/errors/.gitignore b/vendor/github.com/pkg/errors/.gitignore new file mode 100644 index 0000000000..daf913b1b3 --- /dev/null +++ b/vendor/github.com/pkg/errors/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml new file mode 100644 index 0000000000..d4b92663ba --- /dev/null +++ b/vendor/github.com/pkg/errors/.travis.yml @@ -0,0 +1,15 @@ +language: go +go_import_path: github.com/pkg/errors +go: + - 1.4.x + - 1.5.x + - 1.6.x + - 1.7.x + - 1.8.x + - 1.9.x + - 1.10.x + - 1.11.x + - tip + +script: + - go test -v ./... diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md new file mode 100644 index 0000000000..6483ba2afb --- /dev/null +++ b/vendor/github.com/pkg/errors/README.md @@ -0,0 +1,52 @@ +# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge) + +Package errors provides simple error handling primitives. + +`go get github.com/pkg/errors` + +The traditional error handling idiom in Go is roughly akin to +```go +if err != nil { + return err +} +``` +which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. + +## Adding context to an error + +The errors.Wrap function returns a new error that adds context to the original error. For example +```go +_, err := ioutil.ReadAll(r) +if err != nil { + return errors.Wrap(err, "read failed") +} +``` +## Retrieving the cause of an error + +Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. +```go +type causer interface { + Cause() error +} +``` +`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: +```go +switch err := errors.Cause(err).(type) { +case *MyError: + // handle specifically +default: + // unknown error +} +``` + +[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). + +## Contributing + +We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. + +Before proposing a change, please discuss your change by raising an issue. + +## License + +BSD-2-Clause diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml new file mode 100644 index 0000000000..a932eade02 --- /dev/null +++ b/vendor/github.com/pkg/errors/appveyor.yml @@ -0,0 +1,32 @@ +version: build-{build}.{branch} + +clone_folder: C:\gopath\src\github.com\pkg\errors +shallow_clone: true # for startup speed + +environment: + GOPATH: C:\gopath + +platform: + - x64 + +# http://www.appveyor.com/docs/installed-software +install: + # some helpful output for debugging builds + - go version + - go env + # pre-installed MinGW at C:\MinGW is 32bit only + # but MSYS2 at C:\msys64 has mingw64 + - set PATH=C:\msys64\mingw64\bin;%PATH% + - gcc --version + - g++ --version + +build_script: + - go install -v ./... + +test_script: + - set PATH=C:\gopath\bin;%PATH% + - go test -v ./... + +#artifacts: +# - path: '%GOPATH%\bin\*.exe' +deploy: off diff --git a/vendor/github.com/pquerna/otp/.travis.yml b/vendor/github.com/pquerna/otp/.travis.yml new file mode 100644 index 0000000000..73d38b1926 --- /dev/null +++ b/vendor/github.com/pquerna/otp/.travis.yml @@ -0,0 +1,6 @@ +language: go + +go: + - 1.5 + - 1.6 + - tip diff --git a/vendor/github.com/pquerna/otp/README.md b/vendor/github.com/pquerna/otp/README.md new file mode 100644 index 0000000000..148e8980d6 --- /dev/null +++ b/vendor/github.com/pquerna/otp/README.md @@ -0,0 +1,60 @@ +# otp: One Time Password utilities Go / Golang + +[![GoDoc](https://godoc.org/github.com/pquerna/otp?status.svg)](https://godoc.org/github.com/pquerna/otp) [![Build Status](https://travis-ci.org/pquerna/otp.svg?branch=master)](https://travis-ci.org/pquerna/otp) + +# Why One Time Passwords? + +One Time Passwords (OTPs) are an mechanism to improve security over passwords alone. When a Time-based OTP (TOTP) is stored on a user's phone, and combined with something the user knows (Password), you have an easy on-ramp to [Multi-factor authentication](http://en.wikipedia.org/wiki/Multi-factor_authentication) without adding a dependency on a SMS provider. This Password and TOTP combination is used by many popular websites including Google, Github, Facebook, Salesforce and many others. + +The `otp` library enables you to easily add TOTPs to your own application, increasing your user's security against mass-password breaches and malware. + +Because TOTP is standardized and widely deployed, there are many [mobile clients and software implementations](http://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm#Client_implementations). + +## `otp` Supports: + +* Generating QR Code images for easy user enrollment. +* Time-based One-time Password Algorithm (TOTP) (RFC 6238): Time based OTP, the most commonly used method. +* HMAC-based One-time Password Algorithm (HOTP) (RFC 4226): Counter based OTP, which TOTP is based upon. +* Generation and Validation of codes for either algorithm. + +## Implementing TOTP in your application: + +### User Enrollment + +For an example of a working enrollment work flow, [Github has documented theirs](https://help.github.com/articles/configuring-two-factor-authentication-via-a-totp-mobile-app/ +), but the basics are: + +1. Generate new TOTP Key for a User. `key,_ := totp.Generate(...)`. +1. Display the Key's Secret and QR-Code for the User. `key.Secret()` and `key.Image(...)`. +1. Test that the user can successfully use their TOTP. `totp.Validate(...)`. +1. Store TOTP Secret for the User in your backend. `key.Secret()` +1. Provide the user with "recovery codes". (See Recovery Codes bellow) + +### Code Generation + +* In either TOTP or HOTP cases, use the `GenerateCode` function and a counter or + `time.Time` struct to generate a valid code compatible with most implementations. +* For uncommon or custom settings, or to catch unlikely errors, use `GenerateCodeCustom` + in either module. + +### Validation + +1. Prompt and validate User's password as normal. +1. If the user has TOTP enabled, prompt for TOTP passcode. +1. Retrieve the User's TOTP Secret from your backend. +1. Validate the user's passcode. `totp.Validate(...)` + + +### Recovery Codes + +When a user loses access to their TOTP device, they would no longer have access to their account. Because TOTPs are often configured on mobile devices that can be lost, stolen or damaged, this is a common problem. For this reason many providers give their users "backup codes" or "recovery codes". These are a set of one time use codes that can be used instead of the TOTP. These can simply be randomly generated strings that you store in your backend. [Github's documentation provides an overview of the user experience]( +https://help.github.com/articles/downloading-your-two-factor-authentication-recovery-codes/). + + +## Improvements, bugs, adding feature, etc: + +Please [open issues in Github](https://github.com/pquerna/otp/issues) for ideas, bugs, and general thoughts. Pull requests are of course preferred :) + +## License + +`otp` is licensed under the [Apache License, Version 2.0](./LICENSE) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/.gitignore b/vendor/github.com/prometheus/client_golang/prometheus/.gitignore new file mode 100644 index 0000000000..3460f0346d --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/.gitignore @@ -0,0 +1 @@ +command-line-arguments.test diff --git a/vendor/github.com/prometheus/client_golang/prometheus/README.md b/vendor/github.com/prometheus/client_golang/prometheus/README.md new file mode 100644 index 0000000000..44986bff06 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/README.md @@ -0,0 +1 @@ +See [![go-doc](https://godoc.org/github.com/prometheus/client_golang/prometheus?status.svg)](https://godoc.org/github.com/prometheus/client_golang/prometheus). diff --git a/vendor/github.com/prometheus/client_model/ruby/LICENSE b/vendor/github.com/prometheus/client_model/ruby/LICENSE deleted file mode 100644 index 11069edd79..0000000000 --- a/vendor/github.com/prometheus/client_model/ruby/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/README.txt b/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/README.txt new file mode 100644 index 0000000000..7723656d58 --- /dev/null +++ b/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/README.txt @@ -0,0 +1,67 @@ +PACKAGE + +package goautoneg +import "bitbucket.org/ww/goautoneg" + +HTTP Content-Type Autonegotiation. + +The functions in this package implement the behaviour specified in +http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html + +Copyright (c) 2011, Open Knowledge Foundation Ltd. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + Neither the name of the Open Knowledge Foundation Ltd. nor the + names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +FUNCTIONS + +func Negotiate(header string, alternatives []string) (content_type string) +Negotiate the most appropriate content_type given the accept header +and a list of alternatives. + +func ParseAccept(header string) (accept []Accept) +Parse an Accept Header string returning a sorted list +of clauses + + +TYPES + +type Accept struct { + Type, SubType string + Q float32 + Params map[string]string +} +Structure to represent a clause in an HTTP Accept Header + + +SUBDIRECTORIES + + .hg diff --git a/vendor/github.com/prometheus/procfs/.gitignore b/vendor/github.com/prometheus/procfs/.gitignore new file mode 100644 index 0000000000..25e3659ab2 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/.gitignore @@ -0,0 +1 @@ +/fixtures/ diff --git a/vendor/github.com/prometheus/procfs/CONTRIBUTING.md b/vendor/github.com/prometheus/procfs/CONTRIBUTING.md new file mode 100644 index 0000000000..40503edbf1 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/CONTRIBUTING.md @@ -0,0 +1,18 @@ +# Contributing + +Prometheus uses GitHub to manage reviews of pull requests. + +* If you have a trivial fix or improvement, go ahead and create a pull request, + addressing (with `@...`) the maintainer of this repository (see + [MAINTAINERS.md](MAINTAINERS.md)) in the description of the pull request. + +* If you plan to do something more involved, first discuss your ideas + on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers). + This will avoid unnecessary work and surely give you and us a good deal + of inspiration. + +* Relevant coding style guidelines are the [Go Code Review + Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments) + and the _Formatting and style_ section of Peter Bourgon's [Go: Best + Practices for Production + Environments](http://peter.bourgon.org/go-in-production/#formatting-and-style). diff --git a/vendor/github.com/prometheus/procfs/MAINTAINERS.md b/vendor/github.com/prometheus/procfs/MAINTAINERS.md new file mode 100644 index 0000000000..35993c41c2 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/MAINTAINERS.md @@ -0,0 +1 @@ +* Tobias Schmidt diff --git a/vendor/github.com/prometheus/procfs/Makefile b/vendor/github.com/prometheus/procfs/Makefile new file mode 100644 index 0000000000..4d10983946 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/Makefile @@ -0,0 +1,77 @@ +# Copyright 2018 The Prometheus Authors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Ensure GOBIN is not set during build so that promu is installed to the correct path +unexport GOBIN + +GO ?= go +GOFMT ?= $(GO)fmt +FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH))) +STATICCHECK := $(FIRST_GOPATH)/bin/staticcheck +pkgs = $(shell $(GO) list ./... | grep -v /vendor/) + +PREFIX ?= $(shell pwd) +BIN_DIR ?= $(shell pwd) + +ifdef DEBUG + bindata_flags = -debug +endif + +STATICCHECK_IGNORE = + +all: format staticcheck build test + +style: + @echo ">> checking code style" + @! $(GOFMT) -d $(shell find . -path ./vendor -prune -o -name '*.go' -print) | grep '^' + +check_license: + @echo ">> checking license header" + @./scripts/check_license.sh + +test: fixtures/.unpacked sysfs/fixtures/.unpacked + @echo ">> running all tests" + @$(GO) test -race $(shell $(GO) list ./... | grep -v /vendor/ | grep -v examples) + +format: + @echo ">> formatting code" + @$(GO) fmt $(pkgs) + +vet: + @echo ">> vetting code" + @$(GO) vet $(pkgs) + +staticcheck: $(STATICCHECK) + @echo ">> running staticcheck" + @$(STATICCHECK) -ignore "$(STATICCHECK_IGNORE)" $(pkgs) + +%/.unpacked: %.ttar + ./ttar -C $(dir $*) -x -f $*.ttar + touch $@ + +update_fixtures: fixtures.ttar sysfs/fixtures.ttar + +%fixtures.ttar: %/fixtures + rm -v $(dir $*)fixtures/.unpacked + ./ttar -C $(dir $*) -c -f $*fixtures.ttar fixtures/ + +$(FIRST_GOPATH)/bin/staticcheck: + @GOOS= GOARCH= $(GO) get -u honnef.co/go/tools/cmd/staticcheck + +.PHONY: all style check_license format test vet staticcheck + +# Declaring the binaries at their default locations as PHONY targets is a hack +# to ensure the latest version is downloaded on every make execution. +# If this is not desired, copy/symlink these binaries to a different path and +# set the respective environment variables. +.PHONY: $(GOPATH)/bin/staticcheck diff --git a/vendor/github.com/prometheus/procfs/README.md b/vendor/github.com/prometheus/procfs/README.md new file mode 100644 index 0000000000..2095494719 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/README.md @@ -0,0 +1,11 @@ +# procfs + +This procfs package provides functions to retrieve system, kernel and process +metrics from the pseudo-filesystem proc. + +*WARNING*: This package is a work in progress. Its API may still break in +backwards-incompatible ways without warnings. Use it at your own risk. + +[![GoDoc](https://godoc.org/github.com/prometheus/procfs?status.png)](https://godoc.org/github.com/prometheus/procfs) +[![Build Status](https://travis-ci.org/prometheus/procfs.svg?branch=master)](https://travis-ci.org/prometheus/procfs) +[![Go Report Card](https://goreportcard.com/badge/github.com/prometheus/procfs)](https://goreportcard.com/report/github.com/prometheus/procfs) diff --git a/vendor/github.com/prometheus/procfs/fixtures.ttar b/vendor/github.com/prometheus/procfs/fixtures.ttar new file mode 100644 index 0000000000..13c831ef59 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/fixtures.ttar @@ -0,0 +1,462 @@ +# Archive created by ttar -c -f fixtures.ttar fixtures/ +Directory: fixtures +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26231 +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/cmdline +Lines: 1 +vimNULLBYTEtest.goNULLBYTE+10NULLBYTEEOF +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/comm +Lines: 1 +vim +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/cwd +SymlinkTo: /usr/bin +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/exe +SymlinkTo: /usr/bin/vim +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26231/fd +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/fd/0 +SymlinkTo: ../../symlinktargets/abc +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/fd/1 +SymlinkTo: ../../symlinktargets/def +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/fd/10 +SymlinkTo: ../../symlinktargets/xyz +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/fd/2 +SymlinkTo: ../../symlinktargets/ghi +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/fd/3 +SymlinkTo: ../../symlinktargets/uvw +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/io +Lines: 7 +rchar: 750339 +wchar: 818609 +syscr: 7405 +syscw: 5245 +read_bytes: 1024 +write_bytes: 2048 +cancelled_write_bytes: -1024 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/limits +Lines: 17 +Limit Soft Limit Hard Limit Units +Max cpu time unlimited unlimited seconds +Max file size unlimited unlimited bytes +Max data size unlimited unlimited bytes +Max stack size 8388608 unlimited bytes +Max core file size 0 unlimited bytes +Max resident set unlimited unlimited bytes +Max processes 62898 62898 processes +Max open files 2048 4096 files +Max locked memory 65536 65536 bytes +Max address space 8589934592 unlimited bytes +Max file locks unlimited unlimited locks +Max pending signals 62898 62898 signals +Max msgqueue size 819200 819200 bytes +Max nice priority 0 0 +Max realtime priority 0 0 +Max realtime timeout unlimited unlimited us +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/mountstats +Lines: 19 +device rootfs mounted on / with fstype rootfs +device sysfs mounted on /sys with fstype sysfs +device proc mounted on /proc with fstype proc +device /dev/sda1 mounted on / with fstype ext4 +device 192.168.1.1:/srv/test mounted on /mnt/nfs/test with fstype nfs4 statvers=1.1 + opts: rw,vers=4.0,rsize=1048576,wsize=1048576,namlen=255,acregmin=3,acregmax=60,acdirmin=30,acdirmax=60,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=192.168.1.5,local_lock=none + age: 13968 + caps: caps=0xfff7,wtmult=512,dtsize=32768,bsize=0,namlen=255 + nfsv4: bm0=0xfdffafff,bm1=0xf9be3e,bm2=0x0,acl=0x0,pnfs=not configured + sec: flavor=1,pseudoflavor=1 + events: 52 226 0 0 1 13 398 0 0 331 0 47 0 0 77 0 0 77 0 0 0 0 0 0 0 0 0 + bytes: 1207640230 0 0 0 1210214218 0 295483 0 + RPC iostats version: 1.0 p/v: 100003/4 (nfs) + xprt: tcp 832 0 1 0 11 6428 6428 0 12154 0 24 26 5726 + per-op statistics + NULL: 0 0 0 0 0 0 0 0 + READ: 1298 1298 0 207680 1210292152 6 79386 79407 + WRITE: 0 0 0 0 0 0 0 0 + +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26231/net +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/net/dev +Lines: 4 +Inter-| Receive | Transmit + face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed + lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + eth0: 438 5 0 0 0 0 0 0 648 8 0 0 0 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26231/ns +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/ns/mnt +SymlinkTo: mnt:[4026531840] +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/ns/net +SymlinkTo: net:[4026531993] +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/root +SymlinkTo: / +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/stat +Lines: 1 +26231 (vim) R 5392 7446 5392 34835 7446 4218880 32533 309516 26 82 1677 44 158 99 20 0 1 0 82375 56274944 1981 18446744073709551615 4194304 6294284 140736914091744 140736914087944 139965136429984 0 0 12288 1870679807 0 0 0 17 0 0 0 31 0 0 8391624 8481048 16420864 140736914093252 140736914093279 140736914093279 140736914096107 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26232 +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/cmdline +Lines: 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/comm +Lines: 1 +ata_sff +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/cwd +SymlinkTo: /does/not/exist +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26232/fd +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/fd/0 +SymlinkTo: ../../symlinktargets/abc +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/fd/1 +SymlinkTo: ../../symlinktargets/def +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/fd/2 +SymlinkTo: ../../symlinktargets/ghi +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/fd/3 +SymlinkTo: ../../symlinktargets/uvw +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/fd/4 +SymlinkTo: ../../symlinktargets/xyz +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/limits +Lines: 17 +Limit Soft Limit Hard Limit Units +Max cpu time unlimited unlimited seconds +Max file size unlimited unlimited bytes +Max data size unlimited unlimited bytes +Max stack size 8388608 unlimited bytes +Max core file size 0 unlimited bytes +Max resident set unlimited unlimited bytes +Max processes 29436 29436 processes +Max open files 1024 4096 files +Max locked memory 65536 65536 bytes +Max address space unlimited unlimited bytes +Max file locks unlimited unlimited locks +Max pending signals 29436 29436 signals +Max msgqueue size 819200 819200 bytes +Max nice priority 0 0 +Max realtime priority 0 0 +Max realtime timeout unlimited unlimited us +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/root +SymlinkTo: /does/not/exist +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/stat +Lines: 1 +33 (ata_sff) S 2 0 0 0 -1 69238880 0 0 0 0 0 0 0 0 0 -20 1 0 5 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 18446744073709551615 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26233 +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26233/cmdline +Lines: 1 +com.github.uiautomatorNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEEOF +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/584 +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/584/stat +Lines: 2 +1020 ((a b ) ( c d) ) R 28378 1020 28378 34842 1020 4218880 286 0 0 0 0 0 0 0 20 0 1 0 10839175 10395648 155 18446744073709551615 4194304 4238788 140736466511168 140736466511168 140609271124624 0 0 0 0 0 0 0 17 5 0 0 0 0 0 6336016 6337300 25579520 140736466515030 140736466515061 140736466515061 140736466518002 0 +#!/bin/cat /proc/self/stat +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/buddyinfo +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/buddyinfo/short +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/buddyinfo/short/buddyinfo +Lines: 3 +Node 0, zone +Node 0, zone +Node 0, zone +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/buddyinfo/sizemismatch +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/buddyinfo/sizemismatch/buddyinfo +Lines: 3 +Node 0, zone DMA 1 0 1 0 2 1 1 0 1 1 3 +Node 0, zone DMA32 759 572 791 475 194 45 12 0 0 0 0 0 +Node 0, zone Normal 4381 1093 185 1530 567 102 4 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/buddyinfo/valid +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/buddyinfo/valid/buddyinfo +Lines: 3 +Node 0, zone DMA 1 0 1 0 2 1 1 0 1 1 3 +Node 0, zone DMA32 759 572 791 475 194 45 12 0 0 0 0 +Node 0, zone Normal 4381 1093 185 1530 567 102 4 0 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/fs +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/fs/xfs +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/fs/xfs/stat +Lines: 23 +extent_alloc 92447 97589 92448 93751 +abt 0 0 0 0 +blk_map 1767055 188820 184891 92447 92448 2140766 0 +bmbt 0 0 0 0 +dir 185039 92447 92444 136422 +trans 706 944304 0 +ig 185045 58807 0 126238 0 33637 22 +log 2883 113448 9 17360 739 +push_ail 945014 0 134260 15483 0 3940 464 159985 0 40 +xstrat 92447 0 +rw 107739 94045 +attr 4 0 0 0 +icluster 8677 7849 135802 +vnodes 92601 0 0 0 92444 92444 92444 0 +buf 2666287 7122 2659202 3599 2 7085 0 10297 7085 +abtb2 184941 1277345 13257 13278 0 0 0 0 0 0 0 0 0 0 2746147 +abtc2 345295 2416764 172637 172658 0 0 0 0 0 0 0 0 0 0 21406023 +bmbt2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +ibt2 343004 1358467 0 0 0 0 0 0 0 0 0 0 0 0 0 +fibt2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +qm 0 0 0 0 0 0 0 0 +xpc 399724544 92823103 86219234 +debug 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/mdstat +Lines: 26 +Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] +md3 : active raid6 sda1[8] sdh1[7] sdg1[6] sdf1[5] sde1[11] sdd1[3] sdc1[10] sdb1[9] + 5853468288 blocks super 1.2 level 6, 64k chunk, algorithm 2 [8/8] [UUUUUUUU] + +md127 : active raid1 sdi2[0] sdj2[1] + 312319552 blocks [2/2] [UU] + +md0 : active raid1 sdk[2](S) sdi1[0] sdj1[1] + 248896 blocks [2/2] [UU] + +md4 : inactive raid1 sda3[0] sdb3[1] + 4883648 blocks [2/2] [UU] + +md6 : active raid1 sdb2[2] sda2[0] + 195310144 blocks [2/1] [U_] + [=>...................] recovery = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec + +md8 : active raid1 sdb1[1] sda1[0] + 195310144 blocks [2/2] [UU] + [=>...................] resync = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec + +md7 : active raid6 sdb1[0] sde1[3] sdd1[2] sdc1[1] + 7813735424 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/3] [U_UU] + bitmap: 0/30 pages [0KB], 65536KB chunk + +unused devices: +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/net +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/net/dev +Lines: 6 +Inter-| Receive | Transmit + face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed +vethf345468: 648 8 0 0 0 0 0 0 438 5 0 0 0 0 0 0 + lo: 1664039048 1566805 0 0 0 0 0 0 1664039048 1566805 0 0 0 0 0 0 +docker0: 2568 38 0 0 0 0 0 0 438 5 0 0 0 0 0 0 + eth0: 874354587 1036395 0 0 0 0 0 0 563352563 732147 0 0 0 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/net/ip_vs +Lines: 21 +IP Virtual Server version 1.2.1 (size=4096) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP C0A80016:0CEA wlc + -> C0A85216:0CEA Tunnel 100 248 2 + -> C0A85318:0CEA Tunnel 100 248 2 + -> C0A85315:0CEA Tunnel 100 248 1 +TCP C0A80039:0CEA wlc + -> C0A85416:0CEA Tunnel 0 0 0 + -> C0A85215:0CEA Tunnel 100 1499 0 + -> C0A83215:0CEA Tunnel 100 1498 0 +TCP C0A80037:0CEA wlc + -> C0A8321A:0CEA Tunnel 0 0 0 + -> C0A83120:0CEA Tunnel 100 0 0 +TCP [2620:0000:0000:0000:0000:0000:0000:0001]:0050 sh + -> [2620:0000:0000:0000:0000:0000:0000:0002]:0050 Route 1 0 0 + -> [2620:0000:0000:0000:0000:0000:0000:0003]:0050 Route 1 0 0 + -> [2620:0000:0000:0000:0000:0000:0000:0004]:0050 Route 1 1 1 +FWM 10001000 wlc + -> C0A8321A:0CEA Route 0 0 1 + -> C0A83215:0CEA Route 0 0 2 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/net/ip_vs_stats +Lines: 6 + Total Incoming Outgoing Incoming Outgoing + Conns Packets Packets Bytes Bytes + 16AA370 E33656E5 0 51D8C8883AB3 0 + + Conns/s Pkts/s Pkts/s Bytes/s Bytes/s + 4 1FB3C 0 1282A8F 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/net/rpc +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/net/rpc/nfs +Lines: 5 +net 18628 0 18628 6 +rpc 4329785 0 4338291 +proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 +proc3 22 1 4084749 29200 94754 32580 186 47747 7981 8639 0 6356 0 6962 0 7958 0 0 241 4 4 2 39 +proc4 61 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/net/rpc/nfsd +Lines: 11 +rc 0 6 18622 +fh 0 0 0 0 0 +io 157286400 0 +th 8 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 +ra 32 0 0 0 0 0 0 0 0 0 0 0 +net 18628 0 18628 6 +rpc 18628 0 0 0 0 +proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 +proc3 22 2 112 0 2719 111 0 0 0 0 0 0 0 0 0 0 0 27 216 0 2 1 0 +proc4 2 2 10853 +proc4ops 72 0 0 0 1098 2 0 0 0 0 8179 5896 0 0 0 0 5900 0 0 2 0 2 0 9609 0 2 150 1272 0 0 0 1236 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/net/xfrm_stat +Lines: 28 +XfrmInError 1 +XfrmInBufferError 2 +XfrmInHdrError 4 +XfrmInNoStates 3 +XfrmInStateProtoError 40 +XfrmInStateModeError 100 +XfrmInStateSeqError 6000 +XfrmInStateExpired 4 +XfrmInStateMismatch 23451 +XfrmInStateInvalid 55555 +XfrmInTmplMismatch 51 +XfrmInNoPols 65432 +XfrmInPolBlock 100 +XfrmInPolError 10000 +XfrmOutError 1000000 +XfrmOutBundleGenError 43321 +XfrmOutBundleCheckError 555 +XfrmOutNoStates 869 +XfrmOutStateProtoError 4542 +XfrmOutStateModeError 4 +XfrmOutStateSeqError 543 +XfrmOutStateExpired 565 +XfrmOutPolBlock 43456 +XfrmOutPolDead 7656 +XfrmOutPolError 1454 +XfrmFwdHdrError 6654 +XfrmOutStateInvalid 28765 +XfrmAcquireError 24532 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/self +SymlinkTo: 26231 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/stat +Lines: 16 +cpu 301854 612 111922 8979004 3552 2 3944 0 0 0 +cpu0 44490 19 21045 1087069 220 1 3410 0 0 0 +cpu1 47869 23 16474 1110787 591 0 46 0 0 0 +cpu2 46504 36 15916 1112321 441 0 326 0 0 0 +cpu3 47054 102 15683 1113230 533 0 60 0 0 0 +cpu4 28413 25 10776 1140321 217 0 8 0 0 0 +cpu5 29271 101 11586 1136270 672 0 30 0 0 0 +cpu6 29152 36 10276 1139721 319 0 29 0 0 0 +cpu7 29098 268 10164 1139282 555 0 31 0 0 0 +intr 8885917 17 0 0 0 0 0 0 0 1 79281 0 0 0 0 0 0 0 231237 0 0 0 0 250586 103 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 223424 190745 13 906 1283803 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +ctxt 38014093 +btime 1418183276 +processes 26442 +procs_running 2 +procs_blocked 1 +softirq 5057579 250191 1481983 1647 211099 186066 0 1783454 622196 12499 508444 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/symlinktargets +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/symlinktargets/README +Lines: 2 +This directory contains some empty files that are the symlinks the files in the "fd" directory point to. +They are otherwise ignored by the tests +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/symlinktargets/abc +Lines: 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/symlinktargets/def +Lines: 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/symlinktargets/ghi +Lines: 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/symlinktargets/uvw +Lines: 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/symlinktargets/xyz +Lines: 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/.unpacked +Lines: 0 +Mode: 664 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/prometheus/procfs/ttar b/vendor/github.com/prometheus/procfs/ttar new file mode 100644 index 0000000000..b0171a12b5 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/ttar @@ -0,0 +1,389 @@ +#!/usr/bin/env bash + +# Purpose: plain text tar format +# Limitations: - only suitable for text files, directories, and symlinks +# - stores only filename, content, and mode +# - not designed for untrusted input +# +# Note: must work with bash version 3.2 (macOS) + +# Copyright 2017 Roger Luethi +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit -o nounset + +# Sanitize environment (for instance, standard sorting of glob matches) +export LC_ALL=C + +path="" +CMD="" +ARG_STRING="$*" + +#------------------------------------------------------------------------------ +# Not all sed implementations can work on null bytes. In order to make ttar +# work out of the box on macOS, use Python as a stream editor. + +USE_PYTHON=0 + +PYTHON_CREATE_FILTER=$(cat << 'PCF' +#!/usr/bin/env python + +import re +import sys + +for line in sys.stdin: + line = re.sub(r'EOF', r'\EOF', line) + line = re.sub(r'NULLBYTE', r'\NULLBYTE', line) + line = re.sub('\x00', r'NULLBYTE', line) + sys.stdout.write(line) +PCF +) + +PYTHON_EXTRACT_FILTER=$(cat << 'PEF' +#!/usr/bin/env python + +import re +import sys + +for line in sys.stdin: + line = re.sub(r'(?/dev/null; then + echo "ERROR Python not found. Aborting." + exit 2 + fi + USE_PYTHON=1 + fi +} + +#------------------------------------------------------------------------------ + +function usage { + bname=$(basename "$0") + cat << USAGE +Usage: $bname [-C

] -c -f (create archive) + $bname -t -f (list archive contents) + $bname [-C ] -x -f (extract archive) + +Options: + -C (change directory) + -v (verbose) + +Example: Change to sysfs directory, create ttar file from fixtures directory + $bname -C sysfs -c -f sysfs/fixtures.ttar fixtures/ +USAGE +exit "$1" +} + +function vecho { + if [ "${VERBOSE:-}" == "yes" ]; then + echo >&7 "$@" + fi +} + +function set_cmd { + if [ -n "$CMD" ]; then + echo "ERROR: more than one command given" + echo + usage 2 + fi + CMD=$1 +} + +unset VERBOSE + +while getopts :cf:htxvC: opt; do + case $opt in + c) + set_cmd "create" + ;; + f) + ARCHIVE=$OPTARG + ;; + h) + usage 0 + ;; + t) + set_cmd "list" + ;; + x) + set_cmd "extract" + ;; + v) + VERBOSE=yes + exec 7>&1 + ;; + C) + CDIR=$OPTARG + ;; + *) + echo >&2 "ERROR: invalid option -$OPTARG" + echo + usage 1 + ;; + esac +done + +# Remove processed options from arguments +shift $(( OPTIND - 1 )); + +if [ "${CMD:-}" == "" ]; then + echo >&2 "ERROR: no command given" + echo + usage 1 +elif [ "${ARCHIVE:-}" == "" ]; then + echo >&2 "ERROR: no archive name given" + echo + usage 1 +fi + +function list { + local path="" + local size=0 + local line_no=0 + local ttar_file=$1 + if [ -n "${2:-}" ]; then + echo >&2 "ERROR: too many arguments." + echo + usage 1 + fi + if [ ! -e "$ttar_file" ]; then + echo >&2 "ERROR: file not found ($ttar_file)" + echo + usage 1 + fi + while read -r line; do + line_no=$(( line_no + 1 )) + if [ $size -gt 0 ]; then + size=$(( size - 1 )) + continue + fi + if [[ $line =~ ^Path:\ (.*)$ ]]; then + path=${BASH_REMATCH[1]} + elif [[ $line =~ ^Lines:\ (.*)$ ]]; then + size=${BASH_REMATCH[1]} + echo "$path" + elif [[ $line =~ ^Directory:\ (.*)$ ]]; then + path=${BASH_REMATCH[1]} + echo "$path/" + elif [[ $line =~ ^SymlinkTo:\ (.*)$ ]]; then + echo "$path -> ${BASH_REMATCH[1]}" + fi + done < "$ttar_file" +} + +function extract { + local path="" + local size=0 + local line_no=0 + local ttar_file=$1 + if [ -n "${2:-}" ]; then + echo >&2 "ERROR: too many arguments." + echo + usage 1 + fi + if [ ! -e "$ttar_file" ]; then + echo >&2 "ERROR: file not found ($ttar_file)" + echo + usage 1 + fi + while IFS= read -r line; do + line_no=$(( line_no + 1 )) + local eof_without_newline + if [ "$size" -gt 0 ]; then + if [[ "$line" =~ [^\\]EOF ]]; then + # An EOF not preceeded by a backslash indicates that the line + # does not end with a newline + eof_without_newline=1 + else + eof_without_newline=0 + fi + # Replace NULLBYTE with null byte if at beginning of line + # Replace NULLBYTE with null byte unless preceeded by backslash + # Remove one backslash in front of NULLBYTE (if any) + # Remove EOF unless preceeded by backslash + # Remove one backslash in front of EOF + if [ $USE_PYTHON -eq 1 ]; then + echo -n "$line" | python -c "$PYTHON_EXTRACT_FILTER" >> "$path" + else + # The repeated pattern makes up for sed's lack of negative + # lookbehind assertions (for consecutive null bytes). + echo -n "$line" | \ + sed -e 's/^NULLBYTE/\x0/g; + s/\([^\\]\)NULLBYTE/\1\x0/g; + s/\([^\\]\)NULLBYTE/\1\x0/g; + s/\\NULLBYTE/NULLBYTE/g; + s/\([^\\]\)EOF/\1/g; + s/\\EOF/EOF/g; + ' >> "$path" + fi + if [[ "$eof_without_newline" -eq 0 ]]; then + echo >> "$path" + fi + size=$(( size - 1 )) + continue + fi + if [[ $line =~ ^Path:\ (.*)$ ]]; then + path=${BASH_REMATCH[1]} + if [ -e "$path" ] || [ -L "$path" ]; then + rm "$path" + fi + elif [[ $line =~ ^Lines:\ (.*)$ ]]; then + size=${BASH_REMATCH[1]} + # Create file even if it is zero-length. + touch "$path" + vecho " $path" + elif [[ $line =~ ^Mode:\ (.*)$ ]]; then + mode=${BASH_REMATCH[1]} + chmod "$mode" "$path" + vecho "$mode" + elif [[ $line =~ ^Directory:\ (.*)$ ]]; then + path=${BASH_REMATCH[1]} + mkdir -p "$path" + vecho " $path/" + elif [[ $line =~ ^SymlinkTo:\ (.*)$ ]]; then + ln -s "${BASH_REMATCH[1]}" "$path" + vecho " $path -> ${BASH_REMATCH[1]}" + elif [[ $line =~ ^# ]]; then + # Ignore comments between files + continue + else + echo >&2 "ERROR: Unknown keyword on line $line_no: $line" + exit 1 + fi + done < "$ttar_file" +} + +function div { + echo "# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" \ + "- - - - - -" +} + +function get_mode { + local mfile=$1 + if [ -z "${STAT_OPTION:-}" ]; then + if stat -c '%a' "$mfile" >/dev/null 2>&1; then + # GNU stat + STAT_OPTION='-c' + STAT_FORMAT='%a' + else + # BSD stat + STAT_OPTION='-f' + # Octal output, user/group/other (omit file type, sticky bit) + STAT_FORMAT='%OLp' + fi + fi + stat "${STAT_OPTION}" "${STAT_FORMAT}" "$mfile" +} + +function _create { + shopt -s nullglob + local mode + local eof_without_newline + while (( "$#" )); do + file=$1 + if [ -L "$file" ]; then + echo "Path: $file" + symlinkTo=$(readlink "$file") + echo "SymlinkTo: $symlinkTo" + vecho " $file -> $symlinkTo" + div + elif [ -d "$file" ]; then + # Strip trailing slash (if there is one) + file=${file%/} + echo "Directory: $file" + mode=$(get_mode "$file") + echo "Mode: $mode" + vecho "$mode $file/" + div + # Find all files and dirs, including hidden/dot files + for x in "$file/"{*,.[^.]*}; do + _create "$x" + done + elif [ -f "$file" ]; then + echo "Path: $file" + lines=$(wc -l "$file"|awk '{print $1}') + eof_without_newline=0 + if [[ "$(wc -c "$file"|awk '{print $1}')" -gt 0 ]] && \ + [[ "$(tail -c 1 "$file" | wc -l)" -eq 0 ]]; then + eof_without_newline=1 + lines=$((lines+1)) + fi + echo "Lines: $lines" + # Add backslash in front of EOF + # Add backslash in front of NULLBYTE + # Replace null byte with NULLBYTE + if [ $USE_PYTHON -eq 1 ]; then + < "$file" python -c "$PYTHON_CREATE_FILTER" + else + < "$file" \ + sed 's/EOF/\\EOF/g; + s/NULLBYTE/\\NULLBYTE/g; + s/\x0/NULLBYTE/g; + ' + fi + if [[ "$eof_without_newline" -eq 1 ]]; then + # Finish line with EOF to indicate that the original line did + # not end with a linefeed + echo "EOF" + fi + mode=$(get_mode "$file") + echo "Mode: $mode" + vecho "$mode $file" + div + else + echo >&2 "ERROR: file not found ($file in $(pwd))" + exit 2 + fi + shift + done +} + +function create { + ttar_file=$1 + shift + if [ -z "${1:-}" ]; then + echo >&2 "ERROR: missing arguments." + echo + usage 1 + fi + if [ -e "$ttar_file" ]; then + rm "$ttar_file" + fi + exec > "$ttar_file" + echo "# Archive created by ttar $ARG_STRING" + _create "$@" +} + +test_environment + +if [ -n "${CDIR:-}" ]; then + if [[ "$ARCHIVE" != /* ]]; then + # Relative path: preserve the archive's location before changing + # directory + ARCHIVE="$(pwd)/$ARCHIVE" + fi + cd "$CDIR" +fi + +"$CMD" "$ARCHIVE" "$@" diff --git a/vendor/github.com/russross/blackfriday/.gitignore b/vendor/github.com/russross/blackfriday/.gitignore new file mode 100644 index 0000000000..75623dcccb --- /dev/null +++ b/vendor/github.com/russross/blackfriday/.gitignore @@ -0,0 +1,8 @@ +*.out +*.swp +*.8 +*.6 +_obj +_test* +markdown +tags diff --git a/vendor/github.com/russross/blackfriday/.travis.yml b/vendor/github.com/russross/blackfriday/.travis.yml new file mode 100644 index 0000000000..a1687f17a3 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/.travis.yml @@ -0,0 +1,30 @@ +sudo: false +language: go +go: + - 1.5.4 + - 1.6.2 + - tip +matrix: + include: + - go: 1.2.2 + script: + - go get -t -v ./... + - go test -v -race ./... + - go: 1.3.3 + script: + - go get -t -v ./... + - go test -v -race ./... + - go: 1.4.3 + script: + - go get -t -v ./... + - go test -v -race ./... + allow_failures: + - go: tip + fast_finish: true +install: + - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d -s .) + - go tool vet . + - go test -v -race ./... diff --git a/vendor/github.com/russross/blackfriday/README.md b/vendor/github.com/russross/blackfriday/README.md new file mode 100644 index 0000000000..e0066b0fc1 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/README.md @@ -0,0 +1,363 @@ +Blackfriday +[![Build Status][BuildSVG]][BuildURL] +[![Godoc][GodocV2SVG]][GodocV2URL] +=========== + +Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It +is paranoid about its input (so you can safely feed it user-supplied +data), it is fast, it supports common extensions (tables, smart +punctuation substitutions, etc.), and it is safe for all utf-8 +(unicode) input. + +HTML output is currently supported, along with Smartypants +extensions. + +It started as a translation from C of [Sundown][3]. + + +Installation +------------ + +Blackfriday is compatible with any modern Go release. With Go and git installed: + + go get -u gopkg.in/russross/blackfriday.v2 + +will download, compile, and install the package into your `$GOPATH` directory +hierarchy. + + +Versions +-------- + +Currently maintained and recommended version of Blackfriday is `v2`. It's being +developed on its own branch: https://github.com/russross/blackfriday/tree/v2 and the +documentation is available at +https://godoc.org/gopkg.in/russross/blackfriday.v2. + +It is `go get`-able via [gopkg.in][6] at `gopkg.in/russross/blackfriday.v2`, +but we highly recommend using package management tool like [dep][7] or +[Glide][8] and make use of semantic versioning. With package management you +should import `github.com/russross/blackfriday` and specify that you're using +version 2.0.0. + +Version 2 offers a number of improvements over v1: + +* Cleaned up API +* A separate call to [`Parse`][4], which produces an abstract syntax tree for + the document +* Latest bug fixes +* Flexibility to easily add your own rendering extensions + +Potential drawbacks: + +* Our benchmarks show v2 to be slightly slower than v1. Currently in the + ballpark of around 15%. +* API breakage. If you can't afford modifying your code to adhere to the new API + and don't care too much about the new features, v2 is probably not for you. +* Several bug fixes are trailing behind and still need to be forward-ported to + v2. See issue [#348](https://github.com/russross/blackfriday/issues/348) for + tracking. + +If you are still interested in the legacy `v1`, you can import it from +`github.com/russross/blackfriday`. Documentation for the legacy v1 can be found +here: https://godoc.org/github.com/russross/blackfriday + +### Known issue with `dep` + +There is a known problem with using Blackfriday v1 _transitively_ and `dep`. +Currently `dep` prioritizes semver versions over anything else, and picks the +latest one, plus it does not apply a `[[constraint]]` specifier to transitively +pulled in packages. So if you're using something that uses Blackfriday v1, but +that something does not use `dep` yet, you will get Blackfriday v2 pulled in and +your first dependency will fail to build. + +There are couple of fixes for it, documented here: +https://github.com/golang/dep/blob/master/docs/FAQ.md#how-do-i-constrain-a-transitive-dependencys-version + +Meanwhile, `dep` team is working on a more general solution to the constraints +on transitive dependencies problem: https://github.com/golang/dep/issues/1124. + + +Usage +----- + +### v1 + +For basic usage, it is as simple as getting your input into a byte +slice and calling: + + output := blackfriday.MarkdownBasic(input) + +This renders it with no extensions enabled. To get a more useful +feature set, use this instead: + + output := blackfriday.MarkdownCommon(input) + +### v2 + +For the most sensible markdown processing, it is as simple as getting your input +into a byte slice and calling: + +```go +output := blackfriday.Run(input) +``` + +Your input will be parsed and the output rendered with a set of most popular +extensions enabled. If you want the most basic feature set, corresponding with +the bare Markdown specification, use: + +```go +output := blackfriday.Run(input, blackfriday.WithNoExtensions()) +``` + +### Sanitize untrusted content + +Blackfriday itself does nothing to protect against malicious content. If you are +dealing with user-supplied markdown, we recommend running Blackfriday's output +through HTML sanitizer such as [Bluemonday][5]. + +Here's an example of simple usage of Blackfriday together with Bluemonday: + +```go +import ( + "github.com/microcosm-cc/bluemonday" + "gopkg.in/russross/blackfriday.v2" +) + +// ... +unsafe := blackfriday.Run(input) +html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) +``` + +### Custom options, v1 + +If you want to customize the set of options, first get a renderer +(currently only the HTML output engine), then use it to +call the more general `Markdown` function. For examples, see the +implementations of `MarkdownBasic` and `MarkdownCommon` in +`markdown.go`. + +### Custom options, v2 + +If you want to customize the set of options, use `blackfriday.WithExtensions`, +`blackfriday.WithRenderer` and `blackfriday.WithRefOverride`. + +### `blackfriday-tool` + +You can also check out `blackfriday-tool` for a more complete example +of how to use it. Download and install it using: + + go get github.com/russross/blackfriday-tool + +This is a simple command-line tool that allows you to process a +markdown file using a standalone program. You can also browse the +source directly on github if you are just looking for some example +code: + +* + +Note that if you have not already done so, installing +`blackfriday-tool` will be sufficient to download and install +blackfriday in addition to the tool itself. The tool binary will be +installed in `$GOPATH/bin`. This is a statically-linked binary that +can be copied to wherever you need it without worrying about +dependencies and library versions. + +### Sanitized anchor names + +Blackfriday includes an algorithm for creating sanitized anchor names +corresponding to a given input text. This algorithm is used to create +anchors for headings when `EXTENSION_AUTO_HEADER_IDS` is enabled. The +algorithm has a specification, so that other packages can create +compatible anchor names and links to those anchors. + +The specification is located at https://godoc.org/github.com/russross/blackfriday#hdr-Sanitized_Anchor_Names. + +[`SanitizedAnchorName`](https://godoc.org/github.com/russross/blackfriday#SanitizedAnchorName) exposes this functionality, and can be used to +create compatible links to the anchor names generated by blackfriday. +This algorithm is also implemented in a small standalone package at +[`github.com/shurcooL/sanitized_anchor_name`](https://godoc.org/github.com/shurcooL/sanitized_anchor_name). It can be useful for clients +that want a small package and don't need full functionality of blackfriday. + + +Features +-------- + +All features of Sundown are supported, including: + +* **Compatibility**. The Markdown v1.0.3 test suite passes with + the `--tidy` option. Without `--tidy`, the differences are + mostly in whitespace and entity escaping, where blackfriday is + more consistent and cleaner. + +* **Common extensions**, including table support, fenced code + blocks, autolinks, strikethroughs, non-strict emphasis, etc. + +* **Safety**. Blackfriday is paranoid when parsing, making it safe + to feed untrusted user input without fear of bad things + happening. The test suite stress tests this and there are no + known inputs that make it crash. If you find one, please let me + know and send me the input that does it. + + NOTE: "safety" in this context means *runtime safety only*. In order to + protect yourself against JavaScript injection in untrusted content, see + [this example](https://github.com/russross/blackfriday#sanitize-untrusted-content). + +* **Fast processing**. It is fast enough to render on-demand in + most web applications without having to cache the output. + +* **Thread safety**. You can run multiple parsers in different + goroutines without ill effect. There is no dependence on global + shared state. + +* **Minimal dependencies**. Blackfriday only depends on standard + library packages in Go. The source code is pretty + self-contained, so it is easy to add to any project, including + Google App Engine projects. + +* **Standards compliant**. Output successfully validates using the + W3C validation tool for HTML 4.01 and XHTML 1.0 Transitional. + + +Extensions +---------- + +In addition to the standard markdown syntax, this package +implements the following extensions: + +* **Intra-word emphasis supression**. The `_` character is + commonly used inside words when discussing code, so having + markdown interpret it as an emphasis command is usually the + wrong thing. Blackfriday lets you treat all emphasis markers as + normal characters when they occur inside a word. + +* **Tables**. Tables can be created by drawing them in the input + using a simple syntax: + + ``` + Name | Age + --------|------ + Bob | 27 + Alice | 23 + ``` + +* **Fenced code blocks**. In addition to the normal 4-space + indentation to mark code blocks, you can explicitly mark them + and supply a language (to make syntax highlighting simple). Just + mark it like this: + + ``` go + func getTrue() bool { + return true + } + ``` + + You can use 3 or more backticks to mark the beginning of the + block, and the same number to mark the end of the block. + + To preserve classes of fenced code blocks while using the bluemonday + HTML sanitizer, use the following policy: + + ``` go + p := bluemonday.UGCPolicy() + p.AllowAttrs("class").Matching(regexp.MustCompile("^language-[a-zA-Z0-9]+$")).OnElements("code") + html := p.SanitizeBytes(unsafe) + ``` + +* **Definition lists**. A simple definition list is made of a single-line + term followed by a colon and the definition for that term. + + Cat + : Fluffy animal everyone likes + + Internet + : Vector of transmission for pictures of cats + + Terms must be separated from the previous definition by a blank line. + +* **Footnotes**. A marker in the text that will become a superscript number; + a footnote definition that will be placed in a list of footnotes at the + end of the document. A footnote looks like this: + + This is a footnote.[^1] + + [^1]: the footnote text. + +* **Autolinking**. Blackfriday can find URLs that have not been + explicitly marked as links and turn them into links. + +* **Strikethrough**. Use two tildes (`~~`) to mark text that + should be crossed out. + +* **Hard line breaks**. With this extension enabled (it is off by + default in the `MarkdownBasic` and `MarkdownCommon` convenience + functions), newlines in the input translate into line breaks in + the output. + +* **Smart quotes**. Smartypants-style punctuation substitution is + supported, turning normal double- and single-quote marks into + curly quotes, etc. + +* **LaTeX-style dash parsing** is an additional option, where `--` + is translated into `–`, and `---` is translated into + `—`. This differs from most smartypants processors, which + turn a single hyphen into an ndash and a double hyphen into an + mdash. + +* **Smart fractions**, where anything that looks like a fraction + is translated into suitable HTML (instead of just a few special + cases like most smartypant processors). For example, `4/5` + becomes `45`, which renders as + 45. + + +Other renderers +--------------- + +Blackfriday is structured to allow alternative rendering engines. Here +are a few of note: + +* [github_flavored_markdown](https://godoc.org/github.com/shurcooL/github_flavored_markdown): + provides a GitHub Flavored Markdown renderer with fenced code block + highlighting, clickable heading anchor links. + + It's not customizable, and its goal is to produce HTML output + equivalent to the [GitHub Markdown API endpoint](https://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode), + except the rendering is performed locally. + +* [markdownfmt](https://github.com/shurcooL/markdownfmt): like gofmt, + but for markdown. + +* [LaTeX output](https://bitbucket.org/ambrevar/blackfriday-latex): + renders output as LaTeX. + + +TODO +---- + +* More unit testing +* Improve Unicode support. It does not understand all Unicode + rules (about what constitutes a letter, a punctuation symbol, + etc.), so it may fail to detect word boundaries correctly in + some instances. It is safe on all UTF-8 input. + + +License +------- + +[Blackfriday is distributed under the Simplified BSD License](LICENSE.txt) + + + [1]: https://daringfireball.net/projects/markdown/ "Markdown" + [2]: https://golang.org/ "Go Language" + [3]: https://github.com/vmg/sundown "Sundown" + [4]: https://godoc.org/gopkg.in/russross/blackfriday.v2#Parse "Parse func" + [5]: https://github.com/microcosm-cc/bluemonday "Bluemonday" + [6]: https://labix.org/gopkg.in "gopkg.in" + [7]: https://github.com/golang/dep/ "dep" + [8]: https://github.com/Masterminds/glide "Glide" + + [BuildSVG]: https://travis-ci.org/russross/blackfriday.svg?branch=master + [BuildURL]: https://travis-ci.org/russross/blackfriday + [GodocV2SVG]: https://godoc.org/gopkg.in/russross/blackfriday.v2?status.svg + [GodocV2URL]: https://godoc.org/gopkg.in/russross/blackfriday.v2 diff --git a/vendor/github.com/satori/go.uuid/.travis.yml b/vendor/github.com/satori/go.uuid/.travis.yml new file mode 100644 index 0000000000..20dd53b8d3 --- /dev/null +++ b/vendor/github.com/satori/go.uuid/.travis.yml @@ -0,0 +1,23 @@ +language: go +sudo: false +go: + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - 1.7 + - 1.8 + - 1.9 + - tip +matrix: + allow_failures: + - go: tip + fast_finish: true +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -service=travis-ci +notifications: + email: false diff --git a/vendor/github.com/satori/go.uuid/LICENSE b/vendor/github.com/satori/go.uuid/LICENSE index 488357b8af..926d549870 100644 --- a/vendor/github.com/satori/go.uuid/LICENSE +++ b/vendor/github.com/satori/go.uuid/LICENSE @@ -1,4 +1,4 @@ -Copyright (C) 2013-2016 by Maxim Bublis +Copyright (C) 2013-2018 by Maxim Bublis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/vendor/github.com/satori/go.uuid/README.md b/vendor/github.com/satori/go.uuid/README.md new file mode 100644 index 0000000000..7b1a722dff --- /dev/null +++ b/vendor/github.com/satori/go.uuid/README.md @@ -0,0 +1,65 @@ +# UUID package for Go language + +[![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid) +[![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid) +[![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid) + +This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs. + +With 100% test coverage and benchmarks out of box. + +Supported versions: +* Version 1, based on timestamp and MAC address (RFC 4122) +* Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1) +* Version 3, based on MD5 hashing (RFC 4122) +* Version 4, based on random numbers (RFC 4122) +* Version 5, based on SHA-1 hashing (RFC 4122) + +## Installation + +Use the `go` command: + + $ go get github.com/satori/go.uuid + +## Requirements + +UUID package requires Go >= 1.2. + +## Example + +```go +package main + +import ( + "fmt" + "github.com/satori/go.uuid" +) + +func main() { + // Creating UUID Version 4 + u1 := uuid.NewV4() + fmt.Printf("UUIDv4: %s\n", u1) + + // Parsing UUID from string input + u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + if err != nil { + fmt.Printf("Something gone wrong: %s", err) + } + fmt.Printf("Successfully parsed: %s", u2) +} +``` + +## Documentation + +[Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project. + +## Links +* [RFC 4122](http://tools.ietf.org/html/rfc4122) +* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01) + +## Copyright + +Copyright (C) 2013-2018 by Maxim Bublis . + +UUID package released under MIT License. +See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details. diff --git a/vendor/github.com/satori/go.uuid/codec.go b/vendor/github.com/satori/go.uuid/codec.go new file mode 100644 index 0000000000..656892c53e --- /dev/null +++ b/vendor/github.com/satori/go.uuid/codec.go @@ -0,0 +1,206 @@ +// Copyright (C) 2013-2018 by Maxim Bublis +// +// 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. + +package uuid + +import ( + "bytes" + "encoding/hex" + "fmt" +) + +// FromBytes returns UUID converted from raw byte slice input. +// It will return error if the slice isn't 16 bytes long. +func FromBytes(input []byte) (u UUID, err error) { + err = u.UnmarshalBinary(input) + return +} + +// FromBytesOrNil returns UUID converted from raw byte slice input. +// Same behavior as FromBytes, but returns a Nil UUID on error. +func FromBytesOrNil(input []byte) UUID { + uuid, err := FromBytes(input) + if err != nil { + return Nil + } + return uuid +} + +// FromString returns UUID parsed from string input. +// Input is expected in a form accepted by UnmarshalText. +func FromString(input string) (u UUID, err error) { + err = u.UnmarshalText([]byte(input)) + return +} + +// FromStringOrNil returns UUID parsed from string input. +// Same behavior as FromString, but returns a Nil UUID on error. +func FromStringOrNil(input string) UUID { + uuid, err := FromString(input) + if err != nil { + return Nil + } + return uuid +} + +// MarshalText implements the encoding.TextMarshaler interface. +// The encoding is the same as returned by String. +func (u UUID) MarshalText() (text []byte, err error) { + text = []byte(u.String()) + return +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// Following formats are supported: +// "6ba7b810-9dad-11d1-80b4-00c04fd430c8", +// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", +// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" +// "6ba7b8109dad11d180b400c04fd430c8" +// ABNF for supported UUID text representation follows: +// uuid := canonical | hashlike | braced | urn +// plain := canonical | hashlike +// canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct +// hashlike := 12hexoct +// braced := '{' plain '}' +// urn := URN ':' UUID-NID ':' plain +// URN := 'urn' +// UUID-NID := 'uuid' +// 12hexoct := 6hexoct 6hexoct +// 6hexoct := 4hexoct 2hexoct +// 4hexoct := 2hexoct 2hexoct +// 2hexoct := hexoct hexoct +// hexoct := hexdig hexdig +// hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | +// 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | +// 'A' | 'B' | 'C' | 'D' | 'E' | 'F' +func (u *UUID) UnmarshalText(text []byte) (err error) { + switch len(text) { + case 32: + return u.decodeHashLike(text) + case 36: + return u.decodeCanonical(text) + case 38: + return u.decodeBraced(text) + case 41: + fallthrough + case 45: + return u.decodeURN(text) + default: + return fmt.Errorf("uuid: incorrect UUID length: %s", text) + } +} + +// decodeCanonical decodes UUID string in format +// "6ba7b810-9dad-11d1-80b4-00c04fd430c8". +func (u *UUID) decodeCanonical(t []byte) (err error) { + if t[8] != '-' || t[13] != '-' || t[18] != '-' || t[23] != '-' { + return fmt.Errorf("uuid: incorrect UUID format %s", t) + } + + src := t[:] + dst := u[:] + + for i, byteGroup := range byteGroups { + if i > 0 { + src = src[1:] // skip dash + } + _, err = hex.Decode(dst[:byteGroup/2], src[:byteGroup]) + if err != nil { + return + } + src = src[byteGroup:] + dst = dst[byteGroup/2:] + } + + return +} + +// decodeHashLike decodes UUID string in format +// "6ba7b8109dad11d180b400c04fd430c8". +func (u *UUID) decodeHashLike(t []byte) (err error) { + src := t[:] + dst := u[:] + + if _, err = hex.Decode(dst, src); err != nil { + return err + } + return +} + +// decodeBraced decodes UUID string in format +// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" or in format +// "{6ba7b8109dad11d180b400c04fd430c8}". +func (u *UUID) decodeBraced(t []byte) (err error) { + l := len(t) + + if t[0] != '{' || t[l-1] != '}' { + return fmt.Errorf("uuid: incorrect UUID format %s", t) + } + + return u.decodePlain(t[1 : l-1]) +} + +// decodeURN decodes UUID string in format +// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in format +// "urn:uuid:6ba7b8109dad11d180b400c04fd430c8". +func (u *UUID) decodeURN(t []byte) (err error) { + total := len(t) + + urn_uuid_prefix := t[:9] + + if !bytes.Equal(urn_uuid_prefix, urnPrefix) { + return fmt.Errorf("uuid: incorrect UUID format: %s", t) + } + + return u.decodePlain(t[9:total]) +} + +// decodePlain decodes UUID string in canonical format +// "6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in hash-like format +// "6ba7b8109dad11d180b400c04fd430c8". +func (u *UUID) decodePlain(t []byte) (err error) { + switch len(t) { + case 32: + return u.decodeHashLike(t) + case 36: + return u.decodeCanonical(t) + default: + return fmt.Errorf("uuid: incorrrect UUID length: %s", t) + } +} + +// MarshalBinary implements the encoding.BinaryMarshaler interface. +func (u UUID) MarshalBinary() (data []byte, err error) { + data = u.Bytes() + return +} + +// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. +// It will return error if the slice isn't 16 bytes long. +func (u *UUID) UnmarshalBinary(data []byte) (err error) { + if len(data) != Size { + err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data)) + return + } + copy(u[:], data) + + return +} diff --git a/vendor/github.com/satori/go.uuid/generator.go b/vendor/github.com/satori/go.uuid/generator.go new file mode 100644 index 0000000000..3f2f1da2dc --- /dev/null +++ b/vendor/github.com/satori/go.uuid/generator.go @@ -0,0 +1,239 @@ +// Copyright (C) 2013-2018 by Maxim Bublis +// +// 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. + +package uuid + +import ( + "crypto/md5" + "crypto/rand" + "crypto/sha1" + "encoding/binary" + "hash" + "net" + "os" + "sync" + "time" +) + +// Difference in 100-nanosecond intervals between +// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). +const epochStart = 122192928000000000 + +var ( + global = newDefaultGenerator() + + epochFunc = unixTimeFunc + posixUID = uint32(os.Getuid()) + posixGID = uint32(os.Getgid()) +) + +// NewV1 returns UUID based on current timestamp and MAC address. +func NewV1() UUID { + return global.NewV1() +} + +// NewV2 returns DCE Security UUID based on POSIX UID/GID. +func NewV2(domain byte) UUID { + return global.NewV2(domain) +} + +// NewV3 returns UUID based on MD5 hash of namespace UUID and name. +func NewV3(ns UUID, name string) UUID { + return global.NewV3(ns, name) +} + +// NewV4 returns random generated UUID. +func NewV4() UUID { + return global.NewV4() +} + +// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. +func NewV5(ns UUID, name string) UUID { + return global.NewV5(ns, name) +} + +// Generator provides interface for generating UUIDs. +type Generator interface { + NewV1() UUID + NewV2(domain byte) UUID + NewV3(ns UUID, name string) UUID + NewV4() UUID + NewV5(ns UUID, name string) UUID +} + +// Default generator implementation. +type generator struct { + storageOnce sync.Once + storageMutex sync.Mutex + + lastTime uint64 + clockSequence uint16 + hardwareAddr [6]byte +} + +func newDefaultGenerator() Generator { + return &generator{} +} + +// NewV1 returns UUID based on current timestamp and MAC address. +func (g *generator) NewV1() UUID { + u := UUID{} + + timeNow, clockSeq, hardwareAddr := g.getStorage() + + binary.BigEndian.PutUint32(u[0:], uint32(timeNow)) + binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) + binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) + binary.BigEndian.PutUint16(u[8:], clockSeq) + + copy(u[10:], hardwareAddr) + + u.SetVersion(V1) + u.SetVariant(VariantRFC4122) + + return u +} + +// NewV2 returns DCE Security UUID based on POSIX UID/GID. +func (g *generator) NewV2(domain byte) UUID { + u := UUID{} + + timeNow, clockSeq, hardwareAddr := g.getStorage() + + switch domain { + case DomainPerson: + binary.BigEndian.PutUint32(u[0:], posixUID) + case DomainGroup: + binary.BigEndian.PutUint32(u[0:], posixGID) + } + + binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) + binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) + binary.BigEndian.PutUint16(u[8:], clockSeq) + u[9] = domain + + copy(u[10:], hardwareAddr) + + u.SetVersion(V2) + u.SetVariant(VariantRFC4122) + + return u +} + +// NewV3 returns UUID based on MD5 hash of namespace UUID and name. +func (g *generator) NewV3(ns UUID, name string) UUID { + u := newFromHash(md5.New(), ns, name) + u.SetVersion(V3) + u.SetVariant(VariantRFC4122) + + return u +} + +// NewV4 returns random generated UUID. +func (g *generator) NewV4() UUID { + u := UUID{} + g.safeRandom(u[:]) + u.SetVersion(V4) + u.SetVariant(VariantRFC4122) + + return u +} + +// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. +func (g *generator) NewV5(ns UUID, name string) UUID { + u := newFromHash(sha1.New(), ns, name) + u.SetVersion(V5) + u.SetVariant(VariantRFC4122) + + return u +} + +func (g *generator) initStorage() { + g.initClockSequence() + g.initHardwareAddr() +} + +func (g *generator) initClockSequence() { + buf := make([]byte, 2) + g.safeRandom(buf) + g.clockSequence = binary.BigEndian.Uint16(buf) +} + +func (g *generator) initHardwareAddr() { + interfaces, err := net.Interfaces() + if err == nil { + for _, iface := range interfaces { + if len(iface.HardwareAddr) >= 6 { + copy(g.hardwareAddr[:], iface.HardwareAddr) + return + } + } + } + + // Initialize hardwareAddr randomly in case + // of real network interfaces absence + g.safeRandom(g.hardwareAddr[:]) + + // Set multicast bit as recommended in RFC 4122 + g.hardwareAddr[0] |= 0x01 +} + +func (g *generator) safeRandom(dest []byte) { + if _, err := rand.Read(dest); err != nil { + panic(err) + } +} + +// Returns UUID v1/v2 storage state. +// Returns epoch timestamp, clock sequence, and hardware address. +func (g *generator) getStorage() (uint64, uint16, []byte) { + g.storageOnce.Do(g.initStorage) + + g.storageMutex.Lock() + defer g.storageMutex.Unlock() + + timeNow := epochFunc() + // Clock changed backwards since last UUID generation. + // Should increase clock sequence. + if timeNow <= g.lastTime { + g.clockSequence++ + } + g.lastTime = timeNow + + return timeNow, g.clockSequence, g.hardwareAddr[:] +} + +// Returns difference in 100-nanosecond intervals between +// UUID epoch (October 15, 1582) and current time. +// This is default epoch calculation function. +func unixTimeFunc() uint64 { + return epochStart + uint64(time.Now().UnixNano()/100) +} + +// Returns UUID based on hashing of namespace UUID and name. +func newFromHash(h hash.Hash, ns UUID, name string) UUID { + u := UUID{} + h.Write(ns[:]) + h.Write([]byte(name)) + copy(u[:], h.Sum(nil)) + + return u +} diff --git a/vendor/github.com/satori/go.uuid/sql.go b/vendor/github.com/satori/go.uuid/sql.go new file mode 100644 index 0000000000..56759d3905 --- /dev/null +++ b/vendor/github.com/satori/go.uuid/sql.go @@ -0,0 +1,78 @@ +// Copyright (C) 2013-2018 by Maxim Bublis +// +// 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. + +package uuid + +import ( + "database/sql/driver" + "fmt" +) + +// Value implements the driver.Valuer interface. +func (u UUID) Value() (driver.Value, error) { + return u.String(), nil +} + +// Scan implements the sql.Scanner interface. +// A 16-byte slice is handled by UnmarshalBinary, while +// a longer byte slice or a string is handled by UnmarshalText. +func (u *UUID) Scan(src interface{}) error { + switch src := src.(type) { + case []byte: + if len(src) == Size { + return u.UnmarshalBinary(src) + } + return u.UnmarshalText(src) + + case string: + return u.UnmarshalText([]byte(src)) + } + + return fmt.Errorf("uuid: cannot convert %T to UUID", src) +} + +// NullUUID can be used with the standard sql package to represent a +// UUID value that can be NULL in the database +type NullUUID struct { + UUID UUID + Valid bool +} + +// Value implements the driver.Valuer interface. +func (u NullUUID) Value() (driver.Value, error) { + if !u.Valid { + return nil, nil + } + // Delegate to UUID Value function + return u.UUID.Value() +} + +// Scan implements the sql.Scanner interface. +func (u *NullUUID) Scan(src interface{}) error { + if src == nil { + u.UUID, u.Valid = Nil, false + return nil + } + + // Delegate to UUID Scan function + u.Valid = true + return u.UUID.Scan(src) +} diff --git a/vendor/github.com/satori/go.uuid/uuid.go b/vendor/github.com/satori/go.uuid/uuid.go index 295f3fc2c5..a2b8e2ca2a 100644 --- a/vendor/github.com/satori/go.uuid/uuid.go +++ b/vendor/github.com/satori/go.uuid/uuid.go @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 by Maxim Bublis +// Copyright (C) 2013-2018 by Maxim Bublis // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -26,23 +26,29 @@ package uuid import ( "bytes" - "crypto/md5" - "crypto/rand" - "crypto/sha1" - "database/sql/driver" - "encoding/binary" "encoding/hex" - "fmt" - "hash" - "net" - "os" - "sync" - "time" +) + +// Size of a UUID in bytes. +const Size = 16 + +// UUID representation compliant with specification +// described in RFC 4122. +type UUID [Size]byte + +// UUID versions +const ( + _ byte = iota + V1 + V2 + V3 + V4 + V5 ) // UUID layout variants. const ( - VariantNCS = iota + VariantNCS byte = iota VariantRFC4122 VariantMicrosoft VariantFuture @@ -55,136 +61,48 @@ const ( DomainOrg ) -// Difference in 100-nanosecond intervals between -// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). -const epochStart = 122192928000000000 - -// Used in string method conversion -const dash byte = '-' - -// UUID v1/v2 storage. -var ( - storageMutex sync.Mutex - storageOnce sync.Once - epochFunc = unixTimeFunc - clockSequence uint16 - lastTime uint64 - hardwareAddr [6]byte - posixUID = uint32(os.Getuid()) - posixGID = uint32(os.Getgid()) -) - // String parse helpers. var ( urnPrefix = []byte("urn:uuid:") byteGroups = []int{8, 4, 4, 4, 12} ) -func initClockSequence() { - buf := make([]byte, 2) - safeRandom(buf) - clockSequence = binary.BigEndian.Uint16(buf) -} - -func initHardwareAddr() { - interfaces, err := net.Interfaces() - if err == nil { - for _, iface := range interfaces { - if len(iface.HardwareAddr) >= 6 { - copy(hardwareAddr[:], iface.HardwareAddr) - return - } - } - } - - // Initialize hardwareAddr randomly in case - // of real network interfaces absence - safeRandom(hardwareAddr[:]) - - // Set multicast bit as recommended in RFC 4122 - hardwareAddr[0] |= 0x01 -} - -func initStorage() { - initClockSequence() - initHardwareAddr() -} - -func safeRandom(dest []byte) { - if _, err := rand.Read(dest); err != nil { - panic(err) - } -} - -// Returns difference in 100-nanosecond intervals between -// UUID epoch (October 15, 1582) and current time. -// This is default epoch calculation function. -func unixTimeFunc() uint64 { - return epochStart + uint64(time.Now().UnixNano()/100) -} - -// UUID representation compliant with specification -// described in RFC 4122. -type UUID [16]byte - -// NullUUID can be used with the standard sql package to represent a -// UUID value that can be NULL in the database -type NullUUID struct { - UUID UUID - Valid bool -} - -// The nil UUID is special form of UUID that is specified to have all +// Nil is special form of UUID that is specified to have all // 128 bits set to zero. var Nil = UUID{} // Predefined namespace UUIDs. var ( - NamespaceDNS, _ = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - NamespaceURL, _ = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8") - NamespaceOID, _ = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8") - NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8") + NamespaceDNS = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) + NamespaceURL = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) + NamespaceOID = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) + NamespaceX500 = Must(FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) ) -// And returns result of binary AND of two UUIDs. -func And(u1 UUID, u2 UUID) UUID { - u := UUID{} - for i := 0; i < 16; i++ { - u[i] = u1[i] & u2[i] - } - return u -} - -// Or returns result of binary OR of two UUIDs. -func Or(u1 UUID, u2 UUID) UUID { - u := UUID{} - for i := 0; i < 16; i++ { - u[i] = u1[i] | u2[i] - } - return u -} - // Equal returns true if u1 and u2 equals, otherwise returns false. func Equal(u1 UUID, u2 UUID) bool { return bytes.Equal(u1[:], u2[:]) } // Version returns algorithm version used to generate UUID. -func (u UUID) Version() uint { - return uint(u[6] >> 4) +func (u UUID) Version() byte { + return u[6] >> 4 } // Variant returns UUID layout variant. -func (u UUID) Variant() uint { +func (u UUID) Variant() byte { switch { - case (u[8] & 0x80) == 0x00: + case (u[8] >> 7) == 0x00: return VariantNCS - case (u[8]&0xc0)|0x80 == 0x80: + case (u[8] >> 6) == 0x02: return VariantRFC4122 - case (u[8]&0xe0)|0xc0 == 0xc0: + case (u[8] >> 5) == 0x06: return VariantMicrosoft + case (u[8] >> 5) == 0x07: + fallthrough + default: + return VariantFuture } - return VariantFuture } // Bytes returns bytes slice representation of UUID. @@ -198,13 +116,13 @@ func (u UUID) String() string { buf := make([]byte, 36) hex.Encode(buf[0:8], u[0:4]) - buf[8] = dash + buf[8] = '-' hex.Encode(buf[9:13], u[4:6]) - buf[13] = dash + buf[13] = '-' hex.Encode(buf[14:18], u[6:8]) - buf[18] = dash + buf[18] = '-' hex.Encode(buf[19:23], u[8:10]) - buf[23] = dash + buf[23] = '-' hex.Encode(buf[24:], u[10:]) return string(buf) @@ -215,267 +133,29 @@ func (u *UUID) SetVersion(v byte) { u[6] = (u[6] & 0x0f) | (v << 4) } -// SetVariant sets variant bits as described in RFC 4122. -func (u *UUID) SetVariant() { - u[8] = (u[8] & 0xbf) | 0x80 -} - -// MarshalText implements the encoding.TextMarshaler interface. -// The encoding is the same as returned by String. -func (u UUID) MarshalText() (text []byte, err error) { - text = []byte(u.String()) - return -} - -// UnmarshalText implements the encoding.TextUnmarshaler interface. -// Following formats are supported: -// "6ba7b810-9dad-11d1-80b4-00c04fd430c8", -// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", -// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" -func (u *UUID) UnmarshalText(text []byte) (err error) { - if len(text) < 32 { - err = fmt.Errorf("uuid: UUID string too short: %s", text) - return +// SetVariant sets variant bits. +func (u *UUID) SetVariant(v byte) { + switch v { + case VariantNCS: + u[8] = (u[8]&(0xff>>1) | (0x00 << 7)) + case VariantRFC4122: + u[8] = (u[8]&(0xff>>2) | (0x02 << 6)) + case VariantMicrosoft: + u[8] = (u[8]&(0xff>>3) | (0x06 << 5)) + case VariantFuture: + fallthrough + default: + u[8] = (u[8]&(0xff>>3) | (0x07 << 5)) } - - t := text[:] - braced := false - - if bytes.Equal(t[:9], urnPrefix) { - t = t[9:] - } else if t[0] == '{' { - braced = true - t = t[1:] - } - - b := u[:] - - for i, byteGroup := range byteGroups { - if i > 0 { - if t[0] != '-' { - err = fmt.Errorf("uuid: invalid string format") - return - } - t = t[1:] - } - - if len(t) < byteGroup { - err = fmt.Errorf("uuid: UUID string too short: %s", text) - return - } - - if i == 4 && len(t) > byteGroup && - ((braced && t[byteGroup] != '}') || len(t[byteGroup:]) > 1 || !braced) { - err = fmt.Errorf("uuid: UUID string too long: %s", text) - return - } - - _, err = hex.Decode(b[:byteGroup/2], t[:byteGroup]) - if err != nil { - return - } - - t = t[byteGroup:] - b = b[byteGroup/2:] - } - - return } -// MarshalBinary implements the encoding.BinaryMarshaler interface. -func (u UUID) MarshalBinary() (data []byte, err error) { - data = u.Bytes() - return -} - -// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. -// It will return error if the slice isn't 16 bytes long. -func (u *UUID) UnmarshalBinary(data []byte) (err error) { - if len(data) != 16 { - err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data)) - return - } - copy(u[:], data) - - return -} - -// Value implements the driver.Valuer interface. -func (u UUID) Value() (driver.Value, error) { - return u.String(), nil -} - -// Scan implements the sql.Scanner interface. -// A 16-byte slice is handled by UnmarshalBinary, while -// a longer byte slice or a string is handled by UnmarshalText. -func (u *UUID) Scan(src interface{}) error { - switch src := src.(type) { - case []byte: - if len(src) == 16 { - return u.UnmarshalBinary(src) - } - return u.UnmarshalText(src) - - case string: - return u.UnmarshalText([]byte(src)) - } - - return fmt.Errorf("uuid: cannot convert %T to UUID", src) -} - -// Value implements the driver.Valuer interface. -func (u NullUUID) Value() (driver.Value, error) { - if !u.Valid { - return nil, nil - } - // Delegate to UUID Value function - return u.UUID.Value() -} - -// Scan implements the sql.Scanner interface. -func (u *NullUUID) Scan(src interface{}) error { - if src == nil { - u.UUID, u.Valid = Nil, false - return nil - } - - // Delegate to UUID Scan function - u.Valid = true - return u.UUID.Scan(src) -} - -// FromBytes returns UUID converted from raw byte slice input. -// It will return error if the slice isn't 16 bytes long. -func FromBytes(input []byte) (u UUID, err error) { - err = u.UnmarshalBinary(input) - return -} - -// FromBytesOrNil returns UUID converted from raw byte slice input. -// Same behavior as FromBytes, but returns a Nil UUID on error. -func FromBytesOrNil(input []byte) UUID { - uuid, err := FromBytes(input) +// Must is a helper that wraps a call to a function returning (UUID, error) +// and panics if the error is non-nil. It is intended for use in variable +// initializations such as +// var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000")); +func Must(u UUID, err error) UUID { if err != nil { - return Nil + panic(err) } - return uuid -} - -// FromString returns UUID parsed from string input. -// Input is expected in a form accepted by UnmarshalText. -func FromString(input string) (u UUID, err error) { - err = u.UnmarshalText([]byte(input)) - return -} - -// FromStringOrNil returns UUID parsed from string input. -// Same behavior as FromString, but returns a Nil UUID on error. -func FromStringOrNil(input string) UUID { - uuid, err := FromString(input) - if err != nil { - return Nil - } - return uuid -} - -// Returns UUID v1/v2 storage state. -// Returns epoch timestamp, clock sequence, and hardware address. -func getStorage() (uint64, uint16, []byte) { - storageOnce.Do(initStorage) - - storageMutex.Lock() - defer storageMutex.Unlock() - - timeNow := epochFunc() - // Clock changed backwards since last UUID generation. - // Should increase clock sequence. - if timeNow <= lastTime { - clockSequence++ - } - lastTime = timeNow - - return timeNow, clockSequence, hardwareAddr[:] -} - -// NewV1 returns UUID based on current timestamp and MAC address. -func NewV1() UUID { - u := UUID{} - - timeNow, clockSeq, hardwareAddr := getStorage() - - binary.BigEndian.PutUint32(u[0:], uint32(timeNow)) - binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) - binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) - binary.BigEndian.PutUint16(u[8:], clockSeq) - - copy(u[10:], hardwareAddr) - - u.SetVersion(1) - u.SetVariant() - - return u -} - -// NewV2 returns DCE Security UUID based on POSIX UID/GID. -func NewV2(domain byte) UUID { - u := UUID{} - - timeNow, clockSeq, hardwareAddr := getStorage() - - switch domain { - case DomainPerson: - binary.BigEndian.PutUint32(u[0:], posixUID) - case DomainGroup: - binary.BigEndian.PutUint32(u[0:], posixGID) - } - - binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) - binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) - binary.BigEndian.PutUint16(u[8:], clockSeq) - u[9] = domain - - copy(u[10:], hardwareAddr) - - u.SetVersion(2) - u.SetVariant() - - return u -} - -// NewV3 returns UUID based on MD5 hash of namespace UUID and name. -func NewV3(ns UUID, name string) UUID { - u := newFromHash(md5.New(), ns, name) - u.SetVersion(3) - u.SetVariant() - - return u -} - -// NewV4 returns random generated UUID. -func NewV4() UUID { - u := UUID{} - safeRandom(u[:]) - u.SetVersion(4) - u.SetVariant() - - return u -} - -// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. -func NewV5(ns UUID, name string) UUID { - u := newFromHash(sha1.New(), ns, name) - u.SetVersion(5) - u.SetVariant() - - return u -} - -// Returns UUID based on hashing of namespace UUID and name. -func newFromHash(h hash.Hash, ns UUID, name string) UUID { - u := UUID{} - h.Write(ns[:]) - h.Write([]byte(name)) - copy(u[:], h.Sum(nil)) - return u } diff --git a/vendor/github.com/sergi/go-diff/AUTHORS b/vendor/github.com/sergi/go-diff/AUTHORS new file mode 100644 index 0000000000..2d7bb2bf57 --- /dev/null +++ b/vendor/github.com/sergi/go-diff/AUTHORS @@ -0,0 +1,25 @@ +# This is the official list of go-diff authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. + +# Names should be added to this file as +# Name or Organization +# The email address is not required for organizations. + +# Please keep the list sorted. + +Danny Yoo +James Kolb +Jonathan Amsterdam +Markus Zimmermann +Matt Kovars +Örjan Persson +Osman Masood +Robert Carlsen +Rory Flynn +Sergi Mansilla +Shatrugna Sadhu +Shawn Smith +Stas Maksimov +Tor Arvid Lund +Zac Bergquist diff --git a/vendor/github.com/sergi/go-diff/CONTRIBUTORS b/vendor/github.com/sergi/go-diff/CONTRIBUTORS new file mode 100644 index 0000000000..369e3d5519 --- /dev/null +++ b/vendor/github.com/sergi/go-diff/CONTRIBUTORS @@ -0,0 +1,32 @@ +# This is the official list of people who can contribute +# (and typically have contributed) code to the go-diff +# repository. +# +# The AUTHORS file lists the copyright holders; this file +# lists people. For example, ACME Inc. employees would be listed here +# but not in AUTHORS, because ACME Inc. would hold the copyright. +# +# When adding J Random Contributor's name to this file, +# either J's name or J's organization's name should be +# added to the AUTHORS file. +# +# Names should be added to this file like so: +# Name +# +# Please keep the list sorted. + +Danny Yoo +James Kolb +Jonathan Amsterdam +Markus Zimmermann +Matt Kovars +Örjan Persson +Osman Masood +Robert Carlsen +Rory Flynn +Sergi Mansilla +Shatrugna Sadhu +Shawn Smith +Stas Maksimov +Tor Arvid Lund +Zac Bergquist diff --git a/vendor/github.com/sergi/go-diff/LICENSE.txt b/vendor/github.com/sergi/go-diff/LICENSE similarity index 93% rename from vendor/github.com/sergi/go-diff/LICENSE.txt rename to vendor/github.com/sergi/go-diff/LICENSE index eeb91026ac..937942c2b2 100644 --- a/vendor/github.com/sergi/go-diff/LICENSE.txt +++ b/vendor/github.com/sergi/go-diff/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012 Sergi Mansilla +Copyright (c) 2012-2016 The go-diff Authors. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/vendor/github.com/sergi/go-diff/diffmatchpatch/dmp.go b/vendor/github.com/sergi/go-diff/diffmatchpatch/diff.go similarity index 52% rename from vendor/github.com/sergi/go-diff/diffmatchpatch/dmp.go rename to vendor/github.com/sergi/go-diff/diffmatchpatch/diff.go index 4e61821dd6..82ad7bc8f1 100644 --- a/vendor/github.com/sergi/go-diff/diffmatchpatch/dmp.go +++ b/vendor/github.com/sergi/go-diff/diffmatchpatch/diff.go @@ -1,19 +1,11 @@ -/** - * dmp.go - * - * Go language implementation of Google Diff, Match, and Patch library - * - * Original library is Copyright (c) 2006 Google Inc. - * http://code.google.com/p/google-diff-match-patch/ - * - * Copyright (c) 2012 Sergi Mansilla - * https://github.com/sergi/go-diff - * - * See included LICENSE file for license details. - */ +// Copyright (c) 2012-2016 The go-diff authors. All rights reserved. +// https://github.com/sergi/go-diff +// See the included LICENSE file for license details. +// +// go-diff is a Go implementation of Google's Diff, Match, and Patch library +// Original library is Copyright (c) 2006 Google Inc. +// http://code.google.com/p/google-diff-match-patch/ -// Package diffmatchpatch offers robust algorithms to perform the -// operations required for synchronizing plain text. package diffmatchpatch import ( @@ -30,10 +22,6 @@ import ( "unicode/utf8" ) -// The data structure representing a diff is an array of tuples: -// [[DiffDelete, 'Hello'], [DiffInsert, 'Goodbye'], [DiffEqual, ' world.']] -// which means: delete 'Hello', add 'Goodbye' and keep ' world.' - // Operation defines the operation of a diff item. type Operation int8 @@ -46,214 +34,24 @@ const ( DiffEqual Operation = 0 ) -// unescaper unescapes selected chars for compatibility with JavaScript's encodeURI. -// In speed critical applications this could be dropped since the -// receiving application will certainly decode these fine. -// Note that this function is case-sensitive. Thus "%3F" would not be -// unescaped. But this is ok because it is only called with the output of -// HttpUtility.UrlEncode which returns lowercase hex. -// -// Example: "%3f" -> "?", "%24" -> "$", etc. -var unescaper = strings.NewReplacer( - "%21", "!", "%7E", "~", "%27", "'", - "%28", "(", "%29", ")", "%3B", ";", - "%2F", "/", "%3F", "?", "%3A", ":", - "%40", "@", "%26", "&", "%3D", "=", - "%2B", "+", "%24", "$", "%2C", ",", "%23", "#", "%2A", "*") - -// Define some regex patterns for matching boundaries. -var ( - nonAlphaNumericRegex = regexp.MustCompile(`[^a-zA-Z0-9]`) - whitespaceRegex = regexp.MustCompile(`\s`) - linebreakRegex = regexp.MustCompile(`[\r\n]`) - blanklineEndRegex = regexp.MustCompile(`\n\r?\n$`) - blanklineStartRegex = regexp.MustCompile(`^\r?\n\r?\n`) -) - -func splice(slice []Diff, index int, amount int, elements ...Diff) []Diff { - return append(slice[:index], append(elements, slice[index+amount:]...)...) -} - -// indexOf returns the first index of pattern in str, starting at str[i]. -func indexOf(str string, pattern string, i int) int { - if i > len(str)-1 { - return -1 - } - if i <= 0 { - return strings.Index(str, pattern) - } - ind := strings.Index(str[i:], pattern) - if ind == -1 { - return -1 - } - return ind + i -} - -// lastIndexOf returns the last index of pattern in str, starting at str[i]. -func lastIndexOf(str string, pattern string, i int) int { - if i < 0 { - return -1 - } - if i >= len(str) { - return strings.LastIndex(str, pattern) - } - _, size := utf8.DecodeRuneInString(str[i:]) - return strings.LastIndex(str[:i+size], pattern) -} - -// Return the index of pattern in target, starting at target[i]. -func runesIndexOf(target, pattern []rune, i int) int { - if i > len(target)-1 { - return -1 - } - if i <= 0 { - return runesIndex(target, pattern) - } - ind := runesIndex(target[i:], pattern) - if ind == -1 { - return -1 - } - return ind + i -} - -func min(x, y int) int { - if x < y { - return x - } - return y -} - -func max(x, y int) int { - if x > y { - return x - } - return y -} - -func runesEqual(r1, r2 []rune) bool { - if len(r1) != len(r2) { - return false - } - for i, c := range r1 { - if c != r2[i] { - return false - } - } - return true -} - -// The equivalent of strings.Index for rune slices. -func runesIndex(r1, r2 []rune) int { - last := len(r1) - len(r2) - for i := 0; i <= last; i++ { - if runesEqual(r1[i:i+len(r2)], r2) { - return i - } - } - return -1 -} - // Diff represents one diff operation type Diff struct { Type Operation Text string } -// Patch represents one patch operation. -type Patch struct { - diffs []Diff - start1 int - start2 int - length1 int - length2 int -} - -// String emulates GNU diff's format. -// Header: @@ -382,8 +481,9 @@ -// Indicies are printed as 1-based, not 0-based. -func (p *Patch) String() string { - var coords1, coords2 string - - if p.length1 == 0 { - coords1 = strconv.Itoa(p.start1) + ",0" - } else if p.length1 == 1 { - coords1 = strconv.Itoa(p.start1 + 1) - } else { - coords1 = strconv.Itoa(p.start1+1) + "," + strconv.Itoa(p.length1) - } - - if p.length2 == 0 { - coords2 = strconv.Itoa(p.start2) + ",0" - } else if p.length2 == 1 { - coords2 = strconv.Itoa(p.start2 + 1) - } else { - coords2 = strconv.Itoa(p.start2+1) + "," + strconv.Itoa(p.length2) - } - - var text bytes.Buffer - _, _ = text.WriteString("@@ -" + coords1 + " +" + coords2 + " @@\n") - - // Escape the body of the patch with %xx notation. - for _, aDiff := range p.diffs { - switch aDiff.Type { - case DiffInsert: - _, _ = text.WriteString("+") - case DiffDelete: - _, _ = text.WriteString("-") - case DiffEqual: - _, _ = text.WriteString(" ") - } - - _, _ = text.WriteString(strings.Replace(url.QueryEscape(aDiff.Text), "+", " ", -1)) - _, _ = text.WriteString("\n") - } - - return unescaper.Replace(text.String()) -} - -// DiffMatchPatch holds the configuration for diff-match-patch operations. -type DiffMatchPatch struct { - // Number of seconds to map a diff before giving up (0 for infinity). - DiffTimeout time.Duration - // Cost of an empty edit operation in terms of edit characters. - DiffEditCost int - // How far to search for a match (0 = exact location, 1000+ = broad match). - // A match this many characters away from the expected location will add - // 1.0 to the score (0.0 is a perfect match). - MatchDistance int - // When deleting a large block of text (over ~64 characters), how close do - // the contents have to be to match the expected contents. (0.0 = perfection, - // 1.0 = very loose). Note that MatchThreshold controls how closely the - // end points of a delete need to match. - PatchDeleteThreshold float64 - // Chunk size for context length. - PatchMargin int - // The number of bits in an int. - MatchMaxBits int - // At what point is no match declared (0.0 = perfection, 1.0 = very loose). - MatchThreshold float64 -} - -// New creates a new DiffMatchPatch object with default parameters. -func New() *DiffMatchPatch { - // Defaults. - return &DiffMatchPatch{ - DiffTimeout: time.Second, - DiffEditCost: 4, - MatchThreshold: 0.5, - MatchDistance: 1000, - PatchDeleteThreshold: 0.5, - PatchMargin: 4, - MatchMaxBits: 32, - } +func splice(slice []Diff, index int, amount int, elements ...Diff) []Diff { + return append(slice[:index], append(elements, slice[index+amount:]...)...) } // DiffMain finds the differences between two texts. +// If an invalid UTF-8 sequence is encountered, it will be replaced by the Unicode replacement character. func (dmp *DiffMatchPatch) DiffMain(text1, text2 string, checklines bool) []Diff { return dmp.DiffMainRunes([]rune(text1), []rune(text2), checklines) } // DiffMainRunes finds the differences between two rune sequences. +// If an invalid UTF-8 sequence is encountered, it will be replaced by the Unicode replacement character. func (dmp *DiffMatchPatch) DiffMainRunes(text1, text2 []rune, checklines bool) []Diff { var deadline time.Time if dmp.DiffTimeout > 0 { @@ -296,8 +94,7 @@ func (dmp *DiffMatchPatch) diffMainRunes(text1, text2 []rune, checklines bool, d return dmp.DiffCleanupMerge(diffs) } -// diffCompute finds the differences between two rune slices. Assumes that the texts do not -// have any common prefix or suffix. +// diffCompute finds the differences between two rune slices. Assumes that the texts do not have any common prefix or suffix. func (dmp *DiffMatchPatch) diffCompute(text1, text2 []rune, checklines bool, deadline time.Time) []Diff { diffs := []Diff{} if len(text1) == 0 { @@ -355,8 +152,7 @@ func (dmp *DiffMatchPatch) diffCompute(text1, text2 []rune, checklines bool, dea return dmp.diffBisect(text1, text2, deadline) } -// diffLineMode does a quick line-level diff on both []runes, then rediff the parts for -// greater accuracy. This speedup can produce non-minimal diffs. +// diffLineMode does a quick line-level diff on both []runes, then rediff the parts for greater accuracy. This speedup can produce non-minimal diffs. func (dmp *DiffMatchPatch) diffLineMode(text1, text2 []rune, deadline time.Time) []Diff { // Scan the text on a line-by-line basis first. text1, text2, linearray := dmp.diffLinesToRunes(text1, text2) @@ -414,16 +210,15 @@ func (dmp *DiffMatchPatch) diffLineMode(text1, text2 []rune, deadline time.Time) return diffs[:len(diffs)-1] // Remove the dummy entry at the end. } -// DiffBisect finds the 'middle snake' of a diff, split the problem in two -// and return the recursively constructed diff. +// DiffBisect finds the 'middle snake' of a diff, split the problem in two and return the recursively constructed diff. +// If an invalid UTF-8 sequence is encountered, it will be replaced by the Unicode replacement character. // See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations. func (dmp *DiffMatchPatch) DiffBisect(text1, text2 string, deadline time.Time) []Diff { // Unused in this code, but retained for interface compatibility. return dmp.diffBisect([]rune(text1), []rune(text2), deadline) } -// diffBisect finds the 'middle snake' of a diff, splits the problem in two -// and returns the recursively constructed diff. +// diffBisect finds the 'middle snake' of a diff, splits the problem in two and returns the recursively constructed diff. // See Myers's 1986 paper: An O(ND) Difference Algorithm and Its Variations. func (dmp *DiffMatchPatch) diffBisect(runes1, runes2 []rune, deadline time.Time) []Diff { // Cache the text lengths to prevent multiple calls. @@ -443,11 +238,9 @@ func (dmp *DiffMatchPatch) diffBisect(runes1, runes2 []rune, deadline time.Time) v2[vOffset+1] = 0 delta := runes1Len - runes2Len - // If the total number of characters is odd, then the front path will collide - // with the reverse path. + // If the total number of characters is odd, then the front path will collide with the reverse path. front := (delta%2 != 0) - // Offsets for start and end of k loop. - // Prevents mapping of space beyond the grid. + // Offsets for start and end of k loop. Prevents mapping of space beyond the grid. k1start := 0 k1end := 0 k2start := 0 @@ -535,8 +328,7 @@ func (dmp *DiffMatchPatch) diffBisect(runes1, runes2 []rune, deadline time.Time) } } } - // Diff took too long and hit the deadline or - // number of diffs equals number of characters, no commonality at all. + // Diff took too long and hit the deadline or number of diffs equals number of characters, no commonality at all. return []Diff{ Diff{DiffDelete, string(runes1)}, Diff{DiffInsert, string(runes2)}, @@ -557,18 +349,16 @@ func (dmp *DiffMatchPatch) diffBisectSplit(runes1, runes2 []rune, x, y int, return append(diffs, diffsb...) } -// DiffLinesToChars splits two texts into a list of strings. Reduces the texts to a string of -// hashes where each Unicode character represents one line. +// DiffLinesToChars splits two texts into a list of strings, and educes the texts to a string of hashes where each Unicode character represents one line. // It's slightly faster to call DiffLinesToRunes first, followed by DiffMainRunes. func (dmp *DiffMatchPatch) DiffLinesToChars(text1, text2 string) (string, string, []string) { chars1, chars2, lineArray := dmp.DiffLinesToRunes(text1, text2) return string(chars1), string(chars2), lineArray } -// DiffLinesToRunes splits two texts into a list of runes. Each rune represents one line. +// DiffLinesToRunes splits two texts into a list of runes. Each rune represents one line. func (dmp *DiffMatchPatch) DiffLinesToRunes(text1, text2 string) ([]rune, []rune, []string) { - // '\x00' is a valid character, but various debuggers don't like it. - // So we'll insert a junk entry to avoid generating a null character. + // '\x00' is a valid character, but various debuggers don't like it. So we'll insert a junk entry to avoid generating a null character. lineArray := []string{""} // e.g. lineArray[4] == 'Hello\n' lineHash := map[string]int{} // e.g. lineHash['Hello\n'] == 4 @@ -582,13 +372,10 @@ func (dmp *DiffMatchPatch) diffLinesToRunes(text1, text2 []rune) ([]rune, []rune return dmp.DiffLinesToRunes(string(text1), string(text2)) } -// diffLinesToRunesMunge splits a text into an array of strings. Reduces the -// texts to a []rune where each Unicode character represents one line. +// diffLinesToRunesMunge splits a text into an array of strings, and reduces the texts to a []rune where each Unicode character represents one line. // We use strings instead of []runes as input mainly because you can't use []rune as a map key. func (dmp *DiffMatchPatch) diffLinesToRunesMunge(text string, lineArray *[]string, lineHash map[string]int) []rune { - // Walk the text, pulling out a substring for each line. - // text.split('\n') would would temporarily double our memory footprint. - // Modifying text would create many large strings to garbage collect. + // Walk the text, pulling out a substring for each line. text.split('\n') would would temporarily double our memory footprint. Modifying text would create many large strings to garbage collect. lineStart := 0 lineEnd := -1 runes := []rune{} @@ -616,8 +403,7 @@ func (dmp *DiffMatchPatch) diffLinesToRunesMunge(text string, lineArray *[]strin return runes } -// DiffCharsToLines rehydrates the text in a diff from a string of line hashes to real lines of -// text. +// DiffCharsToLines rehydrates the text in a diff from a string of line hashes to real lines of text. func (dmp *DiffMatchPatch) DiffCharsToLines(diffs []Diff, lineArray []string) []Diff { hydrated := make([]Diff, 0, len(diffs)) for _, aDiff := range diffs { @@ -670,6 +456,7 @@ func commonSuffixLength(text1, text2 []rune) int { } return n + // TODO research and benchmark this, why is it not activated? https://github.com/sergi/go-diff/issues/54 // Binary search. // Performance analysis: http://neil.fraser.name/news/2007/10/09/ /* @@ -712,9 +499,7 @@ func (dmp *DiffMatchPatch) DiffCommonOverlap(text1 string, text2 string) int { return textLength } - // Start by looking for a single character match - // and increase length until no match is found. - // Performance analysis: http://neil.fraser.name/news/2010/11/04/ + // Start by looking for a single character match and increase length until no match is found. Performance analysis: http://neil.fraser.name/news/2010/11/04/ best := 0 length := 1 for { @@ -733,8 +518,7 @@ func (dmp *DiffMatchPatch) DiffCommonOverlap(text1 string, text2 string) int { return best } -// DiffHalfMatch checks whether the two texts share a substring which is at -// least half the length of the longer text. This speedup can produce non-minimal diffs. +// DiffHalfMatch checks whether the two texts share a substring which is at least half the length of the longer text. This speedup can produce non-minimal diffs. func (dmp *DiffMatchPatch) DiffHalfMatch(text1, text2 string) []string { // Unused in this code, but retained for interface compatibility. runeSlices := dmp.diffHalfMatch([]rune(text1), []rune(text2)) @@ -799,12 +583,7 @@ func (dmp *DiffMatchPatch) diffHalfMatch(text1, text2 []rune) [][]rune { } // diffHalfMatchI checks if a substring of shorttext exist within longtext such that the substring is at least half the length of longtext? -// @param {string} longtext Longer string. -// @param {string} shorttext Shorter string. -// @param {number} i Start index of quarter length substring within longtext. -// @return {Array.} Five element Array, containing the prefix of -// longtext, the suffix of longtext, the prefix of shorttext, the suffix -// of shorttext and the common middle. Or null if there was no match. +// Returns a slice containing the prefix of longtext, the suffix of longtext, the prefix of shorttext, the suffix of shorttext and the common middle, or null if there was no match. func (dmp *DiffMatchPatch) diffHalfMatchI(l, s []rune, i int) [][]rune { var bestCommonA []rune var bestCommonB []rune @@ -845,8 +624,7 @@ func (dmp *DiffMatchPatch) diffHalfMatchI(l, s []rune, i int) [][]rune { } } -// DiffCleanupSemantic reduces the number of edits by eliminating -// semantically trivial equalities. +// DiffCleanupSemantic reduces the number of edits by eliminating semantically trivial equalities. func (dmp *DiffMatchPatch) DiffCleanupSemantic(diffs []Diff) []Diff { changes := false // Stack of indices where equalities are found. @@ -865,7 +643,9 @@ func (dmp *DiffMatchPatch) DiffCleanupSemantic(diffs []Diff) []Diff { var lengthInsertions2, lengthDeletions2 int for pointer < len(diffs) { - if diffs[pointer].Type == DiffEqual { // Equality found. + if diffs[pointer].Type == DiffEqual { + // Equality found. + equalities = &equality{ data: pointer, next: equalities, @@ -875,14 +655,15 @@ func (dmp *DiffMatchPatch) DiffCleanupSemantic(diffs []Diff) []Diff { lengthInsertions2 = 0 lengthDeletions2 = 0 lastequality = diffs[pointer].Text - } else { // An insertion or deletion. + } else { + // An insertion or deletion. + if diffs[pointer].Type == DiffInsert { lengthInsertions2 += len(diffs[pointer].Text) } else { lengthDeletions2 += len(diffs[pointer].Text) } - // Eliminate an equality that is smaller or equal to the edits on both - // sides of it. + // Eliminate an equality that is smaller or equal to the edits on both sides of it. difference1 := int(math.Max(float64(lengthInsertions1), float64(lengthDeletions1))) difference2 := int(math.Max(float64(lengthInsertions2), float64(lengthDeletions2))) if len(lastequality) > 0 && @@ -942,12 +723,11 @@ func (dmp *DiffMatchPatch) DiffCleanupSemantic(diffs []Diff) []Diff { if float64(overlapLength1) >= float64(len(deletion))/2 || float64(overlapLength1) >= float64(len(insertion))/2 { - // Overlap found. Insert an equality and trim the surrounding edits. + // Overlap found. Insert an equality and trim the surrounding edits. diffs = append( diffs[:pointer], append([]Diff{Diff{DiffEqual, insertion[:overlapLength1]}}, diffs[pointer:]...)...) - //diffs.splice(pointer, 0, - // [DiffEqual, insertion[0 : overlapLength1)]] + diffs[pointer-1].Text = deletion[0 : len(deletion)-overlapLength1] diffs[pointer+1].Text = insertion[overlapLength1:] @@ -956,14 +736,12 @@ func (dmp *DiffMatchPatch) DiffCleanupSemantic(diffs []Diff) []Diff { } else { if float64(overlapLength2) >= float64(len(deletion))/2 || float64(overlapLength2) >= float64(len(insertion))/2 { - // Reverse overlap found. - // Insert an equality and swap and trim the surrounding edits. + // Reverse overlap found. Insert an equality and swap and trim the surrounding edits. overlap := Diff{DiffEqual, deletion[:overlapLength2]} diffs = append( diffs[:pointer], append([]Diff{overlap}, diffs[pointer:]...)...) - // diffs.splice(pointer, 0, - // [DiffEqual, deletion[0 : overlapLength2)]] + diffs[pointer-1].Type = DiffInsert diffs[pointer-1].Text = insertion[0 : len(insertion)-overlapLength2] diffs[pointer+1].Type = DiffDelete @@ -979,65 +757,60 @@ func (dmp *DiffMatchPatch) DiffCleanupSemantic(diffs []Diff) []Diff { return diffs } -// DiffCleanupSemanticLossless looks for single edits surrounded on both sides by equalities -// which can be shifted sideways to align the edit to a word boundary. -// e.g: The cat came. -> The cat came. -func (dmp *DiffMatchPatch) DiffCleanupSemanticLossless(diffs []Diff) []Diff { +// Define some regex patterns for matching boundaries. +var ( + nonAlphaNumericRegex = regexp.MustCompile(`[^a-zA-Z0-9]`) + whitespaceRegex = regexp.MustCompile(`\s`) + linebreakRegex = regexp.MustCompile(`[\r\n]`) + blanklineEndRegex = regexp.MustCompile(`\n\r?\n$`) + blanklineStartRegex = regexp.MustCompile(`^\r?\n\r?\n`) +) - /** - * Given two strings, compute a score representing whether the internal - * boundary falls on logical boundaries. - * Scores range from 6 (best) to 0 (worst). - * Closure, but does not reference any external variables. - * @param {string} one First string. - * @param {string} two Second string. - * @return {number} The score. - * @private - */ - diffCleanupSemanticScore := func(one, two string) int { - if len(one) == 0 || len(two) == 0 { - // Edges are the best. - return 6 - } - - // Each port of this function behaves slightly differently due to - // subtle differences in each language's definition of things like - // 'whitespace'. Since this function's purpose is largely cosmetic, - // the choice has been made to use each language's native features - // rather than force total conformity. - rune1, _ := utf8.DecodeLastRuneInString(one) - rune2, _ := utf8.DecodeRuneInString(two) - char1 := string(rune1) - char2 := string(rune2) - - nonAlphaNumeric1 := nonAlphaNumericRegex.MatchString(char1) - nonAlphaNumeric2 := nonAlphaNumericRegex.MatchString(char2) - whitespace1 := nonAlphaNumeric1 && whitespaceRegex.MatchString(char1) - whitespace2 := nonAlphaNumeric2 && whitespaceRegex.MatchString(char2) - lineBreak1 := whitespace1 && linebreakRegex.MatchString(char1) - lineBreak2 := whitespace2 && linebreakRegex.MatchString(char2) - blankLine1 := lineBreak1 && blanklineEndRegex.MatchString(one) - blankLine2 := lineBreak2 && blanklineEndRegex.MatchString(two) - - if blankLine1 || blankLine2 { - // Five points for blank lines. - return 5 - } else if lineBreak1 || lineBreak2 { - // Four points for line breaks. - return 4 - } else if nonAlphaNumeric1 && !whitespace1 && whitespace2 { - // Three points for end of sentences. - return 3 - } else if whitespace1 || whitespace2 { - // Two points for whitespace. - return 2 - } else if nonAlphaNumeric1 || nonAlphaNumeric2 { - // One point for non-alphanumeric. - return 1 - } - return 0 +// diffCleanupSemanticScore computes a score representing whether the internal boundary falls on logical boundaries. +// Scores range from 6 (best) to 0 (worst). Closure, but does not reference any external variables. +func diffCleanupSemanticScore(one, two string) int { + if len(one) == 0 || len(two) == 0 { + // Edges are the best. + return 6 } + // Each port of this function behaves slightly differently due to subtle differences in each language's definition of things like 'whitespace'. Since this function's purpose is largely cosmetic, the choice has been made to use each language's native features rather than force total conformity. + rune1, _ := utf8.DecodeLastRuneInString(one) + rune2, _ := utf8.DecodeRuneInString(two) + char1 := string(rune1) + char2 := string(rune2) + + nonAlphaNumeric1 := nonAlphaNumericRegex.MatchString(char1) + nonAlphaNumeric2 := nonAlphaNumericRegex.MatchString(char2) + whitespace1 := nonAlphaNumeric1 && whitespaceRegex.MatchString(char1) + whitespace2 := nonAlphaNumeric2 && whitespaceRegex.MatchString(char2) + lineBreak1 := whitespace1 && linebreakRegex.MatchString(char1) + lineBreak2 := whitespace2 && linebreakRegex.MatchString(char2) + blankLine1 := lineBreak1 && blanklineEndRegex.MatchString(one) + blankLine2 := lineBreak2 && blanklineEndRegex.MatchString(two) + + if blankLine1 || blankLine2 { + // Five points for blank lines. + return 5 + } else if lineBreak1 || lineBreak2 { + // Four points for line breaks. + return 4 + } else if nonAlphaNumeric1 && !whitespace1 && whitespace2 { + // Three points for end of sentences. + return 3 + } else if whitespace1 || whitespace2 { + // Two points for whitespace. + return 2 + } else if nonAlphaNumeric1 || nonAlphaNumeric2 { + // One point for non-alphanumeric. + return 1 + } + return 0 +} + +// DiffCleanupSemanticLossless looks for single edits surrounded on both sides by equalities which can be shifted sideways to align the edit to a word boundary. +// E.g: The cat came. -> The cat came. +func (dmp *DiffMatchPatch) DiffCleanupSemanticLossless(diffs []Diff) []Diff { pointer := 1 // Intentionally ignore the first and last element (don't need checking). @@ -1076,8 +849,7 @@ func (dmp *DiffMatchPatch) DiffCleanupSemanticLossless(diffs []Diff) []Diff { equality2 = equality2[sz:] score := diffCleanupSemanticScore(equality1, edit) + diffCleanupSemanticScore(edit, equality2) - // The >= encourages trailing rather than leading whitespace on - // edits. + // The >= encourages trailing rather than leading whitespace on edits. if score >= bestScore { bestScore = score bestEquality1 = equality1 @@ -1099,7 +871,6 @@ func (dmp *DiffMatchPatch) DiffCleanupSemanticLossless(diffs []Diff) []Diff { if len(bestEquality2) != 0 { diffs[pointer+1].Text = bestEquality2 } else { - //splice(diffs, pointer+1, 1) diffs = append(diffs[:pointer+1], diffs[pointer+2:]...) pointer-- } @@ -1111,8 +882,7 @@ func (dmp *DiffMatchPatch) DiffCleanupSemanticLossless(diffs []Diff) []Diff { return diffs } -// DiffCleanupEfficiency reduces the number of edits by eliminating -// operationally trivial equalities. +// DiffCleanupEfficiency reduces the number of edits by eliminating operationally trivial equalities. func (dmp *DiffMatchPatch) DiffCleanupEfficiency(diffs []Diff) []Diff { changes := false // Stack of indices where equalities are found. @@ -1157,14 +927,13 @@ func (dmp *DiffMatchPatch) DiffCleanupEfficiency(diffs []Diff) []Diff { } else { postIns = true } - /* - * Five types to be split: - * ABXYCD - * AXCD - * ABXC - * AXCD - * ABXC - */ + + // Five types to be split: + // ABXYCD + // AXCD + // ABXC + // AXCD + // ABXC var sumPres int if preIns { sumPres++ @@ -1224,7 +993,7 @@ func (dmp *DiffMatchPatch) DiffCleanupEfficiency(diffs []Diff) []Diff { return diffs } -// DiffCleanupMerge reorders and merges like edit sections. Merge equalities. +// DiffCleanupMerge reorders and merges like edit sections. Merge equalities. // Any edit section can move as long as it doesn't cross an equality. func (dmp *DiffMatchPatch) DiffCleanupMerge(diffs []Diff) []Diff { // Add a dummy entry at the end. @@ -1317,9 +1086,7 @@ func (dmp *DiffMatchPatch) DiffCleanupMerge(diffs []Diff) []Diff { diffs = diffs[0 : len(diffs)-1] // Remove the dummy entry at the end. } - // Second pass: look for single edits surrounded on both sides by - // equalities which can be shifted sideways to eliminate an equality. - // e.g: ABAC -> ABAC + // Second pass: look for single edits surrounded on both sides by equalities which can be shifted sideways to eliminate an equality. E.g: ABAC -> ABAC changes := false pointer = 1 // Intentionally ignore the first and last element (don't need checking). @@ -1355,9 +1122,6 @@ func (dmp *DiffMatchPatch) DiffCleanupMerge(diffs []Diff) []Diff { } // DiffXIndex returns the equivalent location in s2. -// loc is a location in text1, comAdde and return the equivalent location in -// text2. -// e.g. "The cat" vs "The big cat", 1->1, 5->8 func (dmp *DiffMatchPatch) DiffXIndex(diffs []Diff, loc int) int { chars1 := 0 chars2 := 0 @@ -1391,8 +1155,7 @@ func (dmp *DiffMatchPatch) DiffXIndex(diffs []Diff, loc int) int { } // DiffPrettyHtml converts a []Diff into a pretty HTML report. -// It is intended as an example from which to write one's own -// display functions. +// It is intended as an example from which to write one's own display functions. func (dmp *DiffMatchPatch) DiffPrettyHtml(diffs []Diff) string { var buff bytes.Buffer for _, diff := range diffs { @@ -1463,8 +1226,7 @@ func (dmp *DiffMatchPatch) DiffText2(diffs []Diff) string { return text.String() } -// DiffLevenshtein computes the Levenshtein distance; the number of inserted, deleted or -// substituted characters. +// DiffLevenshtein computes the Levenshtein distance that is the number of inserted, deleted or substituted characters. func (dmp *DiffMatchPatch) DiffLevenshtein(diffs []Diff) int { levenshtein := 0 insertions := 0 @@ -1488,11 +1250,8 @@ func (dmp *DiffMatchPatch) DiffLevenshtein(diffs []Diff) int { return levenshtein } -// DiffToDelta crushes the diff into an encoded string which describes the operations -// required to transform text1 into text2. -// E.g. =3\t-2\t+ing -> Keep 3 chars, delete 2 chars, insert 'ing'. -// Operations are tab-separated. Inserted text is escaped using %xx -// notation. +// DiffToDelta crushes the diff into an encoded string which describes the operations required to transform text1 into text2. +// E.g. =3\t-2\t+ing -> Keep 3 chars, delete 2 chars, insert 'ing'. Operations are tab-separated. Inserted text is escaped using %xx notation. func (dmp *DiffMatchPatch) DiffToDelta(diffs []Diff) string { var text bytes.Buffer for _, aDiff := range diffs { @@ -1523,33 +1282,23 @@ func (dmp *DiffMatchPatch) DiffToDelta(diffs []Diff) string { return delta } -// DiffFromDelta given the original text1, and an encoded string which describes the -// operations required to transform text1 into text2, comAdde the full diff. -func (dmp *DiffMatchPatch) DiffFromDelta(text1, delta string) (diffs []Diff, err error) { - diffs = []Diff{} +// DiffFromDelta given the original text1, and an encoded string which describes the operations required to transform text1 into text2, comAdde the full diff. +func (dmp *DiffMatchPatch) DiffFromDelta(text1 string, delta string) (diffs []Diff, err error) { + i := 0 + runes := []rune(text1) - defer func() { - if r := recover(); r != nil { - err = r.(error) - } - }() - - pointer := 0 // Cursor in text1 - tokens := strings.Split(delta, "\t") - - for _, token := range tokens { + for _, token := range strings.Split(delta, "\t") { if len(token) == 0 { // Blank tokens are ok (from a trailing \t). continue } - // Each token begins with a one character parameter which specifies the - // operation of this token (delete, insert, equality). + // Each token begins with a one character parameter which specifies the operation of this token (delete, insert, equality). param := token[1:] switch op := token[0]; op { case '+': - // decode would Diff all "+" to " " + // Decode would Diff all "+" to " " param = strings.Replace(param, "+", "%2b", -1) param, err = url.QueryUnescape(param) if err != nil { @@ -1558,18 +1307,23 @@ func (dmp *DiffMatchPatch) DiffFromDelta(text1, delta string) (diffs []Diff, err if !utf8.ValidString(param) { return nil, fmt.Errorf("invalid UTF-8 token: %q", param) } + diffs = append(diffs, Diff{DiffInsert, param}) case '=', '-': n, err := strconv.ParseInt(param, 10, 0) if err != nil { - return diffs, err + return nil, err } else if n < 0 { - return diffs, errors.New("Negative number in DiffFromDelta: " + param) + return nil, errors.New("Negative number in DiffFromDelta: " + param) } - // remember that string slicing is by byte - we want by rune here. - text := string([]rune(text1)[pointer : pointer+int(n)]) - pointer += int(n) + i += int(n) + // Break out if we are out of bounds, go1.6 can't handle this very well + if i > len(runes) { + break + } + // Remember that string slicing is by byte - we want by rune here. + text := string(runes[i-int(n) : i]) if op == '=' { diffs = append(diffs, Diff{DiffEqual, text}) @@ -1578,667 +1332,13 @@ func (dmp *DiffMatchPatch) DiffFromDelta(text1, delta string) (diffs []Diff, err } default: // Anything else is an error. - return diffs, errors.New("Invalid diff operation in DiffFromDelta: " + string(token[0])) + return nil, errors.New("Invalid diff operation in DiffFromDelta: " + string(token[0])) } } - if pointer != len([]rune(text1)) { - return diffs, fmt.Errorf("Delta length (%v) smaller than source text length (%v)", pointer, len(text1)) + if i != len(runes) { + return nil, fmt.Errorf("Delta length (%v) is different from source text length (%v)", i, len(text1)) } - return diffs, err -} - -// MATCH FUNCTIONS - -// MatchMain locates the best instance of 'pattern' in 'text' near 'loc'. -// Returns -1 if no match found. -func (dmp *DiffMatchPatch) MatchMain(text, pattern string, loc int) int { - // Check for null inputs not needed since null can't be passed in C#. - - loc = int(math.Max(0, math.Min(float64(loc), float64(len(text))))) - if text == pattern { - // Shortcut (potentially not guaranteed by the algorithm) - return 0 - } else if len(text) == 0 { - // Nothing to match. - return -1 - } else if loc+len(pattern) <= len(text) && text[loc:loc+len(pattern)] == pattern { - // Perfect match at the perfect spot! (Includes case of null pattern) - return loc - } - // Do a fuzzy compare. - return dmp.MatchBitap(text, pattern, loc) -} - -// MatchBitap locates the best instance of 'pattern' in 'text' near 'loc' using the -// Bitap algorithm. Returns -1 if no match found. -func (dmp *DiffMatchPatch) MatchBitap(text, pattern string, loc int) int { - // Initialise the alphabet. - s := dmp.MatchAlphabet(pattern) - - // Highest score beyond which we give up. - scoreThreshold := dmp.MatchThreshold - // Is there a nearby exact match? (speedup) - bestLoc := indexOf(text, pattern, loc) - if bestLoc != -1 { - scoreThreshold = math.Min(dmp.matchBitapScore(0, bestLoc, loc, - pattern), scoreThreshold) - // What about in the other direction? (speedup) - bestLoc = lastIndexOf(text, pattern, loc+len(pattern)) - if bestLoc != -1 { - scoreThreshold = math.Min(dmp.matchBitapScore(0, bestLoc, loc, - pattern), scoreThreshold) - } - } - - // Initialise the bit arrays. - matchmask := 1 << uint((len(pattern) - 1)) - bestLoc = -1 - - var binMin, binMid int - binMax := len(pattern) + len(text) - lastRd := []int{} - for d := 0; d < len(pattern); d++ { - // Scan for the best match; each iteration allows for one more error. - // Run a binary search to determine how far from 'loc' we can stray at - // this error level. - binMin = 0 - binMid = binMax - for binMin < binMid { - if dmp.matchBitapScore(d, loc+binMid, loc, pattern) <= scoreThreshold { - binMin = binMid - } else { - binMax = binMid - } - binMid = (binMax-binMin)/2 + binMin - } - // Use the result from this iteration as the maximum for the next. - binMax = binMid - start := int(math.Max(1, float64(loc-binMid+1))) - finish := int(math.Min(float64(loc+binMid), float64(len(text))) + float64(len(pattern))) - - rd := make([]int, finish+2) - rd[finish+1] = (1 << uint(d)) - 1 - - for j := finish; j >= start; j-- { - var charMatch int - if len(text) <= j-1 { - // Out of range. - charMatch = 0 - } else if _, ok := s[text[j-1]]; !ok { - charMatch = 0 - } else { - charMatch = s[text[j-1]] - } - - if d == 0 { - // First pass: exact match. - rd[j] = ((rd[j+1] << 1) | 1) & charMatch - } else { - // Subsequent passes: fuzzy match. - rd[j] = ((rd[j+1]<<1)|1)&charMatch | (((lastRd[j+1] | lastRd[j]) << 1) | 1) | lastRd[j+1] - } - if (rd[j] & matchmask) != 0 { - score := dmp.matchBitapScore(d, j-1, loc, pattern) - // This match will almost certainly be better than any existing - // match. But check anyway. - if score <= scoreThreshold { - // Told you so. - scoreThreshold = score - bestLoc = j - 1 - if bestLoc > loc { - // When passing loc, don't exceed our current distance from loc. - start = int(math.Max(1, float64(2*loc-bestLoc))) - } else { - // Already passed loc, downhill from here on in. - break - } - } - } - } - if dmp.matchBitapScore(d+1, loc, loc, pattern) > scoreThreshold { - // No hope for a (better) match at greater error levels. - break - } - lastRd = rd - } - return bestLoc -} - -// matchBitapScore computes and returns the score for a match with e errors and x location. -func (dmp *DiffMatchPatch) matchBitapScore(e, x, loc int, pattern string) float64 { - accuracy := float64(e) / float64(len(pattern)) - proximity := math.Abs(float64(loc - x)) - if dmp.MatchDistance == 0 { - // Dodge divide by zero error. - if proximity == 0 { - return accuracy - } - - return 1.0 - } - return accuracy + (proximity / float64(dmp.MatchDistance)) -} - -// MatchAlphabet initialises the alphabet for the Bitap algorithm. -func (dmp *DiffMatchPatch) MatchAlphabet(pattern string) map[byte]int { - s := map[byte]int{} - charPattern := []byte(pattern) - for _, c := range charPattern { - _, ok := s[c] - if !ok { - s[c] = 0 - } - } - i := 0 - - for _, c := range charPattern { - value := s[c] | int(uint(1)< 2 { - diffs = dmp.DiffCleanupSemantic(diffs) - diffs = dmp.DiffCleanupEfficiency(diffs) - } - return dmp.PatchMake(text1, diffs) - case []Diff: - return dmp.patchMake2(text1, t) - } - } else if len(opt) == 3 { - return dmp.PatchMake(opt[0], opt[2]) - } - return []Patch{} -} - -// patchMake2 computes a list of patches to turn text1 into text2. -// text2 is not provided, diffs are the delta between text1 and text2. -func (dmp *DiffMatchPatch) patchMake2(text1 string, diffs []Diff) []Patch { - // Check for null inputs not needed since null can't be passed in C#. - patches := []Patch{} - if len(diffs) == 0 { - return patches // Get rid of the null case. - } - - patch := Patch{} - charCount1 := 0 // Number of characters into the text1 string. - charCount2 := 0 // Number of characters into the text2 string. - // Start with text1 (prepatchText) and apply the diffs until we arrive at - // text2 (postpatchText). We recreate the patches one by one to determine - // context info. - prepatchText := text1 - postpatchText := text1 - - for i, aDiff := range diffs { - if len(patch.diffs) == 0 && aDiff.Type != DiffEqual { - // A new patch starts here. - patch.start1 = charCount1 - patch.start2 = charCount2 - } - - switch aDiff.Type { - case DiffInsert: - patch.diffs = append(patch.diffs, aDiff) - patch.length2 += len(aDiff.Text) - postpatchText = postpatchText[:charCount2] + - aDiff.Text + postpatchText[charCount2:] - case DiffDelete: - patch.length1 += len(aDiff.Text) - patch.diffs = append(patch.diffs, aDiff) - postpatchText = postpatchText[:charCount2] + postpatchText[charCount2+len(aDiff.Text):] - case DiffEqual: - if len(aDiff.Text) <= 2*dmp.PatchMargin && - len(patch.diffs) != 0 && i != len(diffs)-1 { - // Small equality inside a patch. - patch.diffs = append(patch.diffs, aDiff) - patch.length1 += len(aDiff.Text) - patch.length2 += len(aDiff.Text) - } - if len(aDiff.Text) >= 2*dmp.PatchMargin { - // Time for a new patch. - if len(patch.diffs) != 0 { - patch = dmp.PatchAddContext(patch, prepatchText) - patches = append(patches, patch) - patch = Patch{} - // Unlike Unidiff, our patch lists have a rolling context. - // http://code.google.com/p/google-diff-match-patch/wiki/Unidiff - // Update prepatch text & pos to reflect the application of the - // just completed patch. - prepatchText = postpatchText - charCount1 = charCount2 - } - } - } - - // Update the current character count. - if aDiff.Type != DiffInsert { - charCount1 += len(aDiff.Text) - } - if aDiff.Type != DiffDelete { - charCount2 += len(aDiff.Text) - } - } - - // Pick up the leftover patch if not empty. - if len(patch.diffs) != 0 { - patch = dmp.PatchAddContext(patch, prepatchText) - patches = append(patches, patch) - } - - return patches -} - -// PatchDeepCopy returns an array that is identical to a -// given an array of patches. -func (dmp *DiffMatchPatch) PatchDeepCopy(patches []Patch) []Patch { - patchesCopy := []Patch{} - for _, aPatch := range patches { - patchCopy := Patch{} - for _, aDiff := range aPatch.diffs { - patchCopy.diffs = append(patchCopy.diffs, Diff{ - aDiff.Type, - aDiff.Text, - }) - } - patchCopy.start1 = aPatch.start1 - patchCopy.start2 = aPatch.start2 - patchCopy.length1 = aPatch.length1 - patchCopy.length2 = aPatch.length2 - patchesCopy = append(patchesCopy, patchCopy) - } - return patchesCopy -} - -// PatchApply merges a set of patches onto the text. Returns a patched text, as well -// as an array of true/false values indicating which patches were applied. -func (dmp *DiffMatchPatch) PatchApply(patches []Patch, text string) (string, []bool) { - if len(patches) == 0 { - return text, []bool{} - } - - // Deep copy the patches so that no changes are made to originals. - patches = dmp.PatchDeepCopy(patches) - - nullPadding := dmp.PatchAddPadding(patches) - text = nullPadding + text + nullPadding - patches = dmp.PatchSplitMax(patches) - - x := 0 - // delta keeps track of the offset between the expected and actual - // location of the previous patch. If there are patches expected at - // positions 10 and 20, but the first patch was found at 12, delta is 2 - // and the second patch has an effective expected position of 22. - delta := 0 - results := make([]bool, len(patches)) - for _, aPatch := range patches { - expectedLoc := aPatch.start2 + delta - text1 := dmp.DiffText1(aPatch.diffs) - var startLoc int - endLoc := -1 - if len(text1) > dmp.MatchMaxBits { - // PatchSplitMax will only provide an oversized pattern - // in the case of a monster delete. - startLoc = dmp.MatchMain(text, text1[:dmp.MatchMaxBits], expectedLoc) - if startLoc != -1 { - endLoc = dmp.MatchMain(text, - text1[len(text1)-dmp.MatchMaxBits:], expectedLoc+len(text1)-dmp.MatchMaxBits) - if endLoc == -1 || startLoc >= endLoc { - // Can't find valid trailing context. Drop this patch. - startLoc = -1 - } - } - } else { - startLoc = dmp.MatchMain(text, text1, expectedLoc) - } - if startLoc == -1 { - // No match found. :( - results[x] = false - // Subtract the delta for this failed patch from subsequent patches. - delta -= aPatch.length2 - aPatch.length1 - } else { - // Found a match. :) - results[x] = true - delta = startLoc - expectedLoc - var text2 string - if endLoc == -1 { - text2 = text[startLoc:int(math.Min(float64(startLoc+len(text1)), float64(len(text))))] - } else { - text2 = text[startLoc:int(math.Min(float64(endLoc+dmp.MatchMaxBits), float64(len(text))))] - } - if text1 == text2 { - // Perfect match, just shove the Replacement text in. - text = text[:startLoc] + dmp.DiffText2(aPatch.diffs) + text[startLoc+len(text1):] - } else { - // Imperfect match. Run a diff to get a framework of equivalent - // indices. - diffs := dmp.DiffMain(text1, text2, false) - if len(text1) > dmp.MatchMaxBits && float64(dmp.DiffLevenshtein(diffs))/float64(len(text1)) > dmp.PatchDeleteThreshold { - // The end points match, but the content is unacceptably bad. - results[x] = false - } else { - diffs = dmp.DiffCleanupSemanticLossless(diffs) - index1 := 0 - for _, aDiff := range aPatch.diffs { - if aDiff.Type != DiffEqual { - index2 := dmp.DiffXIndex(diffs, index1) - if aDiff.Type == DiffInsert { - // Insertion - text = text[:startLoc+index2] + aDiff.Text + text[startLoc+index2:] - } else if aDiff.Type == DiffDelete { - // Deletion - startIndex := startLoc + index2 - text = text[:startIndex] + - text[startIndex+dmp.DiffXIndex(diffs, index1+len(aDiff.Text))-index2:] - } - } - if aDiff.Type != DiffDelete { - index1 += len(aDiff.Text) - } - } - } - } - } - x++ - } - // Strip the padding off. - text = text[len(nullPadding) : len(nullPadding)+(len(text)-2*len(nullPadding))] - return text, results -} - -// PatchAddPadding adds some padding on text start and end so that edges can match something. -// Intended to be called only from within patchApply. -func (dmp *DiffMatchPatch) PatchAddPadding(patches []Patch) string { - paddingLength := dmp.PatchMargin - nullPadding := "" - for x := 1; x <= paddingLength; x++ { - nullPadding += string(x) - } - - // Bump all the patches forward. - for i := range patches { - patches[i].start1 += paddingLength - patches[i].start2 += paddingLength - } - - // Add some padding on start of first diff. - if len(patches[0].diffs) == 0 || patches[0].diffs[0].Type != DiffEqual { - // Add nullPadding equality. - patches[0].diffs = append([]Diff{Diff{DiffEqual, nullPadding}}, patches[0].diffs...) - patches[0].start1 -= paddingLength // Should be 0. - patches[0].start2 -= paddingLength // Should be 0. - patches[0].length1 += paddingLength - patches[0].length2 += paddingLength - } else if paddingLength > len(patches[0].diffs[0].Text) { - // Grow first equality. - extraLength := paddingLength - len(patches[0].diffs[0].Text) - patches[0].diffs[0].Text = nullPadding[len(patches[0].diffs[0].Text):] + patches[0].diffs[0].Text - patches[0].start1 -= extraLength - patches[0].start2 -= extraLength - patches[0].length1 += extraLength - patches[0].length2 += extraLength - } - - // Add some padding on end of last diff. - last := len(patches) - 1 - if len(patches[last].diffs) == 0 || patches[last].diffs[len(patches[last].diffs)-1].Type != DiffEqual { - // Add nullPadding equality. - patches[last].diffs = append(patches[last].diffs, Diff{DiffEqual, nullPadding}) - patches[last].length1 += paddingLength - patches[last].length2 += paddingLength - } else if paddingLength > len(patches[last].diffs[len(patches[last].diffs)-1].Text) { - // Grow last equality. - lastDiff := patches[last].diffs[len(patches[last].diffs)-1] - extraLength := paddingLength - len(lastDiff.Text) - patches[last].diffs[len(patches[last].diffs)-1].Text += nullPadding[:extraLength] - patches[last].length1 += extraLength - patches[last].length2 += extraLength - } - - return nullPadding -} - -// PatchSplitMax looks through the patches and breaks up any which are longer than the -// maximum limit of the match algorithm. -// Intended to be called only from within patchApply. -func (dmp *DiffMatchPatch) PatchSplitMax(patches []Patch) []Patch { - patchSize := dmp.MatchMaxBits - for x := 0; x < len(patches); x++ { - if patches[x].length1 <= patchSize { - continue - } - bigpatch := patches[x] - // Remove the big old patch. - patches = append(patches[:x], patches[x+1:]...) - x-- - - start1 := bigpatch.start1 - start2 := bigpatch.start2 - precontext := "" - for len(bigpatch.diffs) != 0 { - // Create one of several smaller patches. - patch := Patch{} - empty := true - patch.start1 = start1 - len(precontext) - patch.start2 = start2 - len(precontext) - if len(precontext) != 0 { - patch.length1 = len(precontext) - patch.length2 = len(precontext) - patch.diffs = append(patch.diffs, Diff{DiffEqual, precontext}) - } - for len(bigpatch.diffs) != 0 && patch.length1 < patchSize-dmp.PatchMargin { - diffType := bigpatch.diffs[0].Type - diffText := bigpatch.diffs[0].Text - if diffType == DiffInsert { - // Insertions are harmless. - patch.length2 += len(diffText) - start2 += len(diffText) - patch.diffs = append(patch.diffs, bigpatch.diffs[0]) - bigpatch.diffs = bigpatch.diffs[1:] - empty = false - } else if diffType == DiffDelete && len(patch.diffs) == 1 && patch.diffs[0].Type == DiffEqual && len(diffText) > 2*patchSize { - // This is a large deletion. Let it pass in one chunk. - patch.length1 += len(diffText) - start1 += len(diffText) - empty = false - patch.diffs = append(patch.diffs, Diff{diffType, diffText}) - bigpatch.diffs = bigpatch.diffs[1:] - } else { - // Deletion or equality. Only take as much as we can stomach. - diffText = diffText[:min(len(diffText), patchSize-patch.length1-dmp.PatchMargin)] - - patch.length1 += len(diffText) - start1 += len(diffText) - if diffType == DiffEqual { - patch.length2 += len(diffText) - start2 += len(diffText) - } else { - empty = false - } - patch.diffs = append(patch.diffs, Diff{diffType, diffText}) - if diffText == bigpatch.diffs[0].Text { - bigpatch.diffs = bigpatch.diffs[1:] - } else { - bigpatch.diffs[0].Text = - bigpatch.diffs[0].Text[len(diffText):] - } - } - } - // Compute the head context for the next patch. - precontext = dmp.DiffText2(patch.diffs) - precontext = precontext[max(0, len(precontext)-dmp.PatchMargin):] - - postcontext := "" - // Append the end context for this patch. - if len(dmp.DiffText1(bigpatch.diffs)) > dmp.PatchMargin { - postcontext = dmp.DiffText1(bigpatch.diffs)[:dmp.PatchMargin] - } else { - postcontext = dmp.DiffText1(bigpatch.diffs) - } - - if len(postcontext) != 0 { - patch.length1 += len(postcontext) - patch.length2 += len(postcontext) - if len(patch.diffs) != 0 && patch.diffs[len(patch.diffs)-1].Type == DiffEqual { - patch.diffs[len(patch.diffs)-1].Text += postcontext - } else { - patch.diffs = append(patch.diffs, Diff{DiffEqual, postcontext}) - } - } - if !empty { - x++ - patches = append(patches[:x], append([]Patch{patch}, patches[x:]...)...) - } - } - } - return patches -} - -// PatchToText takes a list of patches and returns a textual representation. -func (dmp *DiffMatchPatch) PatchToText(patches []Patch) string { - var text bytes.Buffer - for _, aPatch := range patches { - _, _ = text.WriteString(aPatch.String()) - } - return text.String() -} - -// PatchFromText parses a textual representation of patches and returns a List of Patch -// objects. -func (dmp *DiffMatchPatch) PatchFromText(textline string) ([]Patch, error) { - patches := []Patch{} - if len(textline) == 0 { - return patches, nil - } - text := strings.Split(textline, "\n") - textPointer := 0 - patchHeader := regexp.MustCompile("^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$") - - var patch Patch - var sign uint8 - var line string - for textPointer < len(text) { - - if !patchHeader.MatchString(text[textPointer]) { - return patches, errors.New("Invalid patch string: " + text[textPointer]) - } - - patch = Patch{} - m := patchHeader.FindStringSubmatch(text[textPointer]) - - patch.start1, _ = strconv.Atoi(m[1]) - if len(m[2]) == 0 { - patch.start1-- - patch.length1 = 1 - } else if m[2] == "0" { - patch.length1 = 0 - } else { - patch.start1-- - patch.length1, _ = strconv.Atoi(m[2]) - } - - patch.start2, _ = strconv.Atoi(m[3]) - - if len(m[4]) == 0 { - patch.start2-- - patch.length2 = 1 - } else if m[4] == "0" { - patch.length2 = 0 - } else { - patch.start2-- - patch.length2, _ = strconv.Atoi(m[4]) - } - textPointer++ - - for textPointer < len(text) { - if len(text[textPointer]) > 0 { - sign = text[textPointer][0] - } else { - textPointer++ - continue - } - - line = text[textPointer][1:] - line = strings.Replace(line, "+", "%2b", -1) - line, _ = url.QueryUnescape(line) - if sign == '-' { - // Deletion. - patch.diffs = append(patch.diffs, Diff{DiffDelete, line}) - } else if sign == '+' { - // Insertion. - patch.diffs = append(patch.diffs, Diff{DiffInsert, line}) - } else if sign == ' ' { - // Minor equality. - patch.diffs = append(patch.diffs, Diff{DiffEqual, line}) - } else if sign == '@' { - // Start of next patch. - break - } else { - // WTF? - return patches, errors.New("Invalid patch mode '" + string(sign) + "' in: " + string(line)) - } - textPointer++ - } - - patches = append(patches, patch) - } - return patches, nil + + return diffs, nil } diff --git a/vendor/github.com/sergi/go-diff/diffmatchpatch/diffmatchpatch.go b/vendor/github.com/sergi/go-diff/diffmatchpatch/diffmatchpatch.go new file mode 100644 index 0000000000..d3acc32ce1 --- /dev/null +++ b/vendor/github.com/sergi/go-diff/diffmatchpatch/diffmatchpatch.go @@ -0,0 +1,46 @@ +// Copyright (c) 2012-2016 The go-diff authors. All rights reserved. +// https://github.com/sergi/go-diff +// See the included LICENSE file for license details. +// +// go-diff is a Go implementation of Google's Diff, Match, and Patch library +// Original library is Copyright (c) 2006 Google Inc. +// http://code.google.com/p/google-diff-match-patch/ + +// Package diffmatchpatch offers robust algorithms to perform the operations required for synchronizing plain text. +package diffmatchpatch + +import ( + "time" +) + +// DiffMatchPatch holds the configuration for diff-match-patch operations. +type DiffMatchPatch struct { + // Number of seconds to map a diff before giving up (0 for infinity). + DiffTimeout time.Duration + // Cost of an empty edit operation in terms of edit characters. + DiffEditCost int + // How far to search for a match (0 = exact location, 1000+ = broad match). A match this many characters away from the expected location will add 1.0 to the score (0.0 is a perfect match). + MatchDistance int + // When deleting a large block of text (over ~64 characters), how close do the contents have to be to match the expected contents. (0.0 = perfection, 1.0 = very loose). Note that MatchThreshold controls how closely the end points of a delete need to match. + PatchDeleteThreshold float64 + // Chunk size for context length. + PatchMargin int + // The number of bits in an int. + MatchMaxBits int + // At what point is no match declared (0.0 = perfection, 1.0 = very loose). + MatchThreshold float64 +} + +// New creates a new DiffMatchPatch object with default parameters. +func New() *DiffMatchPatch { + // Defaults. + return &DiffMatchPatch{ + DiffTimeout: time.Second, + DiffEditCost: 4, + MatchThreshold: 0.5, + MatchDistance: 1000, + PatchDeleteThreshold: 0.5, + PatchMargin: 4, + MatchMaxBits: 32, + } +} diff --git a/vendor/github.com/sergi/go-diff/diffmatchpatch/match.go b/vendor/github.com/sergi/go-diff/diffmatchpatch/match.go new file mode 100644 index 0000000000..17374e109f --- /dev/null +++ b/vendor/github.com/sergi/go-diff/diffmatchpatch/match.go @@ -0,0 +1,160 @@ +// Copyright (c) 2012-2016 The go-diff authors. All rights reserved. +// https://github.com/sergi/go-diff +// See the included LICENSE file for license details. +// +// go-diff is a Go implementation of Google's Diff, Match, and Patch library +// Original library is Copyright (c) 2006 Google Inc. +// http://code.google.com/p/google-diff-match-patch/ + +package diffmatchpatch + +import ( + "math" +) + +// MatchMain locates the best instance of 'pattern' in 'text' near 'loc'. +// Returns -1 if no match found. +func (dmp *DiffMatchPatch) MatchMain(text, pattern string, loc int) int { + // Check for null inputs not needed since null can't be passed in C#. + + loc = int(math.Max(0, math.Min(float64(loc), float64(len(text))))) + if text == pattern { + // Shortcut (potentially not guaranteed by the algorithm) + return 0 + } else if len(text) == 0 { + // Nothing to match. + return -1 + } else if loc+len(pattern) <= len(text) && text[loc:loc+len(pattern)] == pattern { + // Perfect match at the perfect spot! (Includes case of null pattern) + return loc + } + // Do a fuzzy compare. + return dmp.MatchBitap(text, pattern, loc) +} + +// MatchBitap locates the best instance of 'pattern' in 'text' near 'loc' using the Bitap algorithm. +// Returns -1 if no match was found. +func (dmp *DiffMatchPatch) MatchBitap(text, pattern string, loc int) int { + // Initialise the alphabet. + s := dmp.MatchAlphabet(pattern) + + // Highest score beyond which we give up. + scoreThreshold := dmp.MatchThreshold + // Is there a nearby exact match? (speedup) + bestLoc := indexOf(text, pattern, loc) + if bestLoc != -1 { + scoreThreshold = math.Min(dmp.matchBitapScore(0, bestLoc, loc, + pattern), scoreThreshold) + // What about in the other direction? (speedup) + bestLoc = lastIndexOf(text, pattern, loc+len(pattern)) + if bestLoc != -1 { + scoreThreshold = math.Min(dmp.matchBitapScore(0, bestLoc, loc, + pattern), scoreThreshold) + } + } + + // Initialise the bit arrays. + matchmask := 1 << uint((len(pattern) - 1)) + bestLoc = -1 + + var binMin, binMid int + binMax := len(pattern) + len(text) + lastRd := []int{} + for d := 0; d < len(pattern); d++ { + // Scan for the best match; each iteration allows for one more error. Run a binary search to determine how far from 'loc' we can stray at this error level. + binMin = 0 + binMid = binMax + for binMin < binMid { + if dmp.matchBitapScore(d, loc+binMid, loc, pattern) <= scoreThreshold { + binMin = binMid + } else { + binMax = binMid + } + binMid = (binMax-binMin)/2 + binMin + } + // Use the result from this iteration as the maximum for the next. + binMax = binMid + start := int(math.Max(1, float64(loc-binMid+1))) + finish := int(math.Min(float64(loc+binMid), float64(len(text))) + float64(len(pattern))) + + rd := make([]int, finish+2) + rd[finish+1] = (1 << uint(d)) - 1 + + for j := finish; j >= start; j-- { + var charMatch int + if len(text) <= j-1 { + // Out of range. + charMatch = 0 + } else if _, ok := s[text[j-1]]; !ok { + charMatch = 0 + } else { + charMatch = s[text[j-1]] + } + + if d == 0 { + // First pass: exact match. + rd[j] = ((rd[j+1] << 1) | 1) & charMatch + } else { + // Subsequent passes: fuzzy match. + rd[j] = ((rd[j+1]<<1)|1)&charMatch | (((lastRd[j+1] | lastRd[j]) << 1) | 1) | lastRd[j+1] + } + if (rd[j] & matchmask) != 0 { + score := dmp.matchBitapScore(d, j-1, loc, pattern) + // This match will almost certainly be better than any existing match. But check anyway. + if score <= scoreThreshold { + // Told you so. + scoreThreshold = score + bestLoc = j - 1 + if bestLoc > loc { + // When passing loc, don't exceed our current distance from loc. + start = int(math.Max(1, float64(2*loc-bestLoc))) + } else { + // Already passed loc, downhill from here on in. + break + } + } + } + } + if dmp.matchBitapScore(d+1, loc, loc, pattern) > scoreThreshold { + // No hope for a (better) match at greater error levels. + break + } + lastRd = rd + } + return bestLoc +} + +// matchBitapScore computes and returns the score for a match with e errors and x location. +func (dmp *DiffMatchPatch) matchBitapScore(e, x, loc int, pattern string) float64 { + accuracy := float64(e) / float64(len(pattern)) + proximity := math.Abs(float64(loc - x)) + if dmp.MatchDistance == 0 { + // Dodge divide by zero error. + if proximity == 0 { + return accuracy + } + + return 1.0 + } + return accuracy + (proximity / float64(dmp.MatchDistance)) +} + +// MatchAlphabet initialises the alphabet for the Bitap algorithm. +func (dmp *DiffMatchPatch) MatchAlphabet(pattern string) map[byte]int { + s := map[byte]int{} + charPattern := []byte(pattern) + for _, c := range charPattern { + _, ok := s[c] + if !ok { + s[c] = 0 + } + } + i := 0 + + for _, c := range charPattern { + value := s[c] | int(uint(1)< y { + return x + } + return y +} diff --git a/vendor/github.com/sergi/go-diff/diffmatchpatch/patch.go b/vendor/github.com/sergi/go-diff/diffmatchpatch/patch.go new file mode 100644 index 0000000000..223c43c426 --- /dev/null +++ b/vendor/github.com/sergi/go-diff/diffmatchpatch/patch.go @@ -0,0 +1,556 @@ +// Copyright (c) 2012-2016 The go-diff authors. All rights reserved. +// https://github.com/sergi/go-diff +// See the included LICENSE file for license details. +// +// go-diff is a Go implementation of Google's Diff, Match, and Patch library +// Original library is Copyright (c) 2006 Google Inc. +// http://code.google.com/p/google-diff-match-patch/ + +package diffmatchpatch + +import ( + "bytes" + "errors" + "math" + "net/url" + "regexp" + "strconv" + "strings" +) + +// Patch represents one patch operation. +type Patch struct { + diffs []Diff + Start1 int + Start2 int + Length1 int + Length2 int +} + +// String emulates GNU diff's format. +// Header: @@ -382,8 +481,9 @@ +// Indices are printed as 1-based, not 0-based. +func (p *Patch) String() string { + var coords1, coords2 string + + if p.Length1 == 0 { + coords1 = strconv.Itoa(p.Start1) + ",0" + } else if p.Length1 == 1 { + coords1 = strconv.Itoa(p.Start1 + 1) + } else { + coords1 = strconv.Itoa(p.Start1+1) + "," + strconv.Itoa(p.Length1) + } + + if p.Length2 == 0 { + coords2 = strconv.Itoa(p.Start2) + ",0" + } else if p.Length2 == 1 { + coords2 = strconv.Itoa(p.Start2 + 1) + } else { + coords2 = strconv.Itoa(p.Start2+1) + "," + strconv.Itoa(p.Length2) + } + + var text bytes.Buffer + _, _ = text.WriteString("@@ -" + coords1 + " +" + coords2 + " @@\n") + + // Escape the body of the patch with %xx notation. + for _, aDiff := range p.diffs { + switch aDiff.Type { + case DiffInsert: + _, _ = text.WriteString("+") + case DiffDelete: + _, _ = text.WriteString("-") + case DiffEqual: + _, _ = text.WriteString(" ") + } + + _, _ = text.WriteString(strings.Replace(url.QueryEscape(aDiff.Text), "+", " ", -1)) + _, _ = text.WriteString("\n") + } + + return unescaper.Replace(text.String()) +} + +// PatchAddContext increases the context until it is unique, but doesn't let the pattern expand beyond MatchMaxBits. +func (dmp *DiffMatchPatch) PatchAddContext(patch Patch, text string) Patch { + if len(text) == 0 { + return patch + } + + pattern := text[patch.Start2 : patch.Start2+patch.Length1] + padding := 0 + + // Look for the first and last matches of pattern in text. If two different matches are found, increase the pattern length. + for strings.Index(text, pattern) != strings.LastIndex(text, pattern) && + len(pattern) < dmp.MatchMaxBits-2*dmp.PatchMargin { + padding += dmp.PatchMargin + maxStart := max(0, patch.Start2-padding) + minEnd := min(len(text), patch.Start2+patch.Length1+padding) + pattern = text[maxStart:minEnd] + } + // Add one chunk for good luck. + padding += dmp.PatchMargin + + // Add the prefix. + prefix := text[max(0, patch.Start2-padding):patch.Start2] + if len(prefix) != 0 { + patch.diffs = append([]Diff{Diff{DiffEqual, prefix}}, patch.diffs...) + } + // Add the suffix. + suffix := text[patch.Start2+patch.Length1 : min(len(text), patch.Start2+patch.Length1+padding)] + if len(suffix) != 0 { + patch.diffs = append(patch.diffs, Diff{DiffEqual, suffix}) + } + + // Roll back the start points. + patch.Start1 -= len(prefix) + patch.Start2 -= len(prefix) + // Extend the lengths. + patch.Length1 += len(prefix) + len(suffix) + patch.Length2 += len(prefix) + len(suffix) + + return patch +} + +// PatchMake computes a list of patches. +func (dmp *DiffMatchPatch) PatchMake(opt ...interface{}) []Patch { + if len(opt) == 1 { + diffs, _ := opt[0].([]Diff) + text1 := dmp.DiffText1(diffs) + return dmp.PatchMake(text1, diffs) + } else if len(opt) == 2 { + text1 := opt[0].(string) + switch t := opt[1].(type) { + case string: + diffs := dmp.DiffMain(text1, t, true) + if len(diffs) > 2 { + diffs = dmp.DiffCleanupSemantic(diffs) + diffs = dmp.DiffCleanupEfficiency(diffs) + } + return dmp.PatchMake(text1, diffs) + case []Diff: + return dmp.patchMake2(text1, t) + } + } else if len(opt) == 3 { + return dmp.PatchMake(opt[0], opt[2]) + } + return []Patch{} +} + +// patchMake2 computes a list of patches to turn text1 into text2. +// text2 is not provided, diffs are the delta between text1 and text2. +func (dmp *DiffMatchPatch) patchMake2(text1 string, diffs []Diff) []Patch { + // Check for null inputs not needed since null can't be passed in C#. + patches := []Patch{} + if len(diffs) == 0 { + return patches // Get rid of the null case. + } + + patch := Patch{} + charCount1 := 0 // Number of characters into the text1 string. + charCount2 := 0 // Number of characters into the text2 string. + // Start with text1 (prepatchText) and apply the diffs until we arrive at text2 (postpatchText). We recreate the patches one by one to determine context info. + prepatchText := text1 + postpatchText := text1 + + for i, aDiff := range diffs { + if len(patch.diffs) == 0 && aDiff.Type != DiffEqual { + // A new patch starts here. + patch.Start1 = charCount1 + patch.Start2 = charCount2 + } + + switch aDiff.Type { + case DiffInsert: + patch.diffs = append(patch.diffs, aDiff) + patch.Length2 += len(aDiff.Text) + postpatchText = postpatchText[:charCount2] + + aDiff.Text + postpatchText[charCount2:] + case DiffDelete: + patch.Length1 += len(aDiff.Text) + patch.diffs = append(patch.diffs, aDiff) + postpatchText = postpatchText[:charCount2] + postpatchText[charCount2+len(aDiff.Text):] + case DiffEqual: + if len(aDiff.Text) <= 2*dmp.PatchMargin && + len(patch.diffs) != 0 && i != len(diffs)-1 { + // Small equality inside a patch. + patch.diffs = append(patch.diffs, aDiff) + patch.Length1 += len(aDiff.Text) + patch.Length2 += len(aDiff.Text) + } + if len(aDiff.Text) >= 2*dmp.PatchMargin { + // Time for a new patch. + if len(patch.diffs) != 0 { + patch = dmp.PatchAddContext(patch, prepatchText) + patches = append(patches, patch) + patch = Patch{} + // Unlike Unidiff, our patch lists have a rolling context. http://code.google.com/p/google-diff-match-patch/wiki/Unidiff Update prepatch text & pos to reflect the application of the just completed patch. + prepatchText = postpatchText + charCount1 = charCount2 + } + } + } + + // Update the current character count. + if aDiff.Type != DiffInsert { + charCount1 += len(aDiff.Text) + } + if aDiff.Type != DiffDelete { + charCount2 += len(aDiff.Text) + } + } + + // Pick up the leftover patch if not empty. + if len(patch.diffs) != 0 { + patch = dmp.PatchAddContext(patch, prepatchText) + patches = append(patches, patch) + } + + return patches +} + +// PatchDeepCopy returns an array that is identical to a given an array of patches. +func (dmp *DiffMatchPatch) PatchDeepCopy(patches []Patch) []Patch { + patchesCopy := []Patch{} + for _, aPatch := range patches { + patchCopy := Patch{} + for _, aDiff := range aPatch.diffs { + patchCopy.diffs = append(patchCopy.diffs, Diff{ + aDiff.Type, + aDiff.Text, + }) + } + patchCopy.Start1 = aPatch.Start1 + patchCopy.Start2 = aPatch.Start2 + patchCopy.Length1 = aPatch.Length1 + patchCopy.Length2 = aPatch.Length2 + patchesCopy = append(patchesCopy, patchCopy) + } + return patchesCopy +} + +// PatchApply merges a set of patches onto the text. Returns a patched text, as well as an array of true/false values indicating which patches were applied. +func (dmp *DiffMatchPatch) PatchApply(patches []Patch, text string) (string, []bool) { + if len(patches) == 0 { + return text, []bool{} + } + + // Deep copy the patches so that no changes are made to originals. + patches = dmp.PatchDeepCopy(patches) + + nullPadding := dmp.PatchAddPadding(patches) + text = nullPadding + text + nullPadding + patches = dmp.PatchSplitMax(patches) + + x := 0 + // delta keeps track of the offset between the expected and actual location of the previous patch. If there are patches expected at positions 10 and 20, but the first patch was found at 12, delta is 2 and the second patch has an effective expected position of 22. + delta := 0 + results := make([]bool, len(patches)) + for _, aPatch := range patches { + expectedLoc := aPatch.Start2 + delta + text1 := dmp.DiffText1(aPatch.diffs) + var startLoc int + endLoc := -1 + if len(text1) > dmp.MatchMaxBits { + // PatchSplitMax will only provide an oversized pattern in the case of a monster delete. + startLoc = dmp.MatchMain(text, text1[:dmp.MatchMaxBits], expectedLoc) + if startLoc != -1 { + endLoc = dmp.MatchMain(text, + text1[len(text1)-dmp.MatchMaxBits:], expectedLoc+len(text1)-dmp.MatchMaxBits) + if endLoc == -1 || startLoc >= endLoc { + // Can't find valid trailing context. Drop this patch. + startLoc = -1 + } + } + } else { + startLoc = dmp.MatchMain(text, text1, expectedLoc) + } + if startLoc == -1 { + // No match found. :( + results[x] = false + // Subtract the delta for this failed patch from subsequent patches. + delta -= aPatch.Length2 - aPatch.Length1 + } else { + // Found a match. :) + results[x] = true + delta = startLoc - expectedLoc + var text2 string + if endLoc == -1 { + text2 = text[startLoc:int(math.Min(float64(startLoc+len(text1)), float64(len(text))))] + } else { + text2 = text[startLoc:int(math.Min(float64(endLoc+dmp.MatchMaxBits), float64(len(text))))] + } + if text1 == text2 { + // Perfect match, just shove the Replacement text in. + text = text[:startLoc] + dmp.DiffText2(aPatch.diffs) + text[startLoc+len(text1):] + } else { + // Imperfect match. Run a diff to get a framework of equivalent indices. + diffs := dmp.DiffMain(text1, text2, false) + if len(text1) > dmp.MatchMaxBits && float64(dmp.DiffLevenshtein(diffs))/float64(len(text1)) > dmp.PatchDeleteThreshold { + // The end points match, but the content is unacceptably bad. + results[x] = false + } else { + diffs = dmp.DiffCleanupSemanticLossless(diffs) + index1 := 0 + for _, aDiff := range aPatch.diffs { + if aDiff.Type != DiffEqual { + index2 := dmp.DiffXIndex(diffs, index1) + if aDiff.Type == DiffInsert { + // Insertion + text = text[:startLoc+index2] + aDiff.Text + text[startLoc+index2:] + } else if aDiff.Type == DiffDelete { + // Deletion + startIndex := startLoc + index2 + text = text[:startIndex] + + text[startIndex+dmp.DiffXIndex(diffs, index1+len(aDiff.Text))-index2:] + } + } + if aDiff.Type != DiffDelete { + index1 += len(aDiff.Text) + } + } + } + } + } + x++ + } + // Strip the padding off. + text = text[len(nullPadding) : len(nullPadding)+(len(text)-2*len(nullPadding))] + return text, results +} + +// PatchAddPadding adds some padding on text start and end so that edges can match something. +// Intended to be called only from within patchApply. +func (dmp *DiffMatchPatch) PatchAddPadding(patches []Patch) string { + paddingLength := dmp.PatchMargin + nullPadding := "" + for x := 1; x <= paddingLength; x++ { + nullPadding += string(x) + } + + // Bump all the patches forward. + for i := range patches { + patches[i].Start1 += paddingLength + patches[i].Start2 += paddingLength + } + + // Add some padding on start of first diff. + if len(patches[0].diffs) == 0 || patches[0].diffs[0].Type != DiffEqual { + // Add nullPadding equality. + patches[0].diffs = append([]Diff{Diff{DiffEqual, nullPadding}}, patches[0].diffs...) + patches[0].Start1 -= paddingLength // Should be 0. + patches[0].Start2 -= paddingLength // Should be 0. + patches[0].Length1 += paddingLength + patches[0].Length2 += paddingLength + } else if paddingLength > len(patches[0].diffs[0].Text) { + // Grow first equality. + extraLength := paddingLength - len(patches[0].diffs[0].Text) + patches[0].diffs[0].Text = nullPadding[len(patches[0].diffs[0].Text):] + patches[0].diffs[0].Text + patches[0].Start1 -= extraLength + patches[0].Start2 -= extraLength + patches[0].Length1 += extraLength + patches[0].Length2 += extraLength + } + + // Add some padding on end of last diff. + last := len(patches) - 1 + if len(patches[last].diffs) == 0 || patches[last].diffs[len(patches[last].diffs)-1].Type != DiffEqual { + // Add nullPadding equality. + patches[last].diffs = append(patches[last].diffs, Diff{DiffEqual, nullPadding}) + patches[last].Length1 += paddingLength + patches[last].Length2 += paddingLength + } else if paddingLength > len(patches[last].diffs[len(patches[last].diffs)-1].Text) { + // Grow last equality. + lastDiff := patches[last].diffs[len(patches[last].diffs)-1] + extraLength := paddingLength - len(lastDiff.Text) + patches[last].diffs[len(patches[last].diffs)-1].Text += nullPadding[:extraLength] + patches[last].Length1 += extraLength + patches[last].Length2 += extraLength + } + + return nullPadding +} + +// PatchSplitMax looks through the patches and breaks up any which are longer than the maximum limit of the match algorithm. +// Intended to be called only from within patchApply. +func (dmp *DiffMatchPatch) PatchSplitMax(patches []Patch) []Patch { + patchSize := dmp.MatchMaxBits + for x := 0; x < len(patches); x++ { + if patches[x].Length1 <= patchSize { + continue + } + bigpatch := patches[x] + // Remove the big old patch. + patches = append(patches[:x], patches[x+1:]...) + x-- + + Start1 := bigpatch.Start1 + Start2 := bigpatch.Start2 + precontext := "" + for len(bigpatch.diffs) != 0 { + // Create one of several smaller patches. + patch := Patch{} + empty := true + patch.Start1 = Start1 - len(precontext) + patch.Start2 = Start2 - len(precontext) + if len(precontext) != 0 { + patch.Length1 = len(precontext) + patch.Length2 = len(precontext) + patch.diffs = append(patch.diffs, Diff{DiffEqual, precontext}) + } + for len(bigpatch.diffs) != 0 && patch.Length1 < patchSize-dmp.PatchMargin { + diffType := bigpatch.diffs[0].Type + diffText := bigpatch.diffs[0].Text + if diffType == DiffInsert { + // Insertions are harmless. + patch.Length2 += len(diffText) + Start2 += len(diffText) + patch.diffs = append(patch.diffs, bigpatch.diffs[0]) + bigpatch.diffs = bigpatch.diffs[1:] + empty = false + } else if diffType == DiffDelete && len(patch.diffs) == 1 && patch.diffs[0].Type == DiffEqual && len(diffText) > 2*patchSize { + // This is a large deletion. Let it pass in one chunk. + patch.Length1 += len(diffText) + Start1 += len(diffText) + empty = false + patch.diffs = append(patch.diffs, Diff{diffType, diffText}) + bigpatch.diffs = bigpatch.diffs[1:] + } else { + // Deletion or equality. Only take as much as we can stomach. + diffText = diffText[:min(len(diffText), patchSize-patch.Length1-dmp.PatchMargin)] + + patch.Length1 += len(diffText) + Start1 += len(diffText) + if diffType == DiffEqual { + patch.Length2 += len(diffText) + Start2 += len(diffText) + } else { + empty = false + } + patch.diffs = append(patch.diffs, Diff{diffType, diffText}) + if diffText == bigpatch.diffs[0].Text { + bigpatch.diffs = bigpatch.diffs[1:] + } else { + bigpatch.diffs[0].Text = + bigpatch.diffs[0].Text[len(diffText):] + } + } + } + // Compute the head context for the next patch. + precontext = dmp.DiffText2(patch.diffs) + precontext = precontext[max(0, len(precontext)-dmp.PatchMargin):] + + postcontext := "" + // Append the end context for this patch. + if len(dmp.DiffText1(bigpatch.diffs)) > dmp.PatchMargin { + postcontext = dmp.DiffText1(bigpatch.diffs)[:dmp.PatchMargin] + } else { + postcontext = dmp.DiffText1(bigpatch.diffs) + } + + if len(postcontext) != 0 { + patch.Length1 += len(postcontext) + patch.Length2 += len(postcontext) + if len(patch.diffs) != 0 && patch.diffs[len(patch.diffs)-1].Type == DiffEqual { + patch.diffs[len(patch.diffs)-1].Text += postcontext + } else { + patch.diffs = append(patch.diffs, Diff{DiffEqual, postcontext}) + } + } + if !empty { + x++ + patches = append(patches[:x], append([]Patch{patch}, patches[x:]...)...) + } + } + } + return patches +} + +// PatchToText takes a list of patches and returns a textual representation. +func (dmp *DiffMatchPatch) PatchToText(patches []Patch) string { + var text bytes.Buffer + for _, aPatch := range patches { + _, _ = text.WriteString(aPatch.String()) + } + return text.String() +} + +// PatchFromText parses a textual representation of patches and returns a List of Patch objects. +func (dmp *DiffMatchPatch) PatchFromText(textline string) ([]Patch, error) { + patches := []Patch{} + if len(textline) == 0 { + return patches, nil + } + text := strings.Split(textline, "\n") + textPointer := 0 + patchHeader := regexp.MustCompile("^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$") + + var patch Patch + var sign uint8 + var line string + for textPointer < len(text) { + + if !patchHeader.MatchString(text[textPointer]) { + return patches, errors.New("Invalid patch string: " + text[textPointer]) + } + + patch = Patch{} + m := patchHeader.FindStringSubmatch(text[textPointer]) + + patch.Start1, _ = strconv.Atoi(m[1]) + if len(m[2]) == 0 { + patch.Start1-- + patch.Length1 = 1 + } else if m[2] == "0" { + patch.Length1 = 0 + } else { + patch.Start1-- + patch.Length1, _ = strconv.Atoi(m[2]) + } + + patch.Start2, _ = strconv.Atoi(m[3]) + + if len(m[4]) == 0 { + patch.Start2-- + patch.Length2 = 1 + } else if m[4] == "0" { + patch.Length2 = 0 + } else { + patch.Start2-- + patch.Length2, _ = strconv.Atoi(m[4]) + } + textPointer++ + + for textPointer < len(text) { + if len(text[textPointer]) > 0 { + sign = text[textPointer][0] + } else { + textPointer++ + continue + } + + line = text[textPointer][1:] + line = strings.Replace(line, "+", "%2b", -1) + line, _ = url.QueryUnescape(line) + if sign == '-' { + // Deletion. + patch.diffs = append(patch.diffs, Diff{DiffDelete, line}) + } else if sign == '+' { + // Insertion. + patch.diffs = append(patch.diffs, Diff{DiffInsert, line}) + } else if sign == ' ' { + // Minor equality. + patch.diffs = append(patch.diffs, Diff{DiffEqual, line}) + } else if sign == '@' { + // Start of next patch. + break + } else { + // WTF? + return patches, errors.New("Invalid patch mode '" + string(sign) + "' in: " + string(line)) + } + textPointer++ + } + + patches = append(patches, patch) + } + return patches, nil +} diff --git a/vendor/github.com/sergi/go-diff/diffmatchpatch/stringutil.go b/vendor/github.com/sergi/go-diff/diffmatchpatch/stringutil.go new file mode 100644 index 0000000000..265f29cc7e --- /dev/null +++ b/vendor/github.com/sergi/go-diff/diffmatchpatch/stringutil.go @@ -0,0 +1,88 @@ +// Copyright (c) 2012-2016 The go-diff authors. All rights reserved. +// https://github.com/sergi/go-diff +// See the included LICENSE file for license details. +// +// go-diff is a Go implementation of Google's Diff, Match, and Patch library +// Original library is Copyright (c) 2006 Google Inc. +// http://code.google.com/p/google-diff-match-patch/ + +package diffmatchpatch + +import ( + "strings" + "unicode/utf8" +) + +// unescaper unescapes selected chars for compatibility with JavaScript's encodeURI. +// In speed critical applications this could be dropped since the receiving application will certainly decode these fine. Note that this function is case-sensitive. Thus "%3F" would not be unescaped. But this is ok because it is only called with the output of HttpUtility.UrlEncode which returns lowercase hex. Example: "%3f" -> "?", "%24" -> "$", etc. +var unescaper = strings.NewReplacer( + "%21", "!", "%7E", "~", "%27", "'", + "%28", "(", "%29", ")", "%3B", ";", + "%2F", "/", "%3F", "?", "%3A", ":", + "%40", "@", "%26", "&", "%3D", "=", + "%2B", "+", "%24", "$", "%2C", ",", "%23", "#", "%2A", "*") + +// indexOf returns the first index of pattern in str, starting at str[i]. +func indexOf(str string, pattern string, i int) int { + if i > len(str)-1 { + return -1 + } + if i <= 0 { + return strings.Index(str, pattern) + } + ind := strings.Index(str[i:], pattern) + if ind == -1 { + return -1 + } + return ind + i +} + +// lastIndexOf returns the last index of pattern in str, starting at str[i]. +func lastIndexOf(str string, pattern string, i int) int { + if i < 0 { + return -1 + } + if i >= len(str) { + return strings.LastIndex(str, pattern) + } + _, size := utf8.DecodeRuneInString(str[i:]) + return strings.LastIndex(str[:i+size], pattern) +} + +// runesIndexOf returns the index of pattern in target, starting at target[i]. +func runesIndexOf(target, pattern []rune, i int) int { + if i > len(target)-1 { + return -1 + } + if i <= 0 { + return runesIndex(target, pattern) + } + ind := runesIndex(target[i:], pattern) + if ind == -1 { + return -1 + } + return ind + i +} + +func runesEqual(r1, r2 []rune) bool { + if len(r1) != len(r2) { + return false + } + for i, c := range r1 { + if c != r2[i] { + return false + } + } + return true +} + +// runesIndex is the equivalent of strings.Index for rune slices. +func runesIndex(r1, r2 []rune) int { + last := len(r1) - len(r2) + for i := 0; i <= last; i++ { + if runesEqual(r1[i:i+len(r2)], r2) { + return i + } + } + return -1 +} diff --git a/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml b/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml new file mode 100644 index 0000000000..f51cf6aea4 --- /dev/null +++ b/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml @@ -0,0 +1,16 @@ +sudo: false +language: go +go: + - 1.7 + - tip +matrix: + allow_failures: + - go: tip + fast_finish: true +install: + - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d -s .) + - go tool vet . + - go test -v -race ./... diff --git a/vendor/github.com/shurcooL/sanitized_anchor_name/README.md b/vendor/github.com/shurcooL/sanitized_anchor_name/README.md new file mode 100644 index 0000000000..8c714bcfa9 --- /dev/null +++ b/vendor/github.com/shurcooL/sanitized_anchor_name/README.md @@ -0,0 +1,34 @@ +sanitized_anchor_name +===================== + +[![Build Status](https://travis-ci.org/shurcooL/sanitized_anchor_name.svg?branch=master)](https://travis-ci.org/shurcooL/sanitized_anchor_name) [![GoDoc](https://godoc.org/github.com/shurcooL/sanitized_anchor_name?status.svg)](https://godoc.org/github.com/shurcooL/sanitized_anchor_name) + +Package sanitized_anchor_name provides a func to create sanitized anchor names. + +Its logic can be reused by multiple packages to create interoperable anchor names and links to those anchors. + +At this time, it does not try to ensure that generated anchor names are unique, that responsibility falls on the caller. + +Installation +------------ + +```bash +go get -u github.com/shurcooL/sanitized_anchor_name +``` + +Example +------- + +```Go +anchorName := sanitized_anchor_name.Create("This is a header") + +fmt.Println(anchorName) + +// Output: +// this-is-a-header +``` + +License +------- + +- [MIT License](LICENSE) diff --git a/vendor/github.com/src-d/gcfg/README b/vendor/github.com/src-d/gcfg/README new file mode 100644 index 0000000000..1ff233a529 --- /dev/null +++ b/vendor/github.com/src-d/gcfg/README @@ -0,0 +1,4 @@ +Gcfg reads INI-style configuration files into Go structs; +supports user-defined types and subsections. + +Package docs: https://godoc.org/gopkg.in/gcfg.v1 diff --git a/vendor/github.com/steveyen/gtreap/.gitignore b/vendor/github.com/steveyen/gtreap/.gitignore new file mode 100644 index 0000000000..94b2ac31be --- /dev/null +++ b/vendor/github.com/steveyen/gtreap/.gitignore @@ -0,0 +1,5 @@ +#* +*~ +*.test +tmp + diff --git a/vendor/github.com/steveyen/gtreap/README.md b/vendor/github.com/steveyen/gtreap/README.md new file mode 100644 index 0000000000..4cd8de7c75 --- /dev/null +++ b/vendor/github.com/steveyen/gtreap/README.md @@ -0,0 +1,90 @@ +gtreap +------ + +gtreap is an immutable treap implementation in the Go Language + +[![GoDoc](https://godoc.org/github.com/steveyen/gtreap?status.svg)](https://godoc.org/github.com/steveyen/gtreap) [![Build Status](https://drone.io/github.com/steveyen/gtreap/status.png)](https://drone.io/github.com/steveyen/gtreap/latest) [![Coverage Status](https://coveralls.io/repos/steveyen/gtreap/badge.png)](https://coveralls.io/r/steveyen/gtreap) + +Overview +======== + +gtreap implements an immutable treap data structure in golang. + +By treap, this data structure is both a heap and a binary search tree. + +By immutable, any updates/deletes to a treap will return a new treap +which can share internal nodes with the previous treap. All nodes in +this implementation are read-only after their creation. This allows +concurrent readers to operate safely with concurrent writers as +modifications only create new data structures and never modify +existing data structures. This is a simple approach to achieving MVCC +or multi-version concurrency control. + +By heap, items in the treap follow the heap-priority property, where a +parent node will have higher priority than its left and right children +nodes. + +By binary search tree, items are store lexigraphically, ordered by a +user-supplied Compare function. + +To get a probabilistic O(lg N) tree height, you should use a random +priority number during the Upsert() operation. + +LICENSE +======= + +MIT + +Example +======= + + import ( + "math/rand" + "github.com/steveyen/gtreap" + ) + + func stringCompare(a, b interface{}) int { + return bytes.Compare([]byte(a.(string)), []byte(b.(string))) + } + + t := gtreap.NewTreap(stringCompare) + t = t.Upsert("hi", rand.Int()) + t = t.Upsert("hola", rand.Int()) + t = t.Upsert("bye", rand.Int()) + t = t.Upsert("adios", rand.Int()) + + hi = t.Get("hi") + bye = t.Get("bye") + + // Some example Delete()'s... + t = t.Delete("bye") + nilValueHere = t.Get("bye") + t2 = t.Delete("hi") + nilValueHere2 = t2.Get("hi") + + // Since we still hold onto treap t, we can still access "hi". + hiStillExistsInTreapT = t.Get("hi") + + t.VisitAscend("cya", func(i Item) bool { + // This visitor callback will be invoked with every item + // from "cya" onwards. So: "hi", "hola". + // If we want to stop visiting, return false; + // otherwise a true return result means keep visiting items. + return true + }) + +Tips +==== + +The Upsert() method takes both an Item (an interface{}) and a heap +priority. Usually, that priority should be a random int +(math/rand.Int()) or perhaps even a hash of the item. However, if you +want to shuffle more commonly accessed items nearer to the top of the +treap for faster access, at the potential cost of not approaching a +probabilistic O(lg N) tree height, then you might tweak the priority. + +See also +======== + +For a simple, ordered, key-value storage or persistence library built +on immutable treaps, see: https://github.com/steveyen/gkvlite diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go index ae06a54e20..aa1c2b95cd 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -13,6 +13,9 @@ import ( // Conditionf uses a Comparison to assert a complex condition. func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Condition(t, comp, append([]interface{}{msg}, args...)...) } @@ -23,11 +26,17 @@ func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bo // assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") // assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Contains(t, s, contains, append([]interface{}{msg}, args...)...) } // DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return DirExists(t, path, append([]interface{}{msg}, args...)...) } @@ -37,6 +46,9 @@ func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { // // assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) } @@ -45,6 +57,9 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string // // assert.Emptyf(t, obj, "error message %s", "formatted") func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Empty(t, object, append([]interface{}{msg}, args...)...) } @@ -56,6 +71,9 @@ func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) boo // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Equal(t, expected, actual, append([]interface{}{msg}, args...)...) } @@ -65,6 +83,9 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar // actualObj, err := SomeFunction() // assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) } @@ -73,6 +94,9 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args // // assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123)) func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) } @@ -83,6 +107,9 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri // assert.Equal(t, expectedErrorf, err) // } func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Error(t, err, append([]interface{}{msg}, args...)...) } @@ -90,16 +117,25 @@ func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { // // assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123)) func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...) } // Failf reports a failure through func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Fail(t, failureMessage, append([]interface{}{msg}, args...)...) } // FailNowf fails test func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...) } @@ -107,31 +143,43 @@ func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{} // // assert.Falsef(t, myBool, "error message %s", "formatted") func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return False(t, value, append([]interface{}{msg}, args...)...) } // FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return FileExists(t, path, append([]interface{}{msg}, args...)...) } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // -// assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // -// assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) } @@ -141,6 +189,9 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } @@ -150,6 +201,9 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } @@ -159,6 +213,9 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } @@ -166,6 +223,9 @@ func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url strin // // assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) } @@ -173,31 +233,49 @@ func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, ms // // assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // InDeltaSlicef is the same as InDelta, except it compares two slices. func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // InEpsilonf asserts that expected and actual have a relative error less than epsilon func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) } // IsTypef asserts that the specified objects are of the same type. func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...) } @@ -205,6 +283,9 @@ func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg strin // // assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) } @@ -213,6 +294,9 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int // // assert.Lenf(t, mySlice, 3, "error message %s", "formatted") func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Len(t, object, length, append([]interface{}{msg}, args...)...) } @@ -220,6 +304,9 @@ func Lenf(t TestingT, object interface{}, length int, msg string, args ...interf // // assert.Nilf(t, err, "error message %s", "formatted") func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Nil(t, object, append([]interface{}{msg}, args...)...) } @@ -230,6 +317,9 @@ func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool // assert.Equal(t, expectedObj, actualObj) // } func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NoError(t, err, append([]interface{}{msg}, args...)...) } @@ -240,6 +330,9 @@ func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { // assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") // assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotContains(t, s, contains, append([]interface{}{msg}, args...)...) } @@ -250,6 +343,9 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a // assert.Equal(t, "two", obj[1]) // } func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotEmpty(t, object, append([]interface{}{msg}, args...)...) } @@ -260,6 +356,9 @@ func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...) } @@ -267,6 +366,9 @@ func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, // // assert.NotNilf(t, err, "error message %s", "formatted") func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotNil(t, object, append([]interface{}{msg}, args...)...) } @@ -274,6 +376,9 @@ func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bo // // assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotPanics(t, f, append([]interface{}{msg}, args...)...) } @@ -282,6 +387,9 @@ func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bo // assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") // assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...) } @@ -290,11 +398,17 @@ func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args .. // // assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...) } // NotZerof asserts that i is not the zero value for its type. func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return NotZero(t, i, append([]interface{}{msg}, args...)...) } @@ -302,6 +416,9 @@ func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { // // assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Panics(t, f, append([]interface{}{msg}, args...)...) } @@ -310,6 +427,9 @@ func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool // // assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) } @@ -318,6 +438,9 @@ func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg str // assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") // assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Regexp(t, rx, str, append([]interface{}{msg}, args...)...) } @@ -326,6 +449,9 @@ func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...in // // assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Subset(t, list, subset, append([]interface{}{msg}, args...)...) } @@ -333,6 +459,9 @@ func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args // // assert.Truef(t, myBool, "error message %s", "formatted") func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return True(t, value, append([]interface{}{msg}, args...)...) } @@ -340,10 +469,16 @@ func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { // // assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // Zerof asserts that i is the zero value for its type. func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } return Zero(t, i, append([]interface{}{msg}, args...)...) } diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl new file mode 100644 index 0000000000..d2bb0b8177 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl @@ -0,0 +1,5 @@ +{{.CommentFormat}} +func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool { + if h, ok := t.(tHelper); ok { h.Helper() } + return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}}) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go index ffa5428f34..de39f794e7 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -13,11 +13,17 @@ import ( // Condition uses a Comparison to assert a complex condition. func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Condition(a.t, comp, msgAndArgs...) } // Conditionf uses a Comparison to assert a complex condition. func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Conditionf(a.t, comp, msg, args...) } @@ -28,6 +34,9 @@ func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{} // a.Contains(["Hello", "World"], "World") // a.Contains({"Hello": "World"}, "Hello") func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Contains(a.t, s, contains, msgAndArgs...) } @@ -38,16 +47,25 @@ func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs .. // a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") // a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Containsf(a.t, s, contains, msg, args...) } // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return DirExists(a.t, path, msgAndArgs...) } // DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return DirExistsf(a.t, path, msg, args...) } @@ -57,6 +75,9 @@ func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bo // // a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return ElementsMatch(a.t, listA, listB, msgAndArgs...) } @@ -66,6 +87,9 @@ func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndA // // a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return ElementsMatchf(a.t, listA, listB, msg, args...) } @@ -74,6 +98,9 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st // // a.Empty(obj) func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Empty(a.t, object, msgAndArgs...) } @@ -82,6 +109,9 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { // // a.Emptyf(obj, "error message %s", "formatted") func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Emptyf(a.t, object, msg, args...) } @@ -93,6 +123,9 @@ func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Equal(a.t, expected, actual, msgAndArgs...) } @@ -102,6 +135,9 @@ func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs // actualObj, err := SomeFunction() // a.EqualError(err, expectedErrorString) func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return EqualError(a.t, theError, errString, msgAndArgs...) } @@ -111,6 +147,9 @@ func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ... // actualObj, err := SomeFunction() // a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return EqualErrorf(a.t, theError, errString, msg, args...) } @@ -119,6 +158,9 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a // // a.EqualValues(uint32(123), int32(123)) func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return EqualValues(a.t, expected, actual, msgAndArgs...) } @@ -127,6 +169,9 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn // // a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123)) func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return EqualValuesf(a.t, expected, actual, msg, args...) } @@ -138,6 +183,9 @@ func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Equalf(a.t, expected, actual, msg, args...) } @@ -148,6 +196,9 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string // assert.Equal(t, expectedError, err) // } func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Error(a.t, err, msgAndArgs...) } @@ -158,6 +209,9 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { // assert.Equal(t, expectedErrorf, err) // } func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Errorf(a.t, err, msg, args...) } @@ -165,6 +219,9 @@ func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { // // a.Exactly(int32(123), int64(123)) func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Exactly(a.t, expected, actual, msgAndArgs...) } @@ -172,26 +229,41 @@ func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArg // // a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123)) func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Exactlyf(a.t, expected, actual, msg, args...) } // Fail reports a failure through func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Fail(a.t, failureMessage, msgAndArgs...) } // FailNow fails test func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return FailNow(a.t, failureMessage, msgAndArgs...) } // FailNowf fails test func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return FailNowf(a.t, failureMessage, msg, args...) } // Failf reports a failure through func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Failf(a.t, failureMessage, msg, args...) } @@ -199,6 +271,9 @@ func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{ // // a.False(myBool) func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return False(a.t, value, msgAndArgs...) } @@ -206,56 +281,77 @@ func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { // // a.Falsef(myBool, "error message %s", "formatted") func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Falsef(a.t, value, msg, args...) } // FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return FileExists(a.t, path, msgAndArgs...) } // FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return FileExistsf(a.t, path, msg, args...) } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // -// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // -// a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // -// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // -// a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) } @@ -265,6 +361,9 @@ func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method strin // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPError(a.t, handler, method, url, values, msgAndArgs...) } @@ -274,6 +373,9 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPErrorf(a.t, handler, method, url, values, msg, args...) } @@ -283,6 +385,9 @@ func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url str // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) } @@ -292,6 +397,9 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPRedirectf(a.t, handler, method, url, values, msg, args...) } @@ -301,6 +409,9 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) } @@ -310,6 +421,9 @@ func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url st // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return HTTPSuccessf(a.t, handler, method, url, values, msg, args...) } @@ -317,6 +431,9 @@ func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url s // // a.Implements((*MyInterface)(nil), new(MyObject)) func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Implements(a.t, interfaceObject, object, msgAndArgs...) } @@ -324,6 +441,9 @@ func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, // // a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Implementsf(a.t, interfaceObject, object, msg, args...) } @@ -331,26 +451,41 @@ func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{} // // a.InDelta(math.Pi, (22 / 7.0), 0.01) func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InDelta(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) } // InDeltaSlice is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaSlicef is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InDeltaSlicef(a.t, expected, actual, delta, msg, args...) } @@ -358,36 +493,57 @@ func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, del // // a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InDeltaf(a.t, expected, actual, delta, msg, args...) } // InEpsilon asserts that expected and actual have a relative error less than epsilon func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) } // InEpsilonf asserts that expected and actual have a relative error less than epsilon func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) } // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return IsType(a.t, expectedType, object, msgAndArgs...) } // IsTypef asserts that the specified objects are of the same type. func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return IsTypef(a.t, expectedType, object, msg, args...) } @@ -395,6 +551,9 @@ func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg s // // a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return JSONEq(a.t, expected, actual, msgAndArgs...) } @@ -402,6 +561,9 @@ func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interf // // a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return JSONEqf(a.t, expected, actual, msg, args...) } @@ -410,6 +572,9 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args .. // // a.Len(mySlice, 3) func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Len(a.t, object, length, msgAndArgs...) } @@ -418,6 +583,9 @@ func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface // // a.Lenf(mySlice, 3, "error message %s", "formatted") func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Lenf(a.t, object, length, msg, args...) } @@ -425,6 +593,9 @@ func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...in // // a.Nil(err) func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Nil(a.t, object, msgAndArgs...) } @@ -432,6 +603,9 @@ func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { // // a.Nilf(err, "error message %s", "formatted") func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Nilf(a.t, object, msg, args...) } @@ -442,6 +616,9 @@ func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) b // assert.Equal(t, expectedObj, actualObj) // } func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NoError(a.t, err, msgAndArgs...) } @@ -452,6 +629,9 @@ func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { // assert.Equal(t, expectedObj, actualObj) // } func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NoErrorf(a.t, err, msg, args...) } @@ -462,6 +642,9 @@ func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { // a.NotContains(["Hello", "World"], "Earth") // a.NotContains({"Hello": "World"}, "Earth") func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotContains(a.t, s, contains, msgAndArgs...) } @@ -472,6 +655,9 @@ func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs // a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") // a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotContainsf(a.t, s, contains, msg, args...) } @@ -482,6 +668,9 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin // assert.Equal(t, "two", obj[1]) // } func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotEmpty(a.t, object, msgAndArgs...) } @@ -492,6 +681,9 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) boo // assert.Equal(t, "two", obj[1]) // } func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotEmptyf(a.t, object, msg, args...) } @@ -502,6 +694,9 @@ func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotEqual(a.t, expected, actual, msgAndArgs...) } @@ -512,6 +707,9 @@ func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndAr // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotEqualf(a.t, expected, actual, msg, args...) } @@ -519,6 +717,9 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str // // a.NotNil(err) func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotNil(a.t, object, msgAndArgs...) } @@ -526,6 +727,9 @@ func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool // // a.NotNilf(err, "error message %s", "formatted") func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotNilf(a.t, object, msg, args...) } @@ -533,6 +737,9 @@ func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{} // // a.NotPanics(func(){ RemainCalm() }) func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotPanics(a.t, f, msgAndArgs...) } @@ -540,6 +747,9 @@ func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool // // a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotPanicsf(a.t, f, msg, args...) } @@ -548,6 +758,9 @@ func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{} // a.NotRegexp(regexp.MustCompile("starts"), "it's starting") // a.NotRegexp("^start", "it's not starting") func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotRegexp(a.t, rx, str, msgAndArgs...) } @@ -556,6 +769,9 @@ func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...in // a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") // a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotRegexpf(a.t, rx, str, msg, args...) } @@ -564,6 +780,9 @@ func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, arg // // a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotSubset(a.t, list, subset, msgAndArgs...) } @@ -572,16 +791,25 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs // // a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotSubsetf(a.t, list, subset, msg, args...) } // NotZero asserts that i is not the zero value for its type. func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotZero(a.t, i, msgAndArgs...) } // NotZerof asserts that i is not the zero value for its type. func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return NotZerof(a.t, i, msg, args...) } @@ -589,6 +817,9 @@ func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bo // // a.Panics(func(){ GoCrazy() }) func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Panics(a.t, f, msgAndArgs...) } @@ -597,6 +828,9 @@ func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { // // a.PanicsWithValue("crazy error", func(){ GoCrazy() }) func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return PanicsWithValue(a.t, expected, f, msgAndArgs...) } @@ -605,6 +839,9 @@ func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgA // // a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return PanicsWithValuef(a.t, expected, f, msg, args...) } @@ -612,6 +849,9 @@ func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg // // a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Panicsf(a.t, f, msg, args...) } @@ -620,6 +860,9 @@ func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) b // a.Regexp(regexp.MustCompile("start"), "it's starting") // a.Regexp("start...$", "it's not starting") func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Regexp(a.t, rx, str, msgAndArgs...) } @@ -628,6 +871,9 @@ func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...inter // a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") // a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Regexpf(a.t, rx, str, msg, args...) } @@ -636,6 +882,9 @@ func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args . // // a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Subset(a.t, list, subset, msgAndArgs...) } @@ -644,6 +893,9 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... // // a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Subsetf(a.t, list, subset, msg, args...) } @@ -651,6 +903,9 @@ func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, a // // a.True(myBool) func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return True(a.t, value, msgAndArgs...) } @@ -658,6 +913,9 @@ func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { // // a.Truef(myBool, "error message %s", "formatted") func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Truef(a.t, value, msg, args...) } @@ -665,6 +923,9 @@ func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { // // a.WithinDuration(time.Now(), time.Now(), 10*time.Second) func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) } @@ -672,15 +933,24 @@ func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta // // a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return WithinDurationf(a.t, expected, actual, delta, msg, args...) } // Zero asserts that i is the zero value for its type. func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Zero(a.t, i, msgAndArgs...) } // Zerof asserts that i is the zero value for its type. func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } return Zerof(a.t, i, msg, args...) } diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl new file mode 100644 index 0000000000..188bb9e174 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl @@ -0,0 +1,5 @@ +{{.CommentWithoutT "a"}} +func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { + if h, ok := a.t.(tHelper); ok { h.Helper() } + return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index 47bda77866..5bdec56cd8 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -27,6 +27,22 @@ type TestingT interface { Errorf(format string, args ...interface{}) } +// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful +// for table driven tests. +type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool + +// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful +// for table driven tests. +type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool + +// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful +// for table driven tests. +type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool + +// ValuesAssertionFunc is a common function prototype when validating an error value. Can be useful +// for table driven tests. +type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool + // Comparison a custom function that returns true on success and false on failure type Comparison func() (success bool) @@ -38,21 +54,23 @@ type Comparison func() (success bool) // // This function does no assertion of any kind. func ObjectsAreEqual(expected, actual interface{}) bool { - if expected == nil || actual == nil { return expected == actual } - if exp, ok := expected.([]byte); ok { - act, ok := actual.([]byte) - if !ok { - return false - } else if exp == nil || act == nil { - return exp == nil && act == nil - } - return bytes.Equal(exp, act) - } - return reflect.DeepEqual(expected, actual) + exp, ok := expected.([]byte) + if !ok { + return reflect.DeepEqual(expected, actual) + } + + act, ok := actual.([]byte) + if !ok { + return false + } + if exp == nil || act == nil { + return exp == nil && act == nil + } + return bytes.Equal(exp, act) } // ObjectsAreEqualValues gets whether two objects are equal, or if their @@ -156,21 +174,6 @@ func isTest(name, prefix string) bool { return !unicode.IsLower(rune) } -// getWhitespaceString returns a string that is long enough to overwrite the default -// output from the go testing framework. -func getWhitespaceString() string { - - _, file, line, ok := runtime.Caller(1) - if !ok { - return "" - } - parts := strings.Split(file, "/") - file = parts[len(parts)-1] - - return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line))) - -} - func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { if len(msgAndArgs) == 0 || msgAndArgs == nil { return "" @@ -195,7 +198,7 @@ func indentMessageLines(message string, longestLabelLen int) string { // no need to align first line because it starts at the correct location (after the label) if i != 0 { // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab - outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") + outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") } outBuf.WriteString(scanner.Text()) } @@ -209,6 +212,9 @@ type failNower interface { // FailNow fails test func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } Fail(t, failureMessage, msgAndArgs...) // We cannot extend TestingT with FailNow() and @@ -227,8 +233,11 @@ func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool // Fail reports a failure through func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } content := []labeledContent{ - {"Error Trace", strings.Join(CallerInfo(), "\n\r\t\t\t")}, + {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")}, {"Error", failureMessage}, } @@ -244,7 +253,7 @@ func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { content = append(content, labeledContent{"Messages", message}) } - t.Errorf("%s", "\r"+getWhitespaceString()+labeledOutput(content...)) + t.Errorf("\n%s", ""+labeledOutput(content...)) return false } @@ -256,7 +265,7 @@ type labeledContent struct { // labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: // -// \r\t{{label}}:{{align_spaces}}\t{{content}}\n +// \t{{label}}:{{align_spaces}}\t{{content}}\n // // The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. // If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this @@ -272,7 +281,7 @@ func labeledOutput(content ...labeledContent) string { } var output string for _, v := range content { - output += "\r\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" + output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" } return output } @@ -281,6 +290,9 @@ func labeledOutput(content ...labeledContent) string { // // assert.Implements(t, (*MyInterface)(nil), new(MyObject)) func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } interfaceType := reflect.TypeOf(interfaceObject).Elem() if object == nil { @@ -295,6 +307,9 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) @@ -311,6 +326,9 @@ func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if err := validateEqualArgs(expected, actual); err != nil { return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", expected, actual, err), msgAndArgs...) @@ -349,6 +367,9 @@ func formatUnequalValues(expected, actual interface{}) (e string, a string) { // // assert.EqualValues(t, uint32(123), int32(123)) func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if !ObjectsAreEqualValues(expected, actual) { diff := diff(expected, actual) @@ -366,12 +387,15 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa // // assert.Exactly(t, int32(123), int64(123)) func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } aType := reflect.TypeOf(expected) bType := reflect.TypeOf(actual) if aType != bType { - return Fail(t, fmt.Sprintf("Types expected to match exactly\n\r\t%v != %v", aType, bType), msgAndArgs...) + return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) } return Equal(t, expected, actual, msgAndArgs...) @@ -382,6 +406,9 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{} // // assert.NotNil(t, err) func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if !isNil(object) { return true } @@ -407,6 +434,9 @@ func isNil(object interface{}) bool { // // assert.Nil(t, err) func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if isNil(object) { return true } @@ -446,6 +476,9 @@ func isEmpty(object interface{}) bool { // // assert.Empty(t, obj) func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } pass := isEmpty(object) if !pass { @@ -463,6 +496,9 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { // assert.Equal(t, "two", obj[1]) // } func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } pass := !isEmpty(object) if !pass { @@ -490,6 +526,9 @@ func getLen(x interface{}) (ok bool, length int) { // // assert.Len(t, mySlice, 3) func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } ok, l := getLen(object) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) @@ -505,6 +544,14 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) // // assert.True(t, myBool) func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if h, ok := t.(interface { + Helper() + }); ok { + h.Helper() + } if value != true { return Fail(t, "Should be true", msgAndArgs...) @@ -518,6 +565,9 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { // // assert.False(t, myBool) func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if value != false { return Fail(t, "Should be false", msgAndArgs...) @@ -534,6 +584,9 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if err := validateEqualArgs(expected, actual); err != nil { return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", expected, actual, err), msgAndArgs...) @@ -592,6 +645,9 @@ func includeElement(list interface{}, element interface{}) (ok, found bool) { // assert.Contains(t, ["Hello", "World"], "World") // assert.Contains(t, {"Hello": "World"}, "Hello") func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } ok, found := includeElement(s, contains) if !ok { @@ -612,6 +668,9 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo // assert.NotContains(t, ["Hello", "World"], "Earth") // assert.NotContains(t, {"Hello": "World"}, "Earth") func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } ok, found := includeElement(s, contains) if !ok { @@ -630,6 +689,9 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) // // assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } if subset == nil { return true // we consider nil to be equal to the nil set } @@ -671,6 +733,9 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok // // assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } if subset == nil { return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...) } @@ -713,6 +778,9 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) // // assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } if isEmpty(listA) && isEmpty(listB) { return true } @@ -763,6 +831,9 @@ func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface // Condition uses a Comparison to assert a complex condition. func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } result := comp() if !result { Fail(t, "Condition failed!", msgAndArgs...) @@ -800,9 +871,12 @@ func didPanic(f PanicTestFunc) (bool, interface{}) { // // assert.Panics(t, func(){ GoCrazy() }) func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if funcDidPanic, panicValue := didPanic(f); !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) } return true @@ -813,13 +887,16 @@ func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { // // assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } funcDidPanic, panicValue := didPanic(f) if !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) } if panicValue != expected { - return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%v\n\r\tPanic value:\t%v", f, expected, panicValue), msgAndArgs...) + return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v", f, expected, panicValue), msgAndArgs...) } return true @@ -829,9 +906,12 @@ func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndAr // // assert.NotPanics(t, func(){ RemainCalm() }) func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if funcDidPanic, panicValue := didPanic(f); funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v", f, panicValue), msgAndArgs...) } return true @@ -841,6 +921,9 @@ func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { // // assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } dt := expected.Sub(actual) if dt < -delta || dt > delta { @@ -890,6 +973,9 @@ func toFloat(x interface{}) (float64, bool) { // // assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } af, aok := toFloat(expected) bf, bok := toFloat(actual) @@ -916,6 +1002,9 @@ func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs // InDeltaSlice is the same as InDelta, except it compares two slices. func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { @@ -937,6 +1026,9 @@ func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAn // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Map || reflect.TypeOf(expected).Kind() != reflect.Map { @@ -994,6 +1086,9 @@ func calcRelativeError(expected, actual interface{}) (float64, error) { // InEpsilon asserts that expected and actual have a relative error less than epsilon func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } actualEpsilon, err := calcRelativeError(expected, actual) if err != nil { return Fail(t, err.Error(), msgAndArgs...) @@ -1008,6 +1103,9 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { @@ -1038,6 +1136,9 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m // assert.Equal(t, expectedObj, actualObj) // } func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if err != nil { return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) } @@ -1052,6 +1153,9 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { // assert.Equal(t, expectedError, err) // } func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if err == nil { return Fail(t, "An error is expected but got nil.", msgAndArgs...) @@ -1066,6 +1170,9 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { // actualObj, err := SomeFunction() // assert.EqualError(t, err, expectedErrorString) func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if !Error(t, theError, msgAndArgs...) { return false } @@ -1099,6 +1206,9 @@ func matchRegexp(rx interface{}, str interface{}) bool { // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") // assert.Regexp(t, "start...$", "it's not starting") func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } match := matchRegexp(rx, str) @@ -1114,6 +1224,9 @@ func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface // assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") // assert.NotRegexp(t, "^start", "it's not starting") func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } match := matchRegexp(rx, str) if match { @@ -1126,6 +1239,9 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf // Zero asserts that i is the zero value for its type. func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) } @@ -1134,6 +1250,9 @@ func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { // NotZero asserts that i is not the zero value for its type. func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) } @@ -1142,6 +1261,9 @@ func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { // FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } info, err := os.Lstat(path) if err != nil { if os.IsNotExist(err) { @@ -1157,6 +1279,9 @@ func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } info, err := os.Lstat(path) if err != nil { if os.IsNotExist(err) { @@ -1174,6 +1299,9 @@ func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { // // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } var expectedJSONAsInterface, actualJSONAsInterface interface{} if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { @@ -1212,12 +1340,18 @@ func diff(expected interface{}, actual interface{}) string { return "" } - if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array { + if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { return "" } - e := spewConfig.Sdump(expected) - a := spewConfig.Sdump(actual) + var e, a string + if ek != reflect.String { + e = spewConfig.Sdump(expected) + a = spewConfig.Sdump(actual) + } else { + e = expected.(string) + a = actual.(string) + } diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ A: difflib.SplitLines(e), @@ -1254,3 +1388,7 @@ var spewConfig = spew.ConfigState{ DisableCapacities: true, SortKeys: true, } + +type tHelper interface { + Helper() +} diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go index 3101e78ddc..df46fa777a 100644 --- a/vendor/github.com/stretchr/testify/assert/http_assertions.go +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -12,10 +12,11 @@ import ( // an error if building a new request fails. func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { w := httptest.NewRecorder() - req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + req, err := http.NewRequest(method, url, nil) if err != nil { return -1, err } + req.URL.RawQuery = values.Encode() handler(w, req) return w.Code, nil } @@ -26,6 +27,9 @@ func httpCode(handler http.HandlerFunc, method, url string, values url.Values) ( // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) @@ -46,6 +50,9 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) @@ -66,6 +73,9 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu // // Returns whether the assertion was successful (true) or not (false). func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) @@ -95,10 +105,13 @@ func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) s // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // -// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } body := HTTPBody(handler, method, url, values) contains := strings.Contains(body, fmt.Sprint(str)) @@ -112,10 +125,13 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // -// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } body := HTTPBody(handler, method, url, values) contains := strings.Contains(body, fmt.Sprint(str)) diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go index ac3c308788..535f293490 100644 --- a/vendor/github.com/stretchr/testify/require/require.go +++ b/vendor/github.com/stretchr/testify/require/require.go @@ -14,16 +14,24 @@ import ( // Condition uses a Comparison to assert a complex condition. func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) { - if !assert.Condition(t, comp, msgAndArgs...) { - t.FailNow() + if assert.Condition(t, comp, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Conditionf uses a Comparison to assert a complex condition. func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interface{}) { - if !assert.Conditionf(t, comp, msg, args...) { - t.FailNow() + if assert.Conditionf(t, comp, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Contains asserts that the specified string, list(array, slice...) or map contains the @@ -33,9 +41,13 @@ func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interfac // assert.Contains(t, ["Hello", "World"], "World") // assert.Contains(t, {"Hello": "World"}, "Hello") func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if !assert.Contains(t, s, contains, msgAndArgs...) { - t.FailNow() + if assert.Contains(t, s, contains, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Containsf asserts that the specified string, list(array, slice...) or map contains the @@ -45,23 +57,35 @@ func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...int // assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") // assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { - if !assert.Containsf(t, s, contains, msg, args...) { - t.FailNow() + if assert.Containsf(t, s, contains, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func DirExists(t TestingT, path string, msgAndArgs ...interface{}) { - if !assert.DirExists(t, path, msgAndArgs...) { - t.FailNow() + if assert.DirExists(t, path, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func DirExistsf(t TestingT, path string, msg string, args ...interface{}) { - if !assert.DirExistsf(t, path, msg, args...) { - t.FailNow() + if assert.DirExistsf(t, path, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified @@ -70,9 +94,13 @@ func DirExistsf(t TestingT, path string, msg string, args ...interface{}) { // // assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) { - if !assert.ElementsMatch(t, listA, listB, msgAndArgs...) { - t.FailNow() + if assert.ElementsMatch(t, listA, listB, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified @@ -81,9 +109,13 @@ func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs // // assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) { - if !assert.ElementsMatchf(t, listA, listB, msg, args...) { - t.FailNow() + if assert.ElementsMatchf(t, listA, listB, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either @@ -91,9 +123,13 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string // // assert.Empty(t, obj) func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if !assert.Empty(t, object, msgAndArgs...) { - t.FailNow() + if assert.Empty(t, object, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either @@ -101,9 +137,13 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { // // assert.Emptyf(t, obj, "error message %s", "formatted") func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { - if !assert.Emptyf(t, object, msg, args...) { - t.FailNow() + if assert.Emptyf(t, object, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Equal asserts that two objects are equal. @@ -114,9 +154,13 @@ func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if !assert.Equal(t, expected, actual, msgAndArgs...) { - t.FailNow() + if assert.Equal(t, expected, actual, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // EqualError asserts that a function returned an error (i.e. not `nil`) @@ -125,9 +169,13 @@ func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...i // actualObj, err := SomeFunction() // assert.EqualError(t, err, expectedErrorString) func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) { - if !assert.EqualError(t, theError, errString, msgAndArgs...) { - t.FailNow() + if assert.EqualError(t, theError, errString, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // EqualErrorf asserts that a function returned an error (i.e. not `nil`) @@ -136,9 +184,13 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte // actualObj, err := SomeFunction() // assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) { - if !assert.EqualErrorf(t, theError, errString, msg, args...) { - t.FailNow() + if assert.EqualErrorf(t, theError, errString, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // EqualValues asserts that two objects are equal or convertable to the same types @@ -146,9 +198,13 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args // // assert.EqualValues(t, uint32(123), int32(123)) func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if !assert.EqualValues(t, expected, actual, msgAndArgs...) { - t.FailNow() + if assert.EqualValues(t, expected, actual, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // EqualValuesf asserts that two objects are equal or convertable to the same types @@ -156,9 +212,13 @@ func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArg // // assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123)) func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if !assert.EqualValuesf(t, expected, actual, msg, args...) { - t.FailNow() + if assert.EqualValuesf(t, expected, actual, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Equalf asserts that two objects are equal. @@ -169,9 +229,13 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if !assert.Equalf(t, expected, actual, msg, args...) { - t.FailNow() + if assert.Equalf(t, expected, actual, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Error asserts that a function returned an error (i.e. not `nil`). @@ -181,9 +245,13 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar // assert.Equal(t, expectedError, err) // } func Error(t TestingT, err error, msgAndArgs ...interface{}) { - if !assert.Error(t, err, msgAndArgs...) { - t.FailNow() + if assert.Error(t, err, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Errorf asserts that a function returned an error (i.e. not `nil`). @@ -193,135 +261,195 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) { // assert.Equal(t, expectedErrorf, err) // } func Errorf(t TestingT, err error, msg string, args ...interface{}) { - if !assert.Errorf(t, err, msg, args...) { - t.FailNow() + if assert.Errorf(t, err, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Exactly asserts that two objects are equal in value and type. // // assert.Exactly(t, int32(123), int64(123)) func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if !assert.Exactly(t, expected, actual, msgAndArgs...) { - t.FailNow() + if assert.Exactly(t, expected, actual, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Exactlyf asserts that two objects are equal in value and type. // // assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123)) func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if !assert.Exactlyf(t, expected, actual, msg, args...) { - t.FailNow() + if assert.Exactlyf(t, expected, actual, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Fail reports a failure through func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) { - if !assert.Fail(t, failureMessage, msgAndArgs...) { - t.FailNow() + if assert.Fail(t, failureMessage, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // FailNow fails test func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) { - if !assert.FailNow(t, failureMessage, msgAndArgs...) { - t.FailNow() + if assert.FailNow(t, failureMessage, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // FailNowf fails test func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) { - if !assert.FailNowf(t, failureMessage, msg, args...) { - t.FailNow() + if assert.FailNowf(t, failureMessage, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Failf reports a failure through func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) { - if !assert.Failf(t, failureMessage, msg, args...) { - t.FailNow() + if assert.Failf(t, failureMessage, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // False asserts that the specified value is false. // // assert.False(t, myBool) func False(t TestingT, value bool, msgAndArgs ...interface{}) { - if !assert.False(t, value, msgAndArgs...) { - t.FailNow() + if assert.False(t, value, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Falsef asserts that the specified value is false. // // assert.Falsef(t, myBool, "error message %s", "formatted") func Falsef(t TestingT, value bool, msg string, args ...interface{}) { - if !assert.Falsef(t, value, msg, args...) { - t.FailNow() + if assert.Falsef(t, value, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func FileExists(t TestingT, path string, msgAndArgs ...interface{}) { - if !assert.FileExists(t, path, msgAndArgs...) { - t.FailNow() + if assert.FileExists(t, path, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func FileExistsf(t TestingT, path string, msg string, args ...interface{}) { - if !assert.FileExistsf(t, path, msg, args...) { - t.FailNow() + if assert.FileExistsf(t, path, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // -// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if !assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) { - t.FailNow() + if assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // -// assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if !assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) { - t.FailNow() + if assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // -// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if !assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) { - t.FailNow() + if assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // -// assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if !assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) { - t.FailNow() + if assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPError asserts that a specified handler returns an error status code. @@ -330,9 +458,13 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u // // Returns whether the assertion was successful (true) or not (false). func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if !assert.HTTPError(t, handler, method, url, values, msgAndArgs...) { - t.FailNow() + if assert.HTTPError(t, handler, method, url, values, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPErrorf asserts that a specified handler returns an error status code. @@ -341,9 +473,13 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if !assert.HTTPErrorf(t, handler, method, url, values, msg, args...) { - t.FailNow() + if assert.HTTPErrorf(t, handler, method, url, values, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPRedirect asserts that a specified handler returns a redirect status code. @@ -352,9 +488,13 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if !assert.HTTPRedirect(t, handler, method, url, values, msgAndArgs...) { - t.FailNow() + if assert.HTTPRedirect(t, handler, method, url, values, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPRedirectf asserts that a specified handler returns a redirect status code. @@ -363,9 +503,13 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url strin // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if !assert.HTTPRedirectf(t, handler, method, url, values, msg, args...) { - t.FailNow() + if assert.HTTPRedirectf(t, handler, method, url, values, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPSuccess asserts that a specified handler returns a success status code. @@ -374,9 +518,13 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if !assert.HTTPSuccess(t, handler, method, url, values, msgAndArgs...) { - t.FailNow() + if assert.HTTPSuccess(t, handler, method, url, values, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // HTTPSuccessf asserts that a specified handler returns a success status code. @@ -385,133 +533,201 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if !assert.HTTPSuccessf(t, handler, method, url, values, msg, args...) { - t.FailNow() + if assert.HTTPSuccessf(t, handler, method, url, values, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Implements asserts that an object is implemented by the specified interface. // // assert.Implements(t, (*MyInterface)(nil), new(MyObject)) func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { - if !assert.Implements(t, interfaceObject, object, msgAndArgs...) { - t.FailNow() + if assert.Implements(t, interfaceObject, object, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Implementsf asserts that an object is implemented by the specified interface. // // assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { - if !assert.Implementsf(t, interfaceObject, object, msg, args...) { - t.FailNow() + if assert.Implementsf(t, interfaceObject, object, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InDelta asserts that the two numerals are within delta of each other. // // assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if !assert.InDelta(t, expected, actual, delta, msgAndArgs...) { - t.FailNow() + if assert.InDelta(t, expected, actual, delta, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValues(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if !assert.InDeltaMapValues(t, expected, actual, delta, msgAndArgs...) { - t.FailNow() + if assert.InDeltaMapValues(t, expected, actual, delta, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if !assert.InDeltaMapValuesf(t, expected, actual, delta, msg, args...) { - t.FailNow() + if assert.InDeltaMapValuesf(t, expected, actual, delta, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InDeltaSlice is the same as InDelta, except it compares two slices. func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if !assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) { - t.FailNow() + if assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InDeltaSlicef is the same as InDelta, except it compares two slices. func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if !assert.InDeltaSlicef(t, expected, actual, delta, msg, args...) { - t.FailNow() + if assert.InDeltaSlicef(t, expected, actual, delta, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InDeltaf asserts that the two numerals are within delta of each other. // // assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if !assert.InDeltaf(t, expected, actual, delta, msg, args...) { - t.FailNow() + if assert.InDeltaf(t, expected, actual, delta, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InEpsilon asserts that expected and actual have a relative error less than epsilon func InEpsilon(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if !assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) { - t.FailNow() + if assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if !assert.InEpsilonSlice(t, expected, actual, epsilon, msgAndArgs...) { - t.FailNow() + if assert.InEpsilonSlice(t, expected, actual, epsilon, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if !assert.InEpsilonSlicef(t, expected, actual, epsilon, msg, args...) { - t.FailNow() + if assert.InEpsilonSlicef(t, expected, actual, epsilon, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // InEpsilonf asserts that expected and actual have a relative error less than epsilon func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if !assert.InEpsilonf(t, expected, actual, epsilon, msg, args...) { - t.FailNow() + if assert.InEpsilonf(t, expected, actual, epsilon, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { - if !assert.IsType(t, expectedType, object, msgAndArgs...) { - t.FailNow() + if assert.IsType(t, expectedType, object, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // IsTypef asserts that the specified objects are of the same type. func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) { - if !assert.IsTypef(t, expectedType, object, msg, args...) { - t.FailNow() + if assert.IsTypef(t, expectedType, object, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // JSONEq asserts that two JSON strings are equivalent. // // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { - if !assert.JSONEq(t, expected, actual, msgAndArgs...) { - t.FailNow() + if assert.JSONEq(t, expected, actual, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // JSONEqf asserts that two JSON strings are equivalent. // // assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { - if !assert.JSONEqf(t, expected, actual, msg, args...) { - t.FailNow() + if assert.JSONEqf(t, expected, actual, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Len asserts that the specified object has specific length. @@ -519,9 +735,13 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int // // assert.Len(t, mySlice, 3) func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) { - if !assert.Len(t, object, length, msgAndArgs...) { - t.FailNow() + if assert.Len(t, object, length, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Lenf asserts that the specified object has specific length. @@ -529,27 +749,39 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) // // assert.Lenf(t, mySlice, 3, "error message %s", "formatted") func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) { - if !assert.Lenf(t, object, length, msg, args...) { - t.FailNow() + if assert.Lenf(t, object, length, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Nil asserts that the specified object is nil. // // assert.Nil(t, err) func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if !assert.Nil(t, object, msgAndArgs...) { - t.FailNow() + if assert.Nil(t, object, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Nilf asserts that the specified object is nil. // // assert.Nilf(t, err, "error message %s", "formatted") func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) { - if !assert.Nilf(t, object, msg, args...) { - t.FailNow() + if assert.Nilf(t, object, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NoError asserts that a function returned no error (i.e. `nil`). @@ -559,9 +791,13 @@ func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) { // assert.Equal(t, expectedObj, actualObj) // } func NoError(t TestingT, err error, msgAndArgs ...interface{}) { - if !assert.NoError(t, err, msgAndArgs...) { - t.FailNow() + if assert.NoError(t, err, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NoErrorf asserts that a function returned no error (i.e. `nil`). @@ -571,9 +807,13 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) { // assert.Equal(t, expectedObj, actualObj) // } func NoErrorf(t TestingT, err error, msg string, args ...interface{}) { - if !assert.NoErrorf(t, err, msg, args...) { - t.FailNow() + if assert.NoErrorf(t, err, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the @@ -583,9 +823,13 @@ func NoErrorf(t TestingT, err error, msg string, args ...interface{}) { // assert.NotContains(t, ["Hello", "World"], "Earth") // assert.NotContains(t, {"Hello": "World"}, "Earth") func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if !assert.NotContains(t, s, contains, msgAndArgs...) { - t.FailNow() + if assert.NotContains(t, s, contains, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the @@ -595,9 +839,13 @@ func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ... // assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") // assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { - if !assert.NotContainsf(t, s, contains, msg, args...) { - t.FailNow() + if assert.NotContainsf(t, s, contains, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either @@ -607,9 +855,13 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a // assert.Equal(t, "two", obj[1]) // } func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if !assert.NotEmpty(t, object, msgAndArgs...) { - t.FailNow() + if assert.NotEmpty(t, object, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either @@ -619,9 +871,13 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { // assert.Equal(t, "two", obj[1]) // } func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) { - if !assert.NotEmptyf(t, object, msg, args...) { - t.FailNow() + if assert.NotEmptyf(t, object, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotEqual asserts that the specified values are NOT equal. @@ -631,9 +887,13 @@ func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if !assert.NotEqual(t, expected, actual, msgAndArgs...) { - t.FailNow() + if assert.NotEqual(t, expected, actual, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotEqualf asserts that the specified values are NOT equal. @@ -643,45 +903,65 @@ func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs . // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if !assert.NotEqualf(t, expected, actual, msg, args...) { - t.FailNow() + if assert.NotEqualf(t, expected, actual, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if !assert.NotNil(t, object, msgAndArgs...) { - t.FailNow() + if assert.NotNil(t, object, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) { - if !assert.NotNilf(t, object, msg, args...) { - t.FailNow() + if assert.NotNilf(t, object, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanics(t, func(){ RemainCalm() }) func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if !assert.NotPanics(t, f, msgAndArgs...) { - t.FailNow() + if assert.NotPanics(t, f, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { - if !assert.NotPanicsf(t, f, msg, args...) { - t.FailNow() + if assert.NotPanicsf(t, f, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotRegexp asserts that a specified regexp does not match a string. @@ -689,9 +969,13 @@ func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interfac // assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") // assert.NotRegexp(t, "^start", "it's not starting") func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if !assert.NotRegexp(t, rx, str, msgAndArgs...) { - t.FailNow() + if assert.NotRegexp(t, rx, str, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotRegexpf asserts that a specified regexp does not match a string. @@ -699,9 +983,13 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf // assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") // assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { - if !assert.NotRegexpf(t, rx, str, msg, args...) { - t.FailNow() + if assert.NotRegexpf(t, rx, str, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotSubset asserts that the specified list(array, slice...) contains not all @@ -709,9 +997,13 @@ func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args .. // // assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if !assert.NotSubset(t, list, subset, msgAndArgs...) { - t.FailNow() + if assert.NotSubset(t, list, subset, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotSubsetf asserts that the specified list(array, slice...) contains not all @@ -719,32 +1011,48 @@ func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...i // // assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { - if !assert.NotSubsetf(t, list, subset, msg, args...) { - t.FailNow() + if assert.NotSubsetf(t, list, subset, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotZero asserts that i is not the zero value for its type. func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) { - if !assert.NotZero(t, i, msgAndArgs...) { - t.FailNow() + if assert.NotZero(t, i, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // NotZerof asserts that i is not the zero value for its type. func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) { - if !assert.NotZerof(t, i, msg, args...) { - t.FailNow() + if assert.NotZerof(t, i, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Panics asserts that the code inside the specified PanicTestFunc panics. // // assert.Panics(t, func(){ GoCrazy() }) func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if !assert.Panics(t, f, msgAndArgs...) { - t.FailNow() + if assert.Panics(t, f, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that @@ -752,9 +1060,13 @@ func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { // // assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if !assert.PanicsWithValue(t, expected, f, msgAndArgs...) { - t.FailNow() + if assert.PanicsWithValue(t, expected, f, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that @@ -762,18 +1074,26 @@ func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, m // // assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { - if !assert.PanicsWithValuef(t, expected, f, msg, args...) { - t.FailNow() + if assert.PanicsWithValuef(t, expected, f, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { - if !assert.Panicsf(t, f, msg, args...) { - t.FailNow() + if assert.Panicsf(t, f, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Regexp asserts that a specified regexp matches a string. @@ -781,9 +1101,13 @@ func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{} // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") // assert.Regexp(t, "start...$", "it's not starting") func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if !assert.Regexp(t, rx, str, msgAndArgs...) { - t.FailNow() + if assert.Regexp(t, rx, str, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Regexpf asserts that a specified regexp matches a string. @@ -791,9 +1115,13 @@ func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface // assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") // assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { - if !assert.Regexpf(t, rx, str, msg, args...) { - t.FailNow() + if assert.Regexpf(t, rx, str, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Subset asserts that the specified list(array, slice...) contains all @@ -801,9 +1129,13 @@ func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...in // // assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if !assert.Subset(t, list, subset, msgAndArgs...) { - t.FailNow() + if assert.Subset(t, list, subset, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Subsetf asserts that the specified list(array, slice...) contains all @@ -811,57 +1143,85 @@ func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...inte // // assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { - if !assert.Subsetf(t, list, subset, msg, args...) { - t.FailNow() + if assert.Subsetf(t, list, subset, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // True asserts that the specified value is true. // // assert.True(t, myBool) func True(t TestingT, value bool, msgAndArgs ...interface{}) { - if !assert.True(t, value, msgAndArgs...) { - t.FailNow() + if assert.True(t, value, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Truef asserts that the specified value is true. // // assert.Truef(t, myBool, "error message %s", "formatted") func Truef(t TestingT, value bool, msg string, args ...interface{}) { - if !assert.Truef(t, value, msg, args...) { - t.FailNow() + if assert.Truef(t, value, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // WithinDuration asserts that the two times are within duration delta of each other. // // assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { - if !assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) { - t.FailNow() + if assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // WithinDurationf asserts that the two times are within duration delta of each other. // // assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { - if !assert.WithinDurationf(t, expected, actual, delta, msg, args...) { - t.FailNow() + if assert.WithinDurationf(t, expected, actual, delta, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Zero asserts that i is the zero value for its type. func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) { - if !assert.Zero(t, i, msgAndArgs...) { - t.FailNow() + if assert.Zero(t, i, msgAndArgs...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } // Zerof asserts that i is the zero value for its type. func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) { - if !assert.Zerof(t, i, msg, args...) { - t.FailNow() + if assert.Zerof(t, i, msg, args...) { + return } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() } diff --git a/vendor/github.com/stretchr/testify/require/require.go.tmpl b/vendor/github.com/stretchr/testify/require/require.go.tmpl new file mode 100644 index 0000000000..6ffc751b5e --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/require.go.tmpl @@ -0,0 +1,6 @@ +{{.Comment}} +func {{.DocInfo.Name}}(t TestingT, {{.Params}}) { + if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return } + if h, ok := t.(tHelper); ok { h.Helper() } + t.FailNow() +} diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go index 299ceb95ad..9fe41dbdc0 100644 --- a/vendor/github.com/stretchr/testify/require/require_forward.go +++ b/vendor/github.com/stretchr/testify/require/require_forward.go @@ -14,11 +14,17 @@ import ( // Condition uses a Comparison to assert a complex condition. func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Condition(a.t, comp, msgAndArgs...) } // Conditionf uses a Comparison to assert a complex condition. func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Conditionf(a.t, comp, msg, args...) } @@ -29,6 +35,9 @@ func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...inte // a.Contains(["Hello", "World"], "World") // a.Contains({"Hello": "World"}, "Hello") func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Contains(a.t, s, contains, msgAndArgs...) } @@ -39,16 +48,25 @@ func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs .. // a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") // a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Containsf(a.t, s, contains, msg, args...) } // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } DirExists(a.t, path, msgAndArgs...) } // DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } DirExistsf(a.t, path, msg, args...) } @@ -58,6 +76,9 @@ func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) { // // a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } ElementsMatch(a.t, listA, listB, msgAndArgs...) } @@ -67,6 +88,9 @@ func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndA // // a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } ElementsMatchf(a.t, listA, listB, msg, args...) } @@ -75,6 +99,9 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st // // a.Empty(obj) func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Empty(a.t, object, msgAndArgs...) } @@ -83,6 +110,9 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { // // a.Emptyf(obj, "error message %s", "formatted") func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Emptyf(a.t, object, msg, args...) } @@ -94,6 +124,9 @@ func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Equal(a.t, expected, actual, msgAndArgs...) } @@ -103,6 +136,9 @@ func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs // actualObj, err := SomeFunction() // a.EqualError(err, expectedErrorString) func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } EqualError(a.t, theError, errString, msgAndArgs...) } @@ -112,6 +148,9 @@ func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ... // actualObj, err := SomeFunction() // a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } EqualErrorf(a.t, theError, errString, msg, args...) } @@ -120,6 +159,9 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a // // a.EqualValues(uint32(123), int32(123)) func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } EqualValues(a.t, expected, actual, msgAndArgs...) } @@ -128,6 +170,9 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn // // a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123)) func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } EqualValuesf(a.t, expected, actual, msg, args...) } @@ -139,6 +184,9 @@ func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Equalf(a.t, expected, actual, msg, args...) } @@ -149,6 +197,9 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string // assert.Equal(t, expectedError, err) // } func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Error(a.t, err, msgAndArgs...) } @@ -159,6 +210,9 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { // assert.Equal(t, expectedErrorf, err) // } func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Errorf(a.t, err, msg, args...) } @@ -166,6 +220,9 @@ func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { // // a.Exactly(int32(123), int64(123)) func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Exactly(a.t, expected, actual, msgAndArgs...) } @@ -173,26 +230,41 @@ func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArg // // a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123)) func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Exactlyf(a.t, expected, actual, msg, args...) } // Fail reports a failure through func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Fail(a.t, failureMessage, msgAndArgs...) } // FailNow fails test func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } FailNow(a.t, failureMessage, msgAndArgs...) } // FailNowf fails test func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } FailNowf(a.t, failureMessage, msg, args...) } // Failf reports a failure through func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Failf(a.t, failureMessage, msg, args...) } @@ -200,6 +272,9 @@ func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{ // // a.False(myBool) func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } False(a.t, value, msgAndArgs...) } @@ -207,56 +282,77 @@ func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { // // a.Falsef(myBool, "error message %s", "formatted") func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Falsef(a.t, value, msg, args...) } // FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } FileExists(a.t, path, msgAndArgs...) } // FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } FileExistsf(a.t, path, msg, args...) } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // -// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // -// a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // -// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // -// a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) } @@ -266,6 +362,9 @@ func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method strin // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPError(a.t, handler, method, url, values, msgAndArgs...) } @@ -275,6 +374,9 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPErrorf(a.t, handler, method, url, values, msg, args...) } @@ -284,6 +386,9 @@ func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url str // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) } @@ -293,6 +398,9 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPRedirectf(a.t, handler, method, url, values, msg, args...) } @@ -302,6 +410,9 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) } @@ -311,6 +422,9 @@ func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url st // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } HTTPSuccessf(a.t, handler, method, url, values, msg, args...) } @@ -318,6 +432,9 @@ func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url s // // a.Implements((*MyInterface)(nil), new(MyObject)) func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Implements(a.t, interfaceObject, object, msgAndArgs...) } @@ -325,6 +442,9 @@ func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, // // a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Implementsf(a.t, interfaceObject, object, msg, args...) } @@ -332,26 +452,41 @@ func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{} // // a.InDelta(math.Pi, (22 / 7.0), 0.01) func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InDelta(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) } // InDeltaSlice is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaSlicef is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InDeltaSlicef(a.t, expected, actual, delta, msg, args...) } @@ -359,36 +494,57 @@ func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, del // // a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InDeltaf(a.t, expected, actual, delta, msg, args...) } // InEpsilon asserts that expected and actual have a relative error less than epsilon func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) } // InEpsilonf asserts that expected and actual have a relative error less than epsilon func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } InEpsilonf(a.t, expected, actual, epsilon, msg, args...) } // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } IsType(a.t, expectedType, object, msgAndArgs...) } // IsTypef asserts that the specified objects are of the same type. func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } IsTypef(a.t, expectedType, object, msg, args...) } @@ -396,6 +552,9 @@ func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg s // // a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } JSONEq(a.t, expected, actual, msgAndArgs...) } @@ -403,6 +562,9 @@ func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interf // // a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } JSONEqf(a.t, expected, actual, msg, args...) } @@ -411,6 +573,9 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args .. // // a.Len(mySlice, 3) func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Len(a.t, object, length, msgAndArgs...) } @@ -419,6 +584,9 @@ func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface // // a.Lenf(mySlice, 3, "error message %s", "formatted") func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Lenf(a.t, object, length, msg, args...) } @@ -426,6 +594,9 @@ func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...in // // a.Nil(err) func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Nil(a.t, object, msgAndArgs...) } @@ -433,6 +604,9 @@ func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { // // a.Nilf(err, "error message %s", "formatted") func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Nilf(a.t, object, msg, args...) } @@ -443,6 +617,9 @@ func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) { // assert.Equal(t, expectedObj, actualObj) // } func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NoError(a.t, err, msgAndArgs...) } @@ -453,6 +630,9 @@ func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { // assert.Equal(t, expectedObj, actualObj) // } func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NoErrorf(a.t, err, msg, args...) } @@ -463,6 +643,9 @@ func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) { // a.NotContains(["Hello", "World"], "Earth") // a.NotContains({"Hello": "World"}, "Earth") func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotContains(a.t, s, contains, msgAndArgs...) } @@ -473,6 +656,9 @@ func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs // a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") // a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotContainsf(a.t, s, contains, msg, args...) } @@ -483,6 +669,9 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin // assert.Equal(t, "two", obj[1]) // } func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotEmpty(a.t, object, msgAndArgs...) } @@ -493,6 +682,9 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { // assert.Equal(t, "two", obj[1]) // } func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotEmptyf(a.t, object, msg, args...) } @@ -503,6 +695,9 @@ func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotEqual(a.t, expected, actual, msgAndArgs...) } @@ -513,6 +708,9 @@ func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndAr // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotEqualf(a.t, expected, actual, msg, args...) } @@ -520,6 +718,9 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str // // a.NotNil(err) func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotNil(a.t, object, msgAndArgs...) } @@ -527,6 +728,9 @@ func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { // // a.NotNilf(err, "error message %s", "formatted") func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotNilf(a.t, object, msg, args...) } @@ -534,6 +738,9 @@ func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{} // // a.NotPanics(func(){ RemainCalm() }) func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotPanics(a.t, f, msgAndArgs...) } @@ -541,6 +748,9 @@ func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{} // // a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotPanicsf(a.t, f, msg, args...) } @@ -549,6 +759,9 @@ func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...inte // a.NotRegexp(regexp.MustCompile("starts"), "it's starting") // a.NotRegexp("^start", "it's not starting") func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotRegexp(a.t, rx, str, msgAndArgs...) } @@ -557,6 +770,9 @@ func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...in // a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") // a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotRegexpf(a.t, rx, str, msg, args...) } @@ -565,6 +781,9 @@ func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, arg // // a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotSubset(a.t, list, subset, msgAndArgs...) } @@ -573,16 +792,25 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs // // a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotSubsetf(a.t, list, subset, msg, args...) } // NotZero asserts that i is not the zero value for its type. func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotZero(a.t, i, msgAndArgs...) } // NotZerof asserts that i is not the zero value for its type. func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } NotZerof(a.t, i, msg, args...) } @@ -590,6 +818,9 @@ func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) { // // a.Panics(func(){ GoCrazy() }) func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Panics(a.t, f, msgAndArgs...) } @@ -598,6 +829,9 @@ func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { // // a.PanicsWithValue("crazy error", func(){ GoCrazy() }) func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } PanicsWithValue(a.t, expected, f, msgAndArgs...) } @@ -606,6 +840,9 @@ func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFun // // a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } PanicsWithValuef(a.t, expected, f, msg, args...) } @@ -613,6 +850,9 @@ func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFu // // a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Panicsf(a.t, f, msg, args...) } @@ -621,6 +861,9 @@ func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interfa // a.Regexp(regexp.MustCompile("start"), "it's starting") // a.Regexp("start...$", "it's not starting") func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Regexp(a.t, rx, str, msgAndArgs...) } @@ -629,6 +872,9 @@ func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...inter // a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") // a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Regexpf(a.t, rx, str, msg, args...) } @@ -637,6 +883,9 @@ func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args . // // a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Subset(a.t, list, subset, msgAndArgs...) } @@ -645,6 +894,9 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... // // a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Subsetf(a.t, list, subset, msg, args...) } @@ -652,6 +904,9 @@ func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, a // // a.True(myBool) func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } True(a.t, value, msgAndArgs...) } @@ -659,6 +914,9 @@ func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { // // a.Truef(myBool, "error message %s", "formatted") func (a *Assertions) Truef(value bool, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Truef(a.t, value, msg, args...) } @@ -666,6 +924,9 @@ func (a *Assertions) Truef(value bool, msg string, args ...interface{}) { // // a.WithinDuration(time.Now(), time.Now(), 10*time.Second) func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } WithinDuration(a.t, expected, actual, delta, msgAndArgs...) } @@ -673,15 +934,24 @@ func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta // // a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } WithinDurationf(a.t, expected, actual, delta, msg, args...) } // Zero asserts that i is the zero value for its type. func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Zero(a.t, i, msgAndArgs...) } // Zerof asserts that i is the zero value for its type. func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } Zerof(a.t, i, msg, args...) } diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl b/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl new file mode 100644 index 0000000000..54124df1d3 --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl @@ -0,0 +1,5 @@ +{{.CommentWithoutT "a"}} +func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) { + if h, ok := a.t.(tHelper); ok { h.Helper() } + {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) +} diff --git a/vendor/github.com/stretchr/testify/require/requirements.go b/vendor/github.com/stretchr/testify/require/requirements.go index e404f016d1..690583a8e0 100644 --- a/vendor/github.com/stretchr/testify/require/requirements.go +++ b/vendor/github.com/stretchr/testify/require/requirements.go @@ -6,4 +6,24 @@ type TestingT interface { FailNow() } +type tHelper interface { + Helper() +} + +// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful +// for table driven tests. +type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) + +// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful +// for table driven tests. +type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) + +// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful +// for table driven tests. +type BoolAssertionFunc func(TestingT, bool, ...interface{}) + +// ValuesAssertionFunc is a common function prototype when validating an error value. Can be useful +// for table driven tests. +type ErrorAssertionFunc func(TestingT, error, ...interface{}) + //go:generate go run ../_codegen/main.go -output-package=require -template=require.go.tmpl -include-format-funcs diff --git a/vendor/github.com/tstranex/u2f/.gitignore b/vendor/github.com/tstranex/u2f/.gitignore new file mode 100644 index 0000000000..440ef47f09 --- /dev/null +++ b/vendor/github.com/tstranex/u2f/.gitignore @@ -0,0 +1,4 @@ +*~ +/pkg/* +/bin/* +/src/* \ No newline at end of file diff --git a/vendor/github.com/tstranex/u2f/.travis.yml b/vendor/github.com/tstranex/u2f/.travis.yml new file mode 100644 index 0000000000..4f2ee4d973 --- /dev/null +++ b/vendor/github.com/tstranex/u2f/.travis.yml @@ -0,0 +1 @@ +language: go diff --git a/vendor/github.com/tstranex/u2f/README.md b/vendor/github.com/tstranex/u2f/README.md new file mode 100644 index 0000000000..95de78f8b5 --- /dev/null +++ b/vendor/github.com/tstranex/u2f/README.md @@ -0,0 +1,97 @@ +# Go FIDO U2F Library + +This Go package implements the parts of the FIDO U2F specification required on +the server side of an application. + +[![Build Status](https://travis-ci.org/tstranex/u2f.svg?branch=master)](https://travis-ci.org/tstranex/u2f) + +## Features + +- Native Go implementation +- No dependancies other than the Go standard library +- Token attestation certificate verification + +## Usage + +Please visit http://godoc.org/github.com/tstranex/u2f for the full +documentation. + +### How to enrol a new token + +```go +app_id := "http://localhost" + +// Send registration request to the browser. +c, _ := NewChallenge(app_id, []string{app_id}) +req, _ := c.RegisterRequest() + +// Read response from the browser. +var resp RegisterResponse +reg, err := Register(resp, c, nil) +if err != nil { + // Registration failed. +} + +// Store registration in the database. +``` + +### How to perform an authentication + +```go +// Fetch registration and counter from the database. +var reg Registration +var counter uint32 + +// Send authentication request to the browser. +c, _ := NewChallenge(app_id, []string{app_id}) +req, _ := c.SignRequest(reg) + +// Read response from the browser. +var resp SignResponse +newCounter, err := reg.Authenticate(resp, c, counter) +if err != nil { + // Authentication failed. +} + +// Store updated counter in the database. +``` + +## Installation + +``` +$ go get github.com/tstranex/u2f +``` + +## Example + +See u2fdemo/main.go for an full example server. To run it: + +``` +$ go install github.com/tstranex/u2f/u2fdemo +$ ./bin/u2fdemo +``` + +Open https://localhost:3483 in Chrome. +Ignore the SSL warning (due to the self-signed certificate for localhost). +You can then test registering and authenticating using your token. + +## Changelog + +- 2016-12-18: The package has been updated to work with the new + U2F Javascript 1.1 API specification. This causes some breaking changes. + + `SignRequest` has been replaced by `WebSignRequest` which now includes + multiple registrations. This is useful when the user has multiple devices + registered since you can now authenticate against any of them with a single + request. + + `WebRegisterRequest` has been introduced, which should generally be used + instead of using `RegisterRequest` directly. It includes the list of existing + registrations with the new registration request. If the user's device already + matches one of the existing registrations, it will refuse to re-register. + + `Challenge.RegisterRequest` has been replaced by `NewWebRegisterRequest`. + +## License + +The Go FIDO U2F Library is licensed under the MIT License. diff --git a/vendor/github.com/urfave/cli/.gitignore b/vendor/github.com/urfave/cli/.gitignore new file mode 100644 index 0000000000..faf70c4c24 --- /dev/null +++ b/vendor/github.com/urfave/cli/.gitignore @@ -0,0 +1,2 @@ +*.coverprofile +node_modules/ diff --git a/vendor/github.com/urfave/cli/.travis.yml b/vendor/github.com/urfave/cli/.travis.yml new file mode 100644 index 0000000000..94836d750e --- /dev/null +++ b/vendor/github.com/urfave/cli/.travis.yml @@ -0,0 +1,39 @@ +language: go + +sudo: false + +cache: + directories: + - node_modules + +go: +- 1.2.x +- 1.3.x +- 1.4.2 +- 1.5.x +- 1.6.x +- 1.7.x +- master + +matrix: + allow_failures: + - go: master + include: + - go: 1.6.x + os: osx + - go: 1.7.x + os: osx + +before_script: +- go get github.com/urfave/gfmrun/... || true +- go get golang.org/x/tools/... || true +- if [ ! -f node_modules/.bin/markdown-toc ] ; then + npm install markdown-toc ; + fi + +script: +- ./runtests gen +- ./runtests vet +- ./runtests test +- ./runtests gfmrun +- ./runtests toc diff --git a/vendor/github.com/urfave/cli/CHANGELOG.md b/vendor/github.com/urfave/cli/CHANGELOG.md new file mode 100644 index 0000000000..8b0d0eeadf --- /dev/null +++ b/vendor/github.com/urfave/cli/CHANGELOG.md @@ -0,0 +1,336 @@ +# Change Log + +**ATTN**: This project uses [semantic versioning](http://semver.org/). + +## [Unreleased] +### Added +- Flag type code generation via `go generate` +- Write to stderr and exit 1 if action returns non-nil error +- Added support for TOML to the `altsrc` loader + +### Changed +- Raise minimum tested/supported Go version to 1.2+ + +## [1.18.0] - 2016-06-27 +### Added +- `./runtests` test runner with coverage tracking by default +- testing on OS X +- testing on Windows +- `UintFlag`, `Uint64Flag`, and `Int64Flag` types and supporting code + +### Changed +- Use spaces for alignment in help/usage output instead of tabs, making the + output alignment consistent regardless of tab width + +### Fixed +- Printing of command aliases in help text +- Printing of visible flags for both struct and struct pointer flags +- Display the `help` subcommand when using `CommandCategories` +- No longer swallows `panic`s that occur within the `Action`s themselves when + detecting the signature of the `Action` field + +## [1.17.0] - 2016-05-09 +### Added +- Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc` +- `context.GlobalBoolT` was added as an analogue to `context.GlobalBool` +- Support for hiding commands by setting `Hidden: true` -- this will hide the + commands in help output + +### Changed +- `Float64Flag`, `IntFlag`, and `DurationFlag` default values are no longer + quoted in help text output. +- All flag types now include `(default: {value})` strings following usage when a + default value can be (reasonably) detected. +- `IntSliceFlag` and `StringSliceFlag` usage strings are now more consistent + with non-slice flag types +- Apps now exit with a code of 3 if an unknown subcommand is specified + (previously they printed "No help topic for...", but still exited 0. This + makes it easier to script around apps built using `cli` since they can trust + that a 0 exit code indicated a successful execution. +- cleanups based on [Go Report Card + feedback](https://goreportcard.com/report/github.com/urfave/cli) + +## [1.16.0] - 2016-05-02 +### Added +- `Hidden` field on all flag struct types to omit from generated help text + +### Changed +- `BashCompletionFlag` (`--enable-bash-completion`) is now omitted from +generated help text via the `Hidden` field + +### Fixed +- handling of error values in `HandleAction` and `HandleExitCoder` + +## [1.15.0] - 2016-04-30 +### Added +- This file! +- Support for placeholders in flag usage strings +- `App.Metadata` map for arbitrary data/state management +- `Set` and `GlobalSet` methods on `*cli.Context` for altering values after +parsing. +- Support for nested lookup of dot-delimited keys in structures loaded from +YAML. + +### Changed +- The `App.Action` and `Command.Action` now prefer a return signature of +`func(*cli.Context) error`, as defined by `cli.ActionFunc`. If a non-nil +`error` is returned, there may be two outcomes: + - If the error fulfills `cli.ExitCoder`, then `os.Exit` will be called + automatically + - Else the error is bubbled up and returned from `App.Run` +- Specifying an `Action` with the legacy return signature of +`func(*cli.Context)` will produce a deprecation message to stderr +- Specifying an `Action` that is not a `func` type will produce a non-zero exit +from `App.Run` +- Specifying an `Action` func that has an invalid (input) signature will +produce a non-zero exit from `App.Run` + +### Deprecated +- +`cli.App.RunAndExitOnError`, which should now be done by returning an error +that fulfills `cli.ExitCoder` to `cli.App.Run`. +- the legacy signature for +`cli.App.Action` of `func(*cli.Context)`, which should now have a return +signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`. + +### Fixed +- Added missing `*cli.Context.GlobalFloat64` method + +## [1.14.0] - 2016-04-03 (backfilled 2016-04-25) +### Added +- Codebeat badge +- Support for categorization via `CategorizedHelp` and `Categories` on app. + +### Changed +- Use `filepath.Base` instead of `path.Base` in `Name` and `HelpName`. + +### Fixed +- Ensure version is not shown in help text when `HideVersion` set. + +## [1.13.0] - 2016-03-06 (backfilled 2016-04-25) +### Added +- YAML file input support. +- `NArg` method on context. + +## [1.12.0] - 2016-02-17 (backfilled 2016-04-25) +### Added +- Custom usage error handling. +- Custom text support in `USAGE` section of help output. +- Improved help messages for empty strings. +- AppVeyor CI configuration. + +### Changed +- Removed `panic` from default help printer func. +- De-duping and optimizations. + +### Fixed +- Correctly handle `Before`/`After` at command level when no subcommands. +- Case of literal `-` argument causing flag reordering. +- Environment variable hints on Windows. +- Docs updates. + +## [1.11.1] - 2015-12-21 (backfilled 2016-04-25) +### Changed +- Use `path.Base` in `Name` and `HelpName` +- Export `GetName` on flag types. + +### Fixed +- Flag parsing when skipping is enabled. +- Test output cleanup. +- Move completion check to account for empty input case. + +## [1.11.0] - 2015-11-15 (backfilled 2016-04-25) +### Added +- Destination scan support for flags. +- Testing against `tip` in Travis CI config. + +### Changed +- Go version in Travis CI config. + +### Fixed +- Removed redundant tests. +- Use correct example naming in tests. + +## [1.10.2] - 2015-10-29 (backfilled 2016-04-25) +### Fixed +- Remove unused var in bash completion. + +## [1.10.1] - 2015-10-21 (backfilled 2016-04-25) +### Added +- Coverage and reference logos in README. + +### Fixed +- Use specified values in help and version parsing. +- Only display app version and help message once. + +## [1.10.0] - 2015-10-06 (backfilled 2016-04-25) +### Added +- More tests for existing functionality. +- `ArgsUsage` at app and command level for help text flexibility. + +### Fixed +- Honor `HideHelp` and `HideVersion` in `App.Run`. +- Remove juvenile word from README. + +## [1.9.0] - 2015-09-08 (backfilled 2016-04-25) +### Added +- `FullName` on command with accompanying help output update. +- Set default `$PROG` in bash completion. + +### Changed +- Docs formatting. + +### Fixed +- Removed self-referential imports in tests. + +## [1.8.0] - 2015-06-30 (backfilled 2016-04-25) +### Added +- Support for `Copyright` at app level. +- `Parent` func at context level to walk up context lineage. + +### Fixed +- Global flag processing at top level. + +## [1.7.1] - 2015-06-11 (backfilled 2016-04-25) +### Added +- Aggregate errors from `Before`/`After` funcs. +- Doc comments on flag structs. +- Include non-global flags when checking version and help. +- Travis CI config updates. + +### Fixed +- Ensure slice type flags have non-nil values. +- Collect global flags from the full command hierarchy. +- Docs prose. + +## [1.7.0] - 2015-05-03 (backfilled 2016-04-25) +### Changed +- `HelpPrinter` signature includes output writer. + +### Fixed +- Specify go 1.1+ in docs. +- Set `Writer` when running command as app. + +## [1.6.0] - 2015-03-23 (backfilled 2016-04-25) +### Added +- Multiple author support. +- `NumFlags` at context level. +- `Aliases` at command level. + +### Deprecated +- `ShortName` at command level. + +### Fixed +- Subcommand help output. +- Backward compatible support for deprecated `Author` and `Email` fields. +- Docs regarding `Names`/`Aliases`. + +## [1.5.0] - 2015-02-20 (backfilled 2016-04-25) +### Added +- `After` hook func support at app and command level. + +### Fixed +- Use parsed context when running command as subcommand. +- Docs prose. + +## [1.4.1] - 2015-01-09 (backfilled 2016-04-25) +### Added +- Support for hiding `-h / --help` flags, but not `help` subcommand. +- Stop flag parsing after `--`. + +### Fixed +- Help text for generic flags to specify single value. +- Use double quotes in output for defaults. +- Use `ParseInt` instead of `ParseUint` for int environment var values. +- Use `0` as base when parsing int environment var values. + +## [1.4.0] - 2014-12-12 (backfilled 2016-04-25) +### Added +- Support for environment variable lookup "cascade". +- Support for `Stdout` on app for output redirection. + +### Fixed +- Print command help instead of app help in `ShowCommandHelp`. + +## [1.3.1] - 2014-11-13 (backfilled 2016-04-25) +### Added +- Docs and example code updates. + +### Changed +- Default `-v / --version` flag made optional. + +## [1.3.0] - 2014-08-10 (backfilled 2016-04-25) +### Added +- `FlagNames` at context level. +- Exposed `VersionPrinter` var for more control over version output. +- Zsh completion hook. +- `AUTHOR` section in default app help template. +- Contribution guidelines. +- `DurationFlag` type. + +## [1.2.0] - 2014-08-02 +### Added +- Support for environment variable defaults on flags plus tests. + +## [1.1.0] - 2014-07-15 +### Added +- Bash completion. +- Optional hiding of built-in help command. +- Optional skipping of flag parsing at command level. +- `Author`, `Email`, and `Compiled` metadata on app. +- `Before` hook func support at app and command level. +- `CommandNotFound` func support at app level. +- Command reference available on context. +- `GenericFlag` type. +- `Float64Flag` type. +- `BoolTFlag` type. +- `IsSet` flag helper on context. +- More flag lookup funcs at context level. +- More tests & docs. + +### Changed +- Help template updates to account for presence/absence of flags. +- Separated subcommand help template. +- Exposed `HelpPrinter` var for more control over help output. + +## [1.0.0] - 2013-11-01 +### Added +- `help` flag in default app flag set and each command flag set. +- Custom handling of argument parsing errors. +- Command lookup by name at app level. +- `StringSliceFlag` type and supporting `StringSlice` type. +- `IntSliceFlag` type and supporting `IntSlice` type. +- Slice type flag lookups by name at context level. +- Export of app and command help functions. +- More tests & docs. + +## 0.1.0 - 2013-07-22 +### Added +- Initial implementation. + +[Unreleased]: https://github.com/urfave/cli/compare/v1.18.0...HEAD +[1.18.0]: https://github.com/urfave/cli/compare/v1.17.0...v1.18.0 +[1.17.0]: https://github.com/urfave/cli/compare/v1.16.0...v1.17.0 +[1.16.0]: https://github.com/urfave/cli/compare/v1.15.0...v1.16.0 +[1.15.0]: https://github.com/urfave/cli/compare/v1.14.0...v1.15.0 +[1.14.0]: https://github.com/urfave/cli/compare/v1.13.0...v1.14.0 +[1.13.0]: https://github.com/urfave/cli/compare/v1.12.0...v1.13.0 +[1.12.0]: https://github.com/urfave/cli/compare/v1.11.1...v1.12.0 +[1.11.1]: https://github.com/urfave/cli/compare/v1.11.0...v1.11.1 +[1.11.0]: https://github.com/urfave/cli/compare/v1.10.2...v1.11.0 +[1.10.2]: https://github.com/urfave/cli/compare/v1.10.1...v1.10.2 +[1.10.1]: https://github.com/urfave/cli/compare/v1.10.0...v1.10.1 +[1.10.0]: https://github.com/urfave/cli/compare/v1.9.0...v1.10.0 +[1.9.0]: https://github.com/urfave/cli/compare/v1.8.0...v1.9.0 +[1.8.0]: https://github.com/urfave/cli/compare/v1.7.1...v1.8.0 +[1.7.1]: https://github.com/urfave/cli/compare/v1.7.0...v1.7.1 +[1.7.0]: https://github.com/urfave/cli/compare/v1.6.0...v1.7.0 +[1.6.0]: https://github.com/urfave/cli/compare/v1.5.0...v1.6.0 +[1.5.0]: https://github.com/urfave/cli/compare/v1.4.1...v1.5.0 +[1.4.1]: https://github.com/urfave/cli/compare/v1.4.0...v1.4.1 +[1.4.0]: https://github.com/urfave/cli/compare/v1.3.1...v1.4.0 +[1.3.1]: https://github.com/urfave/cli/compare/v1.3.0...v1.3.1 +[1.3.0]: https://github.com/urfave/cli/compare/v1.2.0...v1.3.0 +[1.2.0]: https://github.com/urfave/cli/compare/v1.1.0...v1.2.0 +[1.1.0]: https://github.com/urfave/cli/compare/v1.0.0...v1.1.0 +[1.0.0]: https://github.com/urfave/cli/compare/v0.1.0...v1.0.0 diff --git a/vendor/github.com/urfave/cli/README.md b/vendor/github.com/urfave/cli/README.md new file mode 100644 index 0000000000..bb5f61eafd --- /dev/null +++ b/vendor/github.com/urfave/cli/README.md @@ -0,0 +1,1364 @@ +cli +=== + +[![Build Status](https://travis-ci.org/urfave/cli.svg?branch=master)](https://travis-ci.org/urfave/cli) +[![Windows Build Status](https://ci.appveyor.com/api/projects/status/rtgk5xufi932pb2v?svg=true)](https://ci.appveyor.com/project/urfave/cli) +[![GoDoc](https://godoc.org/github.com/urfave/cli?status.svg)](https://godoc.org/github.com/urfave/cli) +[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-urfave-cli) +[![Go Report Card](https://goreportcard.com/badge/urfave/cli)](https://goreportcard.com/report/urfave/cli) +[![top level coverage](https://gocover.io/_badge/github.com/urfave/cli?0 "top level coverage")](http://gocover.io/github.com/urfave/cli) / +[![altsrc coverage](https://gocover.io/_badge/github.com/urfave/cli/altsrc?0 "altsrc coverage")](http://gocover.io/github.com/urfave/cli/altsrc) + +**Notice:** This is the library formerly known as +`github.com/codegangsta/cli` -- Github will automatically redirect requests +to this repository, but we recommend updating your references for clarity. + +cli is a simple, fast, and fun package for building command line apps in Go. The +goal is to enable developers to write fast and distributable command line +applications in an expressive way. + + + +- [Overview](#overview) +- [Installation](#installation) + * [Supported platforms](#supported-platforms) + * [Using the `v2` branch](#using-the-v2-branch) + * [Pinning to the `v1` releases](#pinning-to-the-v1-releases) +- [Getting Started](#getting-started) +- [Examples](#examples) + * [Arguments](#arguments) + * [Flags](#flags) + + [Placeholder Values](#placeholder-values) + + [Alternate Names](#alternate-names) + + [Ordering](#ordering) + + [Values from the Environment](#values-from-the-environment) + + [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others) + * [Subcommands](#subcommands) + * [Subcommands categories](#subcommands-categories) + * [Exit code](#exit-code) + * [Bash Completion](#bash-completion) + + [Enabling](#enabling) + + [Distribution](#distribution) + + [Customization](#customization) + * [Generated Help Text](#generated-help-text) + + [Customization](#customization-1) + * [Version Flag](#version-flag) + + [Customization](#customization-2) + + [Full API Example](#full-api-example) +- [Contribution Guidelines](#contribution-guidelines) + + + +## Overview + +Command line apps are usually so tiny that there is absolutely no reason why +your code should *not* be self-documenting. Things like generating help text and +parsing command flags/options should not hinder productivity when writing a +command line app. + +**This is where cli comes into play.** cli makes command line programming fun, +organized, and expressive! + +## Installation + +Make sure you have a working Go environment. Go version 1.2+ is supported. [See +the install instructions for Go](http://golang.org/doc/install.html). + +To install cli, simply run: +``` +$ go get github.com/urfave/cli +``` + +Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can +be easily used: +``` +export PATH=$PATH:$GOPATH/bin +``` + +### Supported platforms + +cli is tested against multiple versions of Go on Linux, and against the latest +released version of Go on OS X and Windows. For full details, see +[`./.travis.yml`](./.travis.yml) and [`./appveyor.yml`](./appveyor.yml). + +### Using the `v2` branch + +**Warning**: The `v2` branch is currently unreleased and considered unstable. + +There is currently a long-lived branch named `v2` that is intended to land as +the new `master` branch once development there has settled down. The current +`master` branch (mirrored as `v1`) is being manually merged into `v2` on +an irregular human-based schedule, but generally if one wants to "upgrade" to +`v2` *now* and accept the volatility (read: "awesomeness") that comes along with +that, please use whatever version pinning of your preference, such as via +`gopkg.in`: + +``` +$ go get gopkg.in/urfave/cli.v2 +``` + +``` go +... +import ( + "gopkg.in/urfave/cli.v2" // imports as package "cli" +) +... +``` + +### Pinning to the `v1` releases + +Similarly to the section above describing use of the `v2` branch, if one wants +to avoid any unexpected compatibility pains once `v2` becomes `master`, then +pinning to `v1` is an acceptable option, e.g.: + +``` +$ go get gopkg.in/urfave/cli.v1 +``` + +``` go +... +import ( + "gopkg.in/urfave/cli.v1" // imports as package "cli" +) +... +``` + +This will pull the latest tagged `v1` release (e.g. `v1.18.1` at the time of writing). + +## Getting Started + +One of the philosophies behind cli is that an API should be playful and full of +discovery. So a cli app can be as little as one line of code in `main()`. + + +``` go +package main + +import ( + "os" + + "github.com/urfave/cli" +) + +func main() { + cli.NewApp().Run(os.Args) +} +``` + +This app will run and show help text, but is not very useful. Let's give an +action to execute and some help documentation: + + +``` go +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + app.Name = "boom" + app.Usage = "make an explosive entrance" + app.Action = func(c *cli.Context) error { + fmt.Println("boom! I say!") + return nil + } + + app.Run(os.Args) +} +``` + +Running this already gives you a ton of functionality, plus support for things +like subcommands and flags, which are covered below. + +## Examples + +Being a programmer can be a lonely job. Thankfully by the power of automation +that is not the case! Let's create a greeter app to fend off our demons of +loneliness! + +Start by creating a directory named `greet`, and within it, add a file, +`greet.go` with the following code in it: + + +``` go +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + app.Name = "greet" + app.Usage = "fight the loneliness!" + app.Action = func(c *cli.Context) error { + fmt.Println("Hello friend!") + return nil + } + + app.Run(os.Args) +} +``` + +Install our command to the `$GOPATH/bin` directory: + +``` +$ go install +``` + +Finally run our new command: + +``` +$ greet +Hello friend! +``` + +cli also generates neat help text: + +``` +$ greet help +NAME: + greet - fight the loneliness! + +USAGE: + greet [global options] command [command options] [arguments...] + +VERSION: + 0.0.0 + +COMMANDS: + help, h Shows a list of commands or help for one command + +GLOBAL OPTIONS + --version Shows version information +``` + +### Arguments + +You can lookup arguments by calling the `Args` function on `cli.Context`, e.g.: + + +``` go +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + + app.Action = func(c *cli.Context) error { + fmt.Printf("Hello %q", c.Args().Get(0)) + return nil + } + + app.Run(os.Args) +} +``` + +### Flags + +Setting and querying flags is simple. + + +``` go +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + + app.Flags = []cli.Flag { + cli.StringFlag{ + Name: "lang", + Value: "english", + Usage: "language for the greeting", + }, + } + + app.Action = func(c *cli.Context) error { + name := "Nefertiti" + if c.NArg() > 0 { + name = c.Args().Get(0) + } + if c.String("lang") == "spanish" { + fmt.Println("Hola", name) + } else { + fmt.Println("Hello", name) + } + return nil + } + + app.Run(os.Args) +} +``` + +You can also set a destination variable for a flag, to which the content will be +scanned. + + +``` go +package main + +import ( + "os" + "fmt" + + "github.com/urfave/cli" +) + +func main() { + var language string + + app := cli.NewApp() + + app.Flags = []cli.Flag { + cli.StringFlag{ + Name: "lang", + Value: "english", + Usage: "language for the greeting", + Destination: &language, + }, + } + + app.Action = func(c *cli.Context) error { + name := "someone" + if c.NArg() > 0 { + name = c.Args()[0] + } + if language == "spanish" { + fmt.Println("Hola", name) + } else { + fmt.Println("Hello", name) + } + return nil + } + + app.Run(os.Args) +} +``` + +See full list of flags at http://godoc.org/github.com/urfave/cli + +#### Placeholder Values + +Sometimes it's useful to specify a flag's value within the usage string itself. +Such placeholders are indicated with back quotes. + +For example this: + + +```go +package main + +import ( + "os" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + + app.Flags = []cli.Flag{ + cli.StringFlag{ + Name: "config, c", + Usage: "Load configuration from `FILE`", + }, + } + + app.Run(os.Args) +} +``` + +Will result in help output like: + +``` +--config FILE, -c FILE Load configuration from FILE +``` + +Note that only the first placeholder is used. Subsequent back-quoted words will +be left as-is. + +#### Alternate Names + +You can set alternate (or short) names for flags by providing a comma-delimited +list for the `Name`. e.g. + + +``` go +package main + +import ( + "os" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + + app.Flags = []cli.Flag { + cli.StringFlag{ + Name: "lang, l", + Value: "english", + Usage: "language for the greeting", + }, + } + + app.Run(os.Args) +} +``` + +That flag can then be set with `--lang spanish` or `-l spanish`. Note that +giving two different forms of the same flag in the same command invocation is an +error. + +#### Ordering + +Flags for the application and commands are shown in the order they are defined. +However, it's possible to sort them from outside this library by using `FlagsByName` +with `sort`. + +For example this: + + +``` go +package main + +import ( + "os" + "sort" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + + app.Flags = []cli.Flag { + cli.StringFlag{ + Name: "lang, l", + Value: "english", + Usage: "Language for the greeting", + }, + cli.StringFlag{ + Name: "config, c", + Usage: "Load configuration from `FILE`", + }, + } + + sort.Sort(cli.FlagsByName(app.Flags)) + + app.Run(os.Args) +} +``` + +Will result in help output like: + +``` +--config FILE, -c FILE Load configuration from FILE +--lang value, -l value Language for the greeting (default: "english") +``` + +#### Values from the Environment + +You can also have the default value set from the environment via `EnvVar`. e.g. + + +``` go +package main + +import ( + "os" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + + app.Flags = []cli.Flag { + cli.StringFlag{ + Name: "lang, l", + Value: "english", + Usage: "language for the greeting", + EnvVar: "APP_LANG", + }, + } + + app.Run(os.Args) +} +``` + +The `EnvVar` may also be given as a comma-delimited "cascade", where the first +environment variable that resolves is used as the default. + + +``` go +package main + +import ( + "os" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + + app.Flags = []cli.Flag { + cli.StringFlag{ + Name: "lang, l", + Value: "english", + Usage: "language for the greeting", + EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG", + }, + } + + app.Run(os.Args) +} +``` + +#### Values from alternate input sources (YAML, TOML, and others) + +There is a separate package altsrc that adds support for getting flag values +from other file input sources. + +Currently supported input source formats: +* YAML +* TOML + +In order to get values for a flag from an alternate input source the following +code would be added to wrap an existing cli.Flag like below: + +``` go + altsrc.NewIntFlag(cli.IntFlag{Name: "test"}) +``` + +Initialization must also occur for these flags. Below is an example initializing +getting data from a yaml file below. + +``` go + command.Before = altsrc.InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load")) +``` + +The code above will use the "load" string as a flag name to get the file name of +a yaml file from the cli.Context. It will then use that file name to initialize +the yaml input source for any flags that are defined on that command. As a note +the "load" flag used would also have to be defined on the command flags in order +for this code snipped to work. + +Currently only the aboved specified formats are supported but developers can +add support for other input sources by implementing the +altsrc.InputSourceContext for their given sources. + +Here is a more complete sample of a command using YAML support: + + +``` go +package notmain + +import ( + "fmt" + "os" + + "github.com/urfave/cli" + "github.com/urfave/cli/altsrc" +) + +func main() { + app := cli.NewApp() + + flags := []cli.Flag{ + altsrc.NewIntFlag(cli.IntFlag{Name: "test"}), + cli.StringFlag{Name: "load"}, + } + + app.Action = func(c *cli.Context) error { + fmt.Println("yaml ist rad") + return nil + } + + app.Before = altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("load")) + app.Flags = flags + + app.Run(os.Args) +} +``` + +### Subcommands + +Subcommands can be defined for a more git-like command line app. + + +```go +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + + app.Commands = []cli.Command{ + { + Name: "add", + Aliases: []string{"a"}, + Usage: "add a task to the list", + Action: func(c *cli.Context) error { + fmt.Println("added task: ", c.Args().First()) + return nil + }, + }, + { + Name: "complete", + Aliases: []string{"c"}, + Usage: "complete a task on the list", + Action: func(c *cli.Context) error { + fmt.Println("completed task: ", c.Args().First()) + return nil + }, + }, + { + Name: "template", + Aliases: []string{"t"}, + Usage: "options for task templates", + Subcommands: []cli.Command{ + { + Name: "add", + Usage: "add a new template", + Action: func(c *cli.Context) error { + fmt.Println("new task template: ", c.Args().First()) + return nil + }, + }, + { + Name: "remove", + Usage: "remove an existing template", + Action: func(c *cli.Context) error { + fmt.Println("removed task template: ", c.Args().First()) + return nil + }, + }, + }, + }, + } + + app.Run(os.Args) +} +``` + +### Subcommands categories + +For additional organization in apps that have many subcommands, you can +associate a category for each command to group them together in the help +output. + +E.g. + +```go +package main + +import ( + "os" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + + app.Commands = []cli.Command{ + { + Name: "noop", + }, + { + Name: "add", + Category: "template", + }, + { + Name: "remove", + Category: "template", + }, + } + + app.Run(os.Args) +} +``` + +Will include: + +``` +COMMANDS: + noop + + Template actions: + add + remove +``` + +### Exit code + +Calling `App.Run` will not automatically call `os.Exit`, which means that by +default the exit code will "fall through" to being `0`. An explicit exit code +may be set by returning a non-nil error that fulfills `cli.ExitCoder`, *or* a +`cli.MultiError` that includes an error that fulfills `cli.ExitCoder`, e.g.: + +``` go +package main + +import ( + "os" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + app.Flags = []cli.Flag{ + cli.BoolTFlag{ + Name: "ginger-crouton", + Usage: "is it in the soup?", + }, + } + app.Action = func(ctx *cli.Context) error { + if !ctx.Bool("ginger-crouton") { + return cli.NewExitError("it is not in the soup", 86) + } + return nil + } + + app.Run(os.Args) +} +``` + +### Bash Completion + +You can enable completion commands by setting the `EnableBashCompletion` +flag on the `App` object. By default, this setting will only auto-complete to +show an app's subcommands, but you can write your own completion methods for +the App or its subcommands. + + +``` go +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +func main() { + tasks := []string{"cook", "clean", "laundry", "eat", "sleep", "code"} + + app := cli.NewApp() + app.EnableBashCompletion = true + app.Commands = []cli.Command{ + { + Name: "complete", + Aliases: []string{"c"}, + Usage: "complete a task on the list", + Action: func(c *cli.Context) error { + fmt.Println("completed task: ", c.Args().First()) + return nil + }, + BashComplete: func(c *cli.Context) { + // This will complete if no args are passed + if c.NArg() > 0 { + return + } + for _, t := range tasks { + fmt.Println(t) + } + }, + }, + } + + app.Run(os.Args) +} +``` + +#### Enabling + +Source the `autocomplete/bash_autocomplete` file in your `.bashrc` file while +setting the `PROG` variable to the name of your program: + +`PROG=myprogram source /.../cli/autocomplete/bash_autocomplete` + +#### Distribution + +Copy `autocomplete/bash_autocomplete` into `/etc/bash_completion.d/` and rename +it to the name of the program you wish to add autocomplete support for (or +automatically install it there if you are distributing a package). Don't forget +to source the file to make it active in the current shell. + +``` +sudo cp src/bash_autocomplete /etc/bash_completion.d/ +source /etc/bash_completion.d/ +``` + +Alternatively, you can just document that users should source the generic +`autocomplete/bash_autocomplete` in their bash configuration with `$PROG` set +to the name of their program (as above). + +#### Customization + +The default bash completion flag (`--generate-bash-completion`) is defined as +`cli.BashCompletionFlag`, and may be redefined if desired, e.g.: + + +``` go +package main + +import ( + "os" + + "github.com/urfave/cli" +) + +func main() { + cli.BashCompletionFlag = cli.BoolFlag{ + Name: "compgen", + Hidden: true, + } + + app := cli.NewApp() + app.EnableBashCompletion = true + app.Commands = []cli.Command{ + { + Name: "wat", + }, + } + app.Run(os.Args) +} +``` + +### Generated Help Text + +The default help flag (`-h/--help`) is defined as `cli.HelpFlag` and is checked +by the cli internals in order to print generated help text for the app, command, +or subcommand, and break execution. + +#### Customization + +All of the help text generation may be customized, and at multiple levels. The +templates are exposed as variables `AppHelpTemplate`, `CommandHelpTemplate`, and +`SubcommandHelpTemplate` which may be reassigned or augmented, and full override +is possible by assigning a compatible func to the `cli.HelpPrinter` variable, +e.g.: + + +``` go +package main + +import ( + "fmt" + "io" + "os" + + "github.com/urfave/cli" +) + +func main() { + // EXAMPLE: Append to an existing template + cli.AppHelpTemplate = fmt.Sprintf(`%s + +WEBSITE: http://awesometown.example.com + +SUPPORT: support@awesometown.example.com + +`, cli.AppHelpTemplate) + + // EXAMPLE: Override a template + cli.AppHelpTemplate = `NAME: + {{.Name}} - {{.Usage}} +USAGE: + {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command +[command options]{{end}} {{if +.ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} + {{if len .Authors}} +AUTHOR(S): + {{range .Authors}}{{ . }}{{end}} + {{end}}{{if .Commands}} +COMMANDS: +{{range .Commands}}{{if not .HideHelp}} {{join .Names ", "}}{{ "\t" +}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}} +GLOBAL OPTIONS: + {{range .VisibleFlags}}{{.}} + {{end}}{{end}}{{if .Copyright }} +COPYRIGHT: + {{.Copyright}} + {{end}}{{if .Version}} +VERSION: + {{.Version}} + {{end}} +` + + // EXAMPLE: Replace the `HelpPrinter` func + cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) { + fmt.Println("Ha HA. I pwnd the help!!1") + } + + cli.NewApp().Run(os.Args) +} +``` + +The default flag may be customized to something other than `-h/--help` by +setting `cli.HelpFlag`, e.g.: + + +``` go +package main + +import ( + "os" + + "github.com/urfave/cli" +) + +func main() { + cli.HelpFlag = cli.BoolFlag{ + Name: "halp, haaaaalp", + Usage: "HALP", + EnvVar: "SHOW_HALP,HALPPLZ", + } + + cli.NewApp().Run(os.Args) +} +``` + +### Version Flag + +The default version flag (`-v/--version`) is defined as `cli.VersionFlag`, which +is checked by the cli internals in order to print the `App.Version` via +`cli.VersionPrinter` and break execution. + +#### Customization + +The default flag may be customized to something other than `-v/--version` by +setting `cli.VersionFlag`, e.g.: + + +``` go +package main + +import ( + "os" + + "github.com/urfave/cli" +) + +func main() { + cli.VersionFlag = cli.BoolFlag{ + Name: "print-version, V", + Usage: "print only the version", + } + + app := cli.NewApp() + app.Name = "partay" + app.Version = "19.99.0" + app.Run(os.Args) +} +``` + +Alternatively, the version printer at `cli.VersionPrinter` may be overridden, e.g.: + + +``` go +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +var ( + Revision = "fafafaf" +) + +func main() { + cli.VersionPrinter = func(c *cli.Context) { + fmt.Printf("version=%s revision=%s\n", c.App.Version, Revision) + } + + app := cli.NewApp() + app.Name = "partay" + app.Version = "19.99.0" + app.Run(os.Args) +} +``` + +#### Full API Example + +**Notice**: This is a contrived (functioning) example meant strictly for API +demonstration purposes. Use of one's imagination is encouraged. + + +``` go +package main + +import ( + "errors" + "flag" + "fmt" + "io" + "io/ioutil" + "os" + "time" + + "github.com/urfave/cli" +) + +func init() { + cli.AppHelpTemplate += "\nCUSTOMIZED: you bet ur muffins\n" + cli.CommandHelpTemplate += "\nYMMV\n" + cli.SubcommandHelpTemplate += "\nor something\n" + + cli.HelpFlag = cli.BoolFlag{Name: "halp"} + cli.BashCompletionFlag = cli.BoolFlag{Name: "compgen", Hidden: true} + cli.VersionFlag = cli.BoolFlag{Name: "print-version, V"} + + cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) { + fmt.Fprintf(w, "best of luck to you\n") + } + cli.VersionPrinter = func(c *cli.Context) { + fmt.Fprintf(c.App.Writer, "version=%s\n", c.App.Version) + } + cli.OsExiter = func(c int) { + fmt.Fprintf(cli.ErrWriter, "refusing to exit %d\n", c) + } + cli.ErrWriter = ioutil.Discard + cli.FlagStringer = func(fl cli.Flag) string { + return fmt.Sprintf("\t\t%s", fl.GetName()) + } +} + +type hexWriter struct{} + +func (w *hexWriter) Write(p []byte) (int, error) { + for _, b := range p { + fmt.Printf("%x", b) + } + fmt.Printf("\n") + + return len(p), nil +} + +type genericType struct{ + s string +} + +func (g *genericType) Set(value string) error { + g.s = value + return nil +} + +func (g *genericType) String() string { + return g.s +} + +func main() { + app := cli.NewApp() + app.Name = "kənˈtrīv" + app.Version = "19.99.0" + app.Compiled = time.Now() + app.Authors = []cli.Author{ + cli.Author{ + Name: "Example Human", + Email: "human@example.com", + }, + } + app.Copyright = "(c) 1999 Serious Enterprise" + app.HelpName = "contrive" + app.Usage = "demonstrate available API" + app.UsageText = "contrive - demonstrating the available API" + app.ArgsUsage = "[args and such]" + app.Commands = []cli.Command{ + cli.Command{ + Name: "doo", + Aliases: []string{"do"}, + Category: "motion", + Usage: "do the doo", + UsageText: "doo - does the dooing", + Description: "no really, there is a lot of dooing to be done", + ArgsUsage: "[arrgh]", + Flags: []cli.Flag{ + cli.BoolFlag{Name: "forever, forevvarr"}, + }, + Subcommands: cli.Commands{ + cli.Command{ + Name: "wop", + Action: wopAction, + }, + }, + SkipFlagParsing: false, + HideHelp: false, + Hidden: false, + HelpName: "doo!", + BashComplete: func(c *cli.Context) { + fmt.Fprintf(c.App.Writer, "--better\n") + }, + Before: func(c *cli.Context) error { + fmt.Fprintf(c.App.Writer, "brace for impact\n") + return nil + }, + After: func(c *cli.Context) error { + fmt.Fprintf(c.App.Writer, "did we lose anyone?\n") + return nil + }, + Action: func(c *cli.Context) error { + c.Command.FullName() + c.Command.HasName("wop") + c.Command.Names() + c.Command.VisibleFlags() + fmt.Fprintf(c.App.Writer, "dodododododoodododddooooododododooo\n") + if c.Bool("forever") { + c.Command.Run(c) + } + return nil + }, + OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error { + fmt.Fprintf(c.App.Writer, "for shame\n") + return err + }, + }, + } + app.Flags = []cli.Flag{ + cli.BoolFlag{Name: "fancy"}, + cli.BoolTFlag{Name: "fancier"}, + cli.DurationFlag{Name: "howlong, H", Value: time.Second * 3}, + cli.Float64Flag{Name: "howmuch"}, + cli.GenericFlag{Name: "wat", Value: &genericType{}}, + cli.Int64Flag{Name: "longdistance"}, + cli.Int64SliceFlag{Name: "intervals"}, + cli.IntFlag{Name: "distance"}, + cli.IntSliceFlag{Name: "times"}, + cli.StringFlag{Name: "dance-move, d"}, + cli.StringSliceFlag{Name: "names, N"}, + cli.UintFlag{Name: "age"}, + cli.Uint64Flag{Name: "bigage"}, + } + app.EnableBashCompletion = true + app.HideHelp = false + app.HideVersion = false + app.BashComplete = func(c *cli.Context) { + fmt.Fprintf(c.App.Writer, "lipstick\nkiss\nme\nlipstick\nringo\n") + } + app.Before = func(c *cli.Context) error { + fmt.Fprintf(c.App.Writer, "HEEEERE GOES\n") + return nil + } + app.After = func(c *cli.Context) error { + fmt.Fprintf(c.App.Writer, "Phew!\n") + return nil + } + app.CommandNotFound = func(c *cli.Context, command string) { + fmt.Fprintf(c.App.Writer, "Thar be no %q here.\n", command) + } + app.OnUsageError = func(c *cli.Context, err error, isSubcommand bool) error { + if isSubcommand { + return err + } + + fmt.Fprintf(c.App.Writer, "WRONG: %#v\n", err) + return nil + } + app.Action = func(c *cli.Context) error { + cli.DefaultAppComplete(c) + cli.HandleExitCoder(errors.New("not an exit coder, though")) + cli.ShowAppHelp(c) + cli.ShowCommandCompletions(c, "nope") + cli.ShowCommandHelp(c, "also-nope") + cli.ShowCompletions(c) + cli.ShowSubcommandHelp(c) + cli.ShowVersion(c) + + categories := c.App.Categories() + categories.AddCommand("sounds", cli.Command{ + Name: "bloop", + }) + + for _, category := range c.App.Categories() { + fmt.Fprintf(c.App.Writer, "%s\n", category.Name) + fmt.Fprintf(c.App.Writer, "%#v\n", category.Commands) + fmt.Fprintf(c.App.Writer, "%#v\n", category.VisibleCommands()) + } + + fmt.Printf("%#v\n", c.App.Command("doo")) + if c.Bool("infinite") { + c.App.Run([]string{"app", "doo", "wop"}) + } + + if c.Bool("forevar") { + c.App.RunAsSubcommand(c) + } + c.App.Setup() + fmt.Printf("%#v\n", c.App.VisibleCategories()) + fmt.Printf("%#v\n", c.App.VisibleCommands()) + fmt.Printf("%#v\n", c.App.VisibleFlags()) + + fmt.Printf("%#v\n", c.Args().First()) + if len(c.Args()) > 0 { + fmt.Printf("%#v\n", c.Args()[1]) + } + fmt.Printf("%#v\n", c.Args().Present()) + fmt.Printf("%#v\n", c.Args().Tail()) + + set := flag.NewFlagSet("contrive", 0) + nc := cli.NewContext(c.App, set, c) + + fmt.Printf("%#v\n", nc.Args()) + fmt.Printf("%#v\n", nc.Bool("nope")) + fmt.Printf("%#v\n", nc.BoolT("nerp")) + fmt.Printf("%#v\n", nc.Duration("howlong")) + fmt.Printf("%#v\n", nc.Float64("hay")) + fmt.Printf("%#v\n", nc.Generic("bloop")) + fmt.Printf("%#v\n", nc.Int64("bonk")) + fmt.Printf("%#v\n", nc.Int64Slice("burnks")) + fmt.Printf("%#v\n", nc.Int("bips")) + fmt.Printf("%#v\n", nc.IntSlice("blups")) + fmt.Printf("%#v\n", nc.String("snurt")) + fmt.Printf("%#v\n", nc.StringSlice("snurkles")) + fmt.Printf("%#v\n", nc.Uint("flub")) + fmt.Printf("%#v\n", nc.Uint64("florb")) + fmt.Printf("%#v\n", nc.GlobalBool("global-nope")) + fmt.Printf("%#v\n", nc.GlobalBoolT("global-nerp")) + fmt.Printf("%#v\n", nc.GlobalDuration("global-howlong")) + fmt.Printf("%#v\n", nc.GlobalFloat64("global-hay")) + fmt.Printf("%#v\n", nc.GlobalGeneric("global-bloop")) + fmt.Printf("%#v\n", nc.GlobalInt("global-bips")) + fmt.Printf("%#v\n", nc.GlobalIntSlice("global-blups")) + fmt.Printf("%#v\n", nc.GlobalString("global-snurt")) + fmt.Printf("%#v\n", nc.GlobalStringSlice("global-snurkles")) + + fmt.Printf("%#v\n", nc.FlagNames()) + fmt.Printf("%#v\n", nc.GlobalFlagNames()) + fmt.Printf("%#v\n", nc.GlobalIsSet("wat")) + fmt.Printf("%#v\n", nc.GlobalSet("wat", "nope")) + fmt.Printf("%#v\n", nc.NArg()) + fmt.Printf("%#v\n", nc.NumFlags()) + fmt.Printf("%#v\n", nc.Parent()) + + nc.Set("wat", "also-nope") + + ec := cli.NewExitError("ohwell", 86) + fmt.Fprintf(c.App.Writer, "%d", ec.ExitCode()) + fmt.Printf("made it!\n") + return ec + } + + if os.Getenv("HEXY") != "" { + app.Writer = &hexWriter{} + app.ErrWriter = &hexWriter{} + } + + app.Metadata = map[string]interface{}{ + "layers": "many", + "explicable": false, + "whatever-values": 19.99, + } + + app.Run(os.Args) +} + +func wopAction(c *cli.Context) error { + fmt.Fprintf(c.App.Writer, ":wave: over here, eh\n") + return nil +} +``` + +## Contribution Guidelines + +Feel free to put up a pull request to fix a bug or maybe add a feature. I will +give it a code review and make sure that it does not break backwards +compatibility. If I or any other collaborators agree that it is in line with +the vision of the project, we will work with you to get the code into +a mergeable state and merge it into the master branch. + +If you have contributed something significant to the project, we will most +likely add you as a collaborator. As a collaborator you are given the ability +to merge others pull requests. It is very important that new code does not +break existing code, so be careful about what code you do choose to merge. + +If you feel like you have contributed to the project but have not yet been +added as a collaborator, we probably forgot to add you, please open an issue. diff --git a/vendor/github.com/urfave/cli/appveyor.yml b/vendor/github.com/urfave/cli/appveyor.yml new file mode 100644 index 0000000000..698b188e12 --- /dev/null +++ b/vendor/github.com/urfave/cli/appveyor.yml @@ -0,0 +1,24 @@ +version: "{build}" + +os: Windows Server 2012 R2 + +clone_folder: c:\gopath\src\github.com\urfave\cli + +environment: + GOPATH: C:\gopath + GOVERSION: 1.6 + PYTHON: C:\Python27-x64 + PYTHON_VERSION: 2.7.x + PYTHON_ARCH: 64 + +install: +- set PATH=%GOPATH%\bin;C:\go\bin;%PATH% +- go version +- go env +- go get github.com/urfave/gfmrun/... +- go get -v -t ./... + +build_script: +- python runtests vet +- python runtests test +- python runtests gfmrun diff --git a/vendor/github.com/urfave/cli/flag-types.json b/vendor/github.com/urfave/cli/flag-types.json new file mode 100644 index 0000000000..1223107859 --- /dev/null +++ b/vendor/github.com/urfave/cli/flag-types.json @@ -0,0 +1,93 @@ +[ + { + "name": "Bool", + "type": "bool", + "value": false, + "context_default": "false", + "parser": "strconv.ParseBool(f.Value.String())" + }, + { + "name": "BoolT", + "type": "bool", + "value": false, + "doctail": " that is true by default", + "context_default": "false", + "parser": "strconv.ParseBool(f.Value.String())" + }, + { + "name": "Duration", + "type": "time.Duration", + "doctail": " (see https://golang.org/pkg/time/#ParseDuration)", + "context_default": "0", + "parser": "time.ParseDuration(f.Value.String())" + }, + { + "name": "Float64", + "type": "float64", + "context_default": "0", + "parser": "strconv.ParseFloat(f.Value.String(), 64)" + }, + { + "name": "Generic", + "type": "Generic", + "dest": false, + "context_default": "nil", + "context_type": "interface{}" + }, + { + "name": "Int64", + "type": "int64", + "context_default": "0", + "parser": "strconv.ParseInt(f.Value.String(), 0, 64)" + }, + { + "name": "Int", + "type": "int", + "context_default": "0", + "parser": "strconv.ParseInt(f.Value.String(), 0, 64)", + "parser_cast": "int(parsed)" + }, + { + "name": "IntSlice", + "type": "*IntSlice", + "dest": false, + "context_default": "nil", + "context_type": "[]int", + "parser": "(f.Value.(*IntSlice)).Value(), error(nil)" + }, + { + "name": "Int64Slice", + "type": "*Int64Slice", + "dest": false, + "context_default": "nil", + "context_type": "[]int64", + "parser": "(f.Value.(*Int64Slice)).Value(), error(nil)" + }, + { + "name": "String", + "type": "string", + "context_default": "\"\"", + "parser": "f.Value.String(), error(nil)" + }, + { + "name": "StringSlice", + "type": "*StringSlice", + "dest": false, + "context_default": "nil", + "context_type": "[]string", + "parser": "(f.Value.(*StringSlice)).Value(), error(nil)" + }, + { + "name": "Uint64", + "type": "uint64", + "context_default": "0", + "parser": "strconv.ParseUint(f.Value.String(), 0, 64)" + }, + { + "name": "Uint", + "type": "uint", + "context_default": "0", + "parser": "strconv.ParseUint(f.Value.String(), 0, 64)", + "parser_cast": "uint(parsed)" + } +] diff --git a/vendor/github.com/urfave/cli/generate-flag-types b/vendor/github.com/urfave/cli/generate-flag-types new file mode 100644 index 0000000000..47a168be6f --- /dev/null +++ b/vendor/github.com/urfave/cli/generate-flag-types @@ -0,0 +1,248 @@ +#!/usr/bin/env python +""" +The flag types that ship with the cli library have many things in common, and +so we can take advantage of the `go generate` command to create much of the +source code from a list of definitions. These definitions attempt to cover +the parts that vary between flag types, and should evolve as needed. + +An example of the minimum definition needed is: + + { + "name": "SomeType", + "type": "sometype", + "context_default": "nil" + } + +In this example, the code generated for the `cli` package will include a type +named `SomeTypeFlag` that is expected to wrap a value of type `sometype`. +Fetching values by name via `*cli.Context` will default to a value of `nil`. + +A more complete, albeit somewhat redundant, example showing all available +definition keys is: + + { + "name": "VeryMuchType", + "type": "*VeryMuchType", + "value": true, + "dest": false, + "doctail": " which really only wraps a []float64, oh well!", + "context_type": "[]float64", + "context_default": "nil", + "parser": "parseVeryMuchType(f.Value.String())", + "parser_cast": "[]float64(parsed)" + } + +The meaning of each field is as follows: + + name (string) - The type "name", which will be suffixed with + `Flag` when generating the type definition + for `cli` and the wrapper type for `altsrc` + type (string) - The type that the generated `Flag` type for `cli` + is expected to "contain" as its `.Value` member + value (bool) - Should the generated `cli` type have a `Value` + member? + dest (bool) - Should the generated `cli` type support a + destination pointer? + doctail (string) - Additional docs for the `cli` flag type comment + context_type (string) - The literal type used in the `*cli.Context` + reader func signature + context_default (string) - The literal value used as the default by the + `*cli.Context` reader funcs when no value is + present + parser (string) - Literal code used to parse the flag `f`, + expected to have a return signature of + (value, error) + parser_cast (string) - Literal code used to cast the `parsed` value + returned from the `parser` code +""" + +from __future__ import print_function, unicode_literals + +import argparse +import json +import os +import subprocess +import sys +import tempfile +import textwrap + + +class _FancyFormatter(argparse.ArgumentDefaultsHelpFormatter, + argparse.RawDescriptionHelpFormatter): + pass + + +def main(sysargs=sys.argv[:]): + parser = argparse.ArgumentParser( + description='Generate flag type code!', + formatter_class=_FancyFormatter) + parser.add_argument( + 'package', + type=str, default='cli', choices=_WRITEFUNCS.keys(), + help='Package for which flag types will be generated' + ) + parser.add_argument( + '-i', '--in-json', + type=argparse.FileType('r'), + default=sys.stdin, + help='Input JSON file which defines each type to be generated' + ) + parser.add_argument( + '-o', '--out-go', + type=argparse.FileType('w'), + default=sys.stdout, + help='Output file/stream to which generated source will be written' + ) + parser.epilog = __doc__ + + args = parser.parse_args(sysargs[1:]) + _generate_flag_types(_WRITEFUNCS[args.package], args.out_go, args.in_json) + return 0 + + +def _generate_flag_types(writefunc, output_go, input_json): + types = json.load(input_json) + + tmp = tempfile.NamedTemporaryFile(suffix='.go', delete=False) + writefunc(tmp, types) + tmp.close() + + new_content = subprocess.check_output( + ['goimports', tmp.name] + ).decode('utf-8') + + print(new_content, file=output_go, end='') + output_go.flush() + os.remove(tmp.name) + + +def _set_typedef_defaults(typedef): + typedef.setdefault('doctail', '') + typedef.setdefault('context_type', typedef['type']) + typedef.setdefault('dest', True) + typedef.setdefault('value', True) + typedef.setdefault('parser', 'f.Value, error(nil)') + typedef.setdefault('parser_cast', 'parsed') + + +def _write_cli_flag_types(outfile, types): + _fwrite(outfile, """\ + package cli + + // WARNING: This file is generated! + + """) + + for typedef in types: + _set_typedef_defaults(typedef) + + _fwrite(outfile, """\ + // {name}Flag is a flag with type {type}{doctail} + type {name}Flag struct {{ + Name string + Usage string + EnvVar string + Hidden bool + """.format(**typedef)) + + if typedef['value']: + _fwrite(outfile, """\ + Value {type} + """.format(**typedef)) + + if typedef['dest']: + _fwrite(outfile, """\ + Destination *{type} + """.format(**typedef)) + + _fwrite(outfile, "\n}\n\n") + + _fwrite(outfile, """\ + // String returns a readable representation of this value + // (for usage defaults) + func (f {name}Flag) String() string {{ + return FlagStringer(f) + }} + + // GetName returns the name of the flag + func (f {name}Flag) GetName() string {{ + return f.Name + }} + + // {name} looks up the value of a local {name}Flag, returns + // {context_default} if not found + func (c *Context) {name}(name string) {context_type} {{ + return lookup{name}(name, c.flagSet) + }} + + // Global{name} looks up the value of a global {name}Flag, returns + // {context_default} if not found + func (c *Context) Global{name}(name string) {context_type} {{ + if fs := lookupGlobalFlagSet(name, c); fs != nil {{ + return lookup{name}(name, fs) + }} + return {context_default} + }} + + func lookup{name}(name string, set *flag.FlagSet) {context_type} {{ + f := set.Lookup(name) + if f != nil {{ + parsed, err := {parser} + if err != nil {{ + return {context_default} + }} + return {parser_cast} + }} + return {context_default} + }} + """.format(**typedef)) + + +def _write_altsrc_flag_types(outfile, types): + _fwrite(outfile, """\ + package altsrc + + import ( + "gopkg.in/urfave/cli.v1" + ) + + // WARNING: This file is generated! + + """) + + for typedef in types: + _set_typedef_defaults(typedef) + + _fwrite(outfile, """\ + // {name}Flag is the flag type that wraps cli.{name}Flag to allow + // for other values to be specified + type {name}Flag struct {{ + cli.{name}Flag + set *flag.FlagSet + }} + + // New{name}Flag creates a new {name}Flag + func New{name}Flag(fl cli.{name}Flag) *{name}Flag {{ + return &{name}Flag{{{name}Flag: fl, set: nil}} + }} + + // Apply saves the flagSet for later usage calls, then calls the + // wrapped {name}Flag.Apply + func (f *{name}Flag) Apply(set *flag.FlagSet) {{ + f.set = set + f.{name}Flag.Apply(set) + }} + """.format(**typedef)) + + +def _fwrite(outfile, text): + print(textwrap.dedent(text), end='', file=outfile) + + +_WRITEFUNCS = { + 'cli': _write_cli_flag_types, + 'altsrc': _write_altsrc_flag_types +} + +if __name__ == '__main__': + sys.exit(main()) diff --git a/vendor/github.com/urfave/cli/runtests b/vendor/github.com/urfave/cli/runtests new file mode 100644 index 0000000000..ee22bdeed5 --- /dev/null +++ b/vendor/github.com/urfave/cli/runtests @@ -0,0 +1,122 @@ +#!/usr/bin/env python +from __future__ import print_function + +import argparse +import os +import sys +import tempfile + +from subprocess import check_call, check_output + + +PACKAGE_NAME = os.environ.get( + 'CLI_PACKAGE_NAME', 'github.com/urfave/cli' +) + + +def main(sysargs=sys.argv[:]): + targets = { + 'vet': _vet, + 'test': _test, + 'gfmrun': _gfmrun, + 'toc': _toc, + 'gen': _gen, + } + + parser = argparse.ArgumentParser() + parser.add_argument( + 'target', nargs='?', choices=tuple(targets.keys()), default='test' + ) + args = parser.parse_args(sysargs[1:]) + + targets[args.target]() + return 0 + + +def _test(): + if check_output('go version'.split()).split()[2] < 'go1.2': + _run('go test -v .') + return + + coverprofiles = [] + for subpackage in ['', 'altsrc']: + coverprofile = 'cli.coverprofile' + if subpackage != '': + coverprofile = '{}.coverprofile'.format(subpackage) + + coverprofiles.append(coverprofile) + + _run('go test -v'.split() + [ + '-coverprofile={}'.format(coverprofile), + ('{}/{}'.format(PACKAGE_NAME, subpackage)).rstrip('/') + ]) + + combined_name = _combine_coverprofiles(coverprofiles) + _run('go tool cover -func={}'.format(combined_name)) + os.remove(combined_name) + + +def _gfmrun(): + go_version = check_output('go version'.split()).split()[2] + if go_version < 'go1.3': + print('runtests: skip on {}'.format(go_version), file=sys.stderr) + return + _run(['gfmrun', '-c', str(_gfmrun_count()), '-s', 'README.md']) + + +def _vet(): + _run('go vet ./...') + + +def _toc(): + _run('node_modules/.bin/markdown-toc -i README.md') + _run('git diff --exit-code') + + +def _gen(): + go_version = check_output('go version'.split()).split()[2] + if go_version < 'go1.5': + print('runtests: skip on {}'.format(go_version), file=sys.stderr) + return + + _run('go generate ./...') + _run('git diff --exit-code') + + +def _run(command): + if hasattr(command, 'split'): + command = command.split() + print('runtests: {}'.format(' '.join(command)), file=sys.stderr) + check_call(command) + + +def _gfmrun_count(): + with open('README.md') as infile: + lines = infile.read().splitlines() + return len(filter(_is_go_runnable, lines)) + + +def _is_go_runnable(line): + return line.startswith('package main') + + +def _combine_coverprofiles(coverprofiles): + combined = tempfile.NamedTemporaryFile( + suffix='.coverprofile', delete=False + ) + combined.write('mode: set\n') + + for coverprofile in coverprofiles: + with open(coverprofile, 'r') as infile: + for line in infile.readlines(): + if not line.startswith('mode: '): + combined.write(line) + + combined.flush() + name = combined.name + combined.close() + return name + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/vendor/github.com/willf/bitset/.gitignore b/vendor/github.com/willf/bitset/.gitignore new file mode 100644 index 0000000000..5c204d28b0 --- /dev/null +++ b/vendor/github.com/willf/bitset/.gitignore @@ -0,0 +1,26 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +target diff --git a/vendor/github.com/willf/bitset/.travis.yml b/vendor/github.com/willf/bitset/.travis.yml new file mode 100644 index 0000000000..9413dc497a --- /dev/null +++ b/vendor/github.com/willf/bitset/.travis.yml @@ -0,0 +1,38 @@ +language: go + +sudo: false + +branches: + except: + - release + +branches: + only: + - master + - travis + +go: + - 1.8 + - 1.9 + - tip + +matrix: + allow_failures: + - go: tip + +before_install: + - if [ -n "$GH_USER" ]; then git config --global github.user ${GH_USER}; fi; + - if [ -n "$GH_TOKEN" ]; then git config --global github.token ${GH_TOKEN}; fi; + - go get github.com/mattn/goveralls + +before_script: + - make deps + +script: + - make qa + +after_failure: + - cat ./target/test/report.xml + +after_success: + - if [ "$TRAVIS_GO_VERSION" = "1.8" ]; then $HOME/gopath/bin/goveralls -covermode=count -coverprofile=target/report/coverage.out -service=travis-ci; fi; diff --git a/vendor/github.com/willf/bitset/Makefile b/vendor/github.com/willf/bitset/Makefile new file mode 100644 index 0000000000..e3fd5479d2 --- /dev/null +++ b/vendor/github.com/willf/bitset/Makefile @@ -0,0 +1,197 @@ +# MAKEFILE +# +# @author Nicola Asuni +# @link https://github.com/willf/bitset +# ------------------------------------------------------------------------------ + +# List special make targets that are not associated with files +.PHONY: help all test format fmtcheck vet lint coverage cyclo ineffassign misspell structcheck varcheck errcheck gosimple astscan qa deps clean nuke + +# Use bash as shell (Note: Ubuntu now uses dash which doesn't support PIPESTATUS). +SHELL=/bin/bash + +# CVS path (path to the parent dir containing the project) +CVSPATH=github.com/willf + +# Project owner +OWNER=willf + +# Project vendor +VENDOR=willf + +# Project name +PROJECT=bitset + +# Project version +VERSION=$(shell cat VERSION) + +# Name of RPM or DEB package +PKGNAME=${VENDOR}-${PROJECT} + +# Current directory +CURRENTDIR=$(shell pwd) + +# GO lang path +ifneq ($(GOPATH),) + ifeq ($(findstring $(GOPATH),$(CURRENTDIR)),) + # the defined GOPATH is not valid + GOPATH= + endif +endif +ifeq ($(GOPATH),) + # extract the GOPATH + GOPATH=$(firstword $(subst /src/, ,$(CURRENTDIR))) +endif + +# --- MAKE TARGETS --- + +# Display general help about this command +help: + @echo "" + @echo "$(PROJECT) Makefile." + @echo "GOPATH=$(GOPATH)" + @echo "The following commands are available:" + @echo "" + @echo " make qa : Run all the tests" + @echo " make test : Run the unit tests" + @echo "" + @echo " make format : Format the source code" + @echo " make fmtcheck : Check if the source code has been formatted" + @echo " make vet : Check for suspicious constructs" + @echo " make lint : Check for style errors" + @echo " make coverage : Generate the coverage report" + @echo " make cyclo : Generate the cyclomatic complexity report" + @echo " make ineffassign : Detect ineffectual assignments" + @echo " make misspell : Detect commonly misspelled words in source files" + @echo " make structcheck : Find unused struct fields" + @echo " make varcheck : Find unused global variables and constants" + @echo " make errcheck : Check that error return values are used" + @echo " make gosimple : Suggest code simplifications" + @echo " make astscan : GO AST scanner" + @echo "" + @echo " make docs : Generate source code documentation" + @echo "" + @echo " make deps : Get the dependencies" + @echo " make clean : Remove any build artifact" + @echo " make nuke : Deletes any intermediate file" + @echo "" + +# Alias for help target +all: help + +# Run the unit tests +test: + @mkdir -p target/test + @mkdir -p target/report + GOPATH=$(GOPATH) \ + go test \ + -covermode=atomic \ + -bench=. \ + -race \ + -cpuprofile=target/report/cpu.out \ + -memprofile=target/report/mem.out \ + -mutexprofile=target/report/mutex.out \ + -coverprofile=target/report/coverage.out \ + -v ./... | \ + tee >(PATH=$(GOPATH)/bin:$(PATH) go-junit-report > target/test/report.xml); \ + test $${PIPESTATUS[0]} -eq 0 + +# Format the source code +format: + @find . -type f -name "*.go" -exec gofmt -s -w {} \; + +# Check if the source code has been formatted +fmtcheck: + @mkdir -p target + @find . -type f -name "*.go" -exec gofmt -s -d {} \; | tee target/format.diff + @test ! -s target/format.diff || { echo "ERROR: the source code has not been formatted - please use 'make format' or 'gofmt'"; exit 1; } + +# Check for syntax errors +vet: + GOPATH=$(GOPATH) go vet . + +# Check for style errors +lint: + GOPATH=$(GOPATH) PATH=$(GOPATH)/bin:$(PATH) golint . + +# Generate the coverage report +coverage: + @mkdir -p target/report + GOPATH=$(GOPATH) \ + go tool cover -html=target/report/coverage.out -o target/report/coverage.html + +# Report cyclomatic complexity +cyclo: + @mkdir -p target/report + GOPATH=$(GOPATH) gocyclo -avg ./ | tee target/report/cyclo.txt ; test $${PIPESTATUS[0]} -eq 0 + +# Detect ineffectual assignments +ineffassign: + @mkdir -p target/report + GOPATH=$(GOPATH) ineffassign ./ | tee target/report/ineffassign.txt ; test $${PIPESTATUS[0]} -eq 0 + +# Detect commonly misspelled words in source files +misspell: + @mkdir -p target/report + GOPATH=$(GOPATH) misspell -error ./ | tee target/report/misspell.txt ; test $${PIPESTATUS[0]} -eq 0 + +# Find unused struct fields +structcheck: + @mkdir -p target/report + GOPATH=$(GOPATH) structcheck -a ./ | tee target/report/structcheck.txt + +# Find unused global variables and constants +varcheck: + @mkdir -p target/report + GOPATH=$(GOPATH) varcheck -e ./ | tee target/report/varcheck.txt + +# Check that error return values are used +errcheck: + @mkdir -p target/report + GOPATH=$(GOPATH) errcheck ./ | tee target/report/errcheck.txt + +# Suggest code simplifications +gosimple: + @mkdir -p target/report + GOPATH=$(GOPATH) gosimple ./ | tee target/report/gosimple.txt + +# AST scanner +astscan: + @mkdir -p target/report + GOPATH=$(GOPATH) gas .//*.go | tee target/report/astscan.txt ; test $${PIPESTATUS[0]} -eq 0 + +# Generate source docs +docs: + @mkdir -p target/docs + nohup sh -c 'GOPATH=$(GOPATH) godoc -http=127.0.0.1:6060' > target/godoc_server.log 2>&1 & + wget --directory-prefix=target/docs/ --execute robots=off --retry-connrefused --recursive --no-parent --adjust-extension --page-requisites --convert-links http://127.0.0.1:6060/pkg/github.com/${VENDOR}/${PROJECT}/ ; kill -9 `lsof -ti :6060` + @echo ''${PKGNAME}' Documentation ...' > target/docs/index.html + +# Alias to run all quality-assurance checks +qa: fmtcheck test vet lint coverage cyclo ineffassign misspell structcheck varcheck errcheck gosimple + +# --- INSTALL --- + +# Get the dependencies +deps: + GOPATH=$(GOPATH) go get ./... + GOPATH=$(GOPATH) go get github.com/golang/lint/golint + GOPATH=$(GOPATH) go get github.com/jstemmer/go-junit-report + GOPATH=$(GOPATH) go get github.com/axw/gocov/gocov + GOPATH=$(GOPATH) go get github.com/fzipp/gocyclo + GOPATH=$(GOPATH) go get github.com/gordonklaus/ineffassign + GOPATH=$(GOPATH) go get github.com/client9/misspell/cmd/misspell + GOPATH=$(GOPATH) go get github.com/opennota/check/cmd/structcheck + GOPATH=$(GOPATH) go get github.com/opennota/check/cmd/varcheck + GOPATH=$(GOPATH) go get github.com/kisielk/errcheck + GOPATH=$(GOPATH) go get honnef.co/go/tools/cmd/gosimple + GOPATH=$(GOPATH) go get github.com/GoASTScanner/gas + +# Remove any build artifact +clean: + GOPATH=$(GOPATH) go clean ./... + +# Deletes any intermediate file +nuke: + rm -rf ./target + GOPATH=$(GOPATH) go clean -i ./... diff --git a/vendor/github.com/willf/bitset/README.md b/vendor/github.com/willf/bitset/README.md new file mode 100644 index 0000000000..6c62b20c6c --- /dev/null +++ b/vendor/github.com/willf/bitset/README.md @@ -0,0 +1,96 @@ +# bitset + +*Go language library to map between non-negative integers and boolean values* + +[![Master Build Status](https://secure.travis-ci.org/willf/bitset.png?branch=master)](https://travis-ci.org/willf/bitset?branch=master) +[![Master Coverage Status](https://coveralls.io/repos/willf/bitset/badge.svg?branch=master&service=github)](https://coveralls.io/github/willf/bitset?branch=master) +[![Go Report Card](https://goreportcard.com/badge/github.com/willf/bitset)](https://goreportcard.com/report/github.com/willf/bitset) +[![GoDoc](https://godoc.org/github.com/willf/bitset?status.svg)](http://godoc.org/github.com/willf/bitset) + + +## Description + +Package bitset implements bitsets, a mapping between non-negative integers and boolean values. +It should be more efficient than map[uint] bool. + +It provides methods for setting, clearing, flipping, and testing individual integers. + +But it also provides set intersection, union, difference, complement, and symmetric operations, as well as tests to check whether any, all, or no bits are set, and querying a bitset's current length and number of positive bits. + +BitSets are expanded to the size of the largest set bit; the memory allocation is approximately Max bits, where Max is the largest set bit. BitSets are never shrunk. On creation, a hint can be given for the number of bits that will be used. + +Many of the methods, including Set, Clear, and Flip, return a BitSet pointer, which allows for chaining. + +### Example use: + +```go +package main + +import ( + "fmt" + "math/rand" + + "github.com/willf/bitset" +) + +func main() { + fmt.Printf("Hello from BitSet!\n") + var b bitset.BitSet + // play some Go Fish + for i := 0; i < 100; i++ { + card1 := uint(rand.Intn(52)) + card2 := uint(rand.Intn(52)) + b.Set(card1) + if b.Test(card2) { + fmt.Println("Go Fish!") + } + b.Clear(card1) + } + + // Chaining + b.Set(10).Set(11) + + for i, e := b.NextSet(0); e; i, e = b.NextSet(i + 1) { + fmt.Println("The following bit is set:", i) + } + if b.Intersection(bitset.New(100).Set(10)).Count() == 1 { + fmt.Println("Intersection works.") + } else { + fmt.Println("Intersection doesn't work???") + } +} +``` + +As an alternative to BitSets, one should check out the 'big' package, which provides a (less set-theoretical) view of bitsets. + +Godoc documentation is at: https://godoc.org/github.com/willf/bitset + + +## Implementation Note + +Go 1.9 introduced a native `math/bits` library. We provide backward compatibility to Go 1.7, which might be removed. + +It is possible that a later version will match the `math/bits` return signature for counts (which is `int`, rather than our library's `unit64`). If so, the version will be bumped. + +## Installation + +```bash +go get github.com/willf/bitset +``` + +## Contributing + +If you wish to contribute to this project, please branch and issue a pull request against master ("[GitHub Flow](https://guides.github.com/introduction/flow/)") + +This project include a Makefile that allows you to test and build the project with simple commands. +To see all available options: +```bash +make help +``` + +## Running all tests + +Before committing the code, please check if it passes all tests using (note: this will install some dependencies): +```bash +make qa +``` diff --git a/vendor/github.com/willf/bitset/VERSION b/vendor/github.com/willf/bitset/VERSION new file mode 100644 index 0000000000..781dcb07cd --- /dev/null +++ b/vendor/github.com/willf/bitset/VERSION @@ -0,0 +1 @@ +1.1.3 diff --git a/vendor/github.com/xanzy/ssh-agent/.gitignore b/vendor/github.com/xanzy/ssh-agent/.gitignore new file mode 100644 index 0000000000..daf913b1b3 --- /dev/null +++ b/vendor/github.com/xanzy/ssh-agent/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/xanzy/ssh-agent/README.md b/vendor/github.com/xanzy/ssh-agent/README.md new file mode 100644 index 0000000000..d93af40a0c --- /dev/null +++ b/vendor/github.com/xanzy/ssh-agent/README.md @@ -0,0 +1,23 @@ +# ssh-agent + +Create a new [agent.Agent](https://godoc.org/golang.org/x/crypto/ssh/agent#Agent) on any type of OS (so including Windows) from any [Go](https://golang.org) application. + +## Limitations + +When compiled for Windows, it will only support [Pageant](http://the.earth.li/~sgtatham/putty/0.66/htmldoc/Chapter9.html#pageant) as the SSH authentication agent. + +## Credits + +Big thanks to [Давид Мзареулян (David Mzareulyan)](https://github.com/davidmz) for creating the [go-pageant](https://github.com/davidmz/go-pageant) package! + +## Issues + +If you have an issue: report it on the [issue tracker](https://github.com/xanzy/ssh-agent/issues) + +## Author + +Sander van Harmelen () + +## License + +The files `pageant_windows.go` and `sshagent_windows.go` have their own license (see file headers). The rest of this package is licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at diff --git a/vendor/github.com/yohcop/openid-go/.travis.yml b/vendor/github.com/yohcop/openid-go/.travis.yml new file mode 100644 index 0000000000..e0937781cd --- /dev/null +++ b/vendor/github.com/yohcop/openid-go/.travis.yml @@ -0,0 +1,14 @@ +sudo: false + +language: go + +go: + - 1.3.3 + - 1.4.2 + - 1.5.2 + - 1.6beta2 + +# Get deps, build, test, and ensure the code is gofmt'ed. +script: + - go test -v ./... + - diff <(gofmt -d .) <("") diff --git a/vendor/github.com/yohcop/openid-go/README.md b/vendor/github.com/yohcop/openid-go/README.md new file mode 100644 index 0000000000..f617126d2e --- /dev/null +++ b/vendor/github.com/yohcop/openid-go/README.md @@ -0,0 +1,38 @@ +# openid.go + +This is a consumer (Relying party) implementation of OpenId 2.0, +written in Go. + + go get -u github.com/yohcop/openid-go + +[![Build Status](https://travis-ci.org/yohcop/openid-go.svg?branch=master)](https://travis-ci.org/yohcop/openid-go) + +## Github + +Be awesome! Feel free to clone and use according to the licence. +If you make a useful change that can benefit others, send a +pull request! This ensures that one version has all the good stuff +and doesn't fall behind. + +## Code example + +See `_example/` for a simple webserver using the openID +implementation. Also, read the comment about the NonceStore towards +the top of that file. The example must be run for the openid-go +directory, like so: + + go run _example/server.go + +## App Engine + +In order to use this on Google App Engine, you need to create an instance with a custom `*http.Client` provided by [urlfetch](https://cloud.google.com/appengine/docs/go/urlfetch/). + +```go +oid := openid.NewOpenID(urlfetch.Client(appengine.NewContext(r))) +oid.RedirectURL(...) +oid.Verify(...) +``` + +## License + +Distributed under the [Apache v2.0 license](http://www.apache.org/licenses/LICENSE-2.0.html). diff --git a/vendor/golang.org/x/crypto/acme/acme.go b/vendor/golang.org/x/crypto/acme/acme.go index 1f4fb69edd..7df6476412 100644 --- a/vendor/golang.org/x/crypto/acme/acme.go +++ b/vendor/golang.org/x/crypto/acme/acme.go @@ -14,7 +14,6 @@ package acme import ( - "bytes" "context" "crypto" "crypto/ecdsa" @@ -23,6 +22,8 @@ import ( "crypto/sha256" "crypto/tls" "crypto/x509" + "crypto/x509/pkix" + "encoding/asn1" "encoding/base64" "encoding/hex" "encoding/json" @@ -33,14 +34,26 @@ import ( "io/ioutil" "math/big" "net/http" - "strconv" "strings" "sync" "time" ) -// LetsEncryptURL is the Directory endpoint of Let's Encrypt CA. -const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory" +const ( + // LetsEncryptURL is the Directory endpoint of Let's Encrypt CA. + LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory" + + // ALPNProto is the ALPN protocol name used by a CA server when validating + // tls-alpn-01 challenges. + // + // Package users must ensure their servers can negotiate the ACME ALPN in + // order for tls-alpn-01 challenge verifications to succeed. + // See the crypto/tls package's Config.NextProtos field. + ALPNProto = "acme-tls/1" +) + +// idPeACMEIdentifierV1 is the OID for the ACME extension for the TLS-ALPN challenge. +var idPeACMEIdentifierV1 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 30, 1} const ( maxChainLen = 5 // max depth and breadth of a certificate chain @@ -76,6 +89,22 @@ type Client struct { // will have no effect. DirectoryURL string + // RetryBackoff computes the duration after which the nth retry of a failed request + // should occur. The value of n for the first call on failure is 1. + // The values of r and resp are the request and response of the last failed attempt. + // If the returned value is negative or zero, no more retries are done and an error + // is returned to the caller of the original method. + // + // Requests which result in a 4xx client error are not retried, + // except for 400 Bad Request due to "bad nonce" errors and 429 Too Many Requests. + // + // If RetryBackoff is nil, a truncated exponential backoff algorithm + // with the ceiling of 10 seconds is used, where each subsequent retry n + // is done after either ("Retry-After" + jitter) or (2^n seconds + jitter), + // preferring the former if "Retry-After" header is found in the resp. + // The jitter is a random value up to 1 second. + RetryBackoff func(n int, r *http.Request, resp *http.Response) time.Duration + dirMu sync.Mutex // guards writes to dir dir *Directory // cached result of Client's Discover method @@ -99,15 +128,12 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) { if dirURL == "" { dirURL = LetsEncryptURL } - res, err := c.get(ctx, dirURL) + res, err := c.get(ctx, dirURL, wantStatus(http.StatusOK)) if err != nil { return Directory{}, err } defer res.Body.Close() c.addNonce(res.Header) - if res.StatusCode != http.StatusOK { - return Directory{}, responseError(res) - } var v struct { Reg string `json:"new-reg"` @@ -166,14 +192,11 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, req.NotAfter = now.Add(exp).Format(time.RFC3339) } - res, err := c.retryPostJWS(ctx, c.Key, c.dir.CertURL, req) + res, err := c.post(ctx, c.Key, c.dir.CertURL, req, wantStatus(http.StatusCreated)) if err != nil { return nil, "", err } defer res.Body.Close() - if res.StatusCode != http.StatusCreated { - return nil, "", responseError(res) - } curl := res.Header.Get("Location") // cert permanent URL if res.ContentLength == 0 { @@ -196,26 +219,11 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, // Callers are encouraged to parse the returned value to ensure the certificate is valid // and has expected features. func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) { - for { - res, err := c.get(ctx, url) - if err != nil { - return nil, err - } - defer res.Body.Close() - if res.StatusCode == http.StatusOK { - return c.responseCert(ctx, res, bundle) - } - if res.StatusCode > 299 { - return nil, responseError(res) - } - d := retryAfter(res.Header.Get("Retry-After"), 3*time.Second) - select { - case <-time.After(d): - // retry - case <-ctx.Done(): - return nil, ctx.Err() - } + res, err := c.get(ctx, url, wantStatus(http.StatusOK)) + if err != nil { + return nil, err } + return c.responseCert(ctx, res, bundle) } // RevokeCert revokes a previously issued certificate cert, provided in DER format. @@ -241,14 +249,11 @@ func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, if key == nil { key = c.Key } - res, err := c.retryPostJWS(ctx, key, c.dir.RevokeURL, body) + res, err := c.post(ctx, key, c.dir.RevokeURL, body, wantStatus(http.StatusOK)) if err != nil { return err } defer res.Body.Close() - if res.StatusCode != http.StatusOK { - return responseError(res) - } return nil } @@ -329,14 +334,11 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, Resource: "new-authz", Identifier: authzID{Type: "dns", Value: domain}, } - res, err := c.retryPostJWS(ctx, c.Key, c.dir.AuthzURL, req) + res, err := c.post(ctx, c.Key, c.dir.AuthzURL, req, wantStatus(http.StatusCreated)) if err != nil { return nil, err } defer res.Body.Close() - if res.StatusCode != http.StatusCreated { - return nil, responseError(res) - } var v wireAuthz if err := json.NewDecoder(res.Body).Decode(&v); err != nil { @@ -353,14 +355,11 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, // If a caller needs to poll an authorization until its status is final, // see the WaitAuthorization method. func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) { - res, err := c.get(ctx, url) + res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) if err != nil { return nil, err } defer res.Body.Close() - if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted { - return nil, responseError(res) - } var v wireAuthz if err := json.NewDecoder(res.Body).Decode(&v); err != nil { return nil, fmt.Errorf("acme: invalid response: %v", err) @@ -387,14 +386,11 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error { Status: "deactivated", Delete: true, } - res, err := c.retryPostJWS(ctx, c.Key, url, req) + res, err := c.post(ctx, c.Key, url, req, wantStatus(http.StatusOK)) if err != nil { return err } defer res.Body.Close() - if res.StatusCode != http.StatusOK { - return responseError(res) - } return nil } @@ -406,44 +402,42 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error { // In all other cases WaitAuthorization returns an error. // If the Status is StatusInvalid, the returned error is of type *AuthorizationError. func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) { - sleep := sleeper(ctx) for { - res, err := c.get(ctx, url) + res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) if err != nil { return nil, err } - if res.StatusCode >= 400 && res.StatusCode <= 499 { - // Non-retriable error. For instance, Let's Encrypt may return 404 Not Found - // when requesting an expired authorization. - defer res.Body.Close() - return nil, responseError(res) - } - retry := res.Header.Get("Retry-After") - if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted { - res.Body.Close() - if err := sleep(retry, 1); err != nil { - return nil, err - } - continue - } var raw wireAuthz err = json.NewDecoder(res.Body).Decode(&raw) res.Body.Close() - if err != nil { - if err := sleep(retry, 0); err != nil { - return nil, err - } - continue - } - if raw.Status == StatusValid { + switch { + case err != nil: + // Skip and retry. + case raw.Status == StatusValid: return raw.authorization(url), nil - } - if raw.Status == StatusInvalid { + case raw.Status == StatusInvalid: return nil, raw.error(url) } - if err := sleep(retry, 0); err != nil { - return nil, err + + // Exponential backoff is implemented in c.get above. + // This is just to prevent continuously hitting the CA + // while waiting for a final authorization status. + d := retryAfter(res.Header.Get("Retry-After")) + if d == 0 { + // Given that the fastest challenges TLS-SNI and HTTP-01 + // require a CA to make at least 1 network round trip + // and most likely persist a challenge state, + // this default delay seems reasonable. + d = time.Second + } + t := time.NewTimer(d) + select { + case <-ctx.Done(): + t.Stop() + return nil, ctx.Err() + case <-t.C: + // Retry. } } } @@ -452,14 +446,11 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat // // A client typically polls a challenge status using this method. func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) { - res, err := c.get(ctx, url) + res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) if err != nil { return nil, err } defer res.Body.Close() - if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted { - return nil, responseError(res) - } v := wireChallenge{URI: url} if err := json.NewDecoder(res.Body).Decode(&v); err != nil { return nil, fmt.Errorf("acme: invalid response: %v", err) @@ -486,16 +477,14 @@ func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error Type: chal.Type, Auth: auth, } - res, err := c.retryPostJWS(ctx, c.Key, chal.URI, req) + res, err := c.post(ctx, c.Key, chal.URI, req, wantStatus( + http.StatusOK, // according to the spec + http.StatusAccepted, // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md) + )) if err != nil { return nil, err } defer res.Body.Close() - // Note: the protocol specifies 200 as the expected response code, but - // letsencrypt seems to be returning 202. - if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted { - return nil, responseError(res) - } var v wireChallenge if err := json.NewDecoder(res.Body).Decode(&v); err != nil { @@ -552,7 +541,7 @@ func (c *Client) HTTP01ChallengePath(token string) string { // If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. // // The returned certificate is valid for the next 24 hours and must be presented only when -// the server name of the client hello matches exactly the returned name value. +// the server name of the TLS ClientHello matches exactly the returned name value. func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { ka, err := keyAuth(c.Key.Public(), token) if err != nil { @@ -579,7 +568,7 @@ func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tl // If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. // // The returned certificate is valid for the next 24 hours and must be presented only when -// the server name in the client hello matches exactly the returned name value. +// the server name in the TLS ClientHello matches exactly the returned name value. func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { b := sha256.Sum256([]byte(token)) h := hex.EncodeToString(b[:]) @@ -600,6 +589,52 @@ func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tl return cert, sanA, nil } +// TLSALPN01ChallengeCert creates a certificate for TLS-ALPN-01 challenge response. +// Servers can present the certificate to validate the challenge and prove control +// over a domain name. For more details on TLS-ALPN-01 see +// https://tools.ietf.org/html/draft-shoemaker-acme-tls-alpn-00#section-3 +// +// The token argument is a Challenge.Token value. +// If a WithKey option is provided, its private part signs the returned cert, +// and the public part is used to specify the signee. +// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. +// +// The returned certificate is valid for the next 24 hours and must be presented only when +// the server name in the TLS ClientHello matches the domain, and the special acme-tls/1 ALPN protocol +// has been specified. +func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) (cert tls.Certificate, err error) { + ka, err := keyAuth(c.Key.Public(), token) + if err != nil { + return tls.Certificate{}, err + } + shasum := sha256.Sum256([]byte(ka)) + extValue, err := asn1.Marshal(shasum[:]) + if err != nil { + return tls.Certificate{}, err + } + acmeExtension := pkix.Extension{ + Id: idPeACMEIdentifierV1, + Critical: true, + Value: extValue, + } + + tmpl := defaultTLSChallengeCertTemplate() + + var newOpt []CertOption + for _, o := range opt { + switch o := o.(type) { + case *certOptTemplate: + t := *(*x509.Certificate)(o) // shallow copy is ok + tmpl = &t + default: + newOpt = append(newOpt, o) + } + } + tmpl.ExtraExtensions = append(tmpl.ExtraExtensions, acmeExtension) + newOpt = append(newOpt, WithTemplate(tmpl)) + return tlsChallengeCert([]string{domain}, newOpt) +} + // doReg sends all types of registration requests. // The type of request is identified by typ argument, which is a "resource" // in the ACME spec terms. @@ -619,14 +654,15 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun req.Contact = acct.Contact req.Agreement = acct.AgreedTerms } - res, err := c.retryPostJWS(ctx, c.Key, url, req) + res, err := c.post(ctx, c.Key, url, req, wantStatus( + http.StatusOK, // updates and deletes + http.StatusCreated, // new account creation + http.StatusAccepted, // Let's Encrypt divergent implementation + )) if err != nil { return nil, err } defer res.Body.Close() - if res.StatusCode < 200 || res.StatusCode > 299 { - return nil, responseError(res) - } var v struct { Contact []string @@ -656,59 +692,6 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun }, nil } -// retryPostJWS will retry calls to postJWS if there is a badNonce error, -// clearing the stored nonces after each error. -// If the response was 4XX-5XX, then responseError is called on the body, -// the body is closed, and the error returned. -func (c *Client) retryPostJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) { - sleep := sleeper(ctx) - for { - res, err := c.postJWS(ctx, key, url, body) - if err != nil { - return nil, err - } - // handle errors 4XX-5XX with responseError - if res.StatusCode >= 400 && res.StatusCode <= 599 { - err := responseError(res) - res.Body.Close() - // according to spec badNonce is urn:ietf:params:acme:error:badNonce - // however, acme servers in the wild return their version of the error - // https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4 - if ae, ok := err.(*Error); ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") { - // clear any nonces that we might've stored that might now be - // considered bad - c.clearNonces() - retry := res.Header.Get("Retry-After") - if err := sleep(retry, 1); err != nil { - return nil, err - } - continue - } - return nil, err - } - return res, nil - } -} - -// postJWS signs the body with the given key and POSTs it to the provided url. -// The body argument must be JSON-serializable. -func (c *Client) postJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) { - nonce, err := c.popNonce(ctx, url) - if err != nil { - return nil, err - } - b, err := jwsEncodeJSON(body, key, nonce) - if err != nil { - return nil, err - } - res, err := c.post(ctx, url, "application/jose+json", bytes.NewReader(b)) - if err != nil { - return nil, err - } - c.addNonce(res.Header) - return res, nil -} - // popNonce returns a nonce value previously stored with c.addNonce // or fetches a fresh one from the given URL. func (c *Client) popNonce(ctx context.Context, url string) (string, error) { @@ -749,58 +732,12 @@ func (c *Client) addNonce(h http.Header) { c.nonces[v] = struct{}{} } -func (c *Client) httpClient() *http.Client { - if c.HTTPClient != nil { - return c.HTTPClient - } - return http.DefaultClient -} - -func (c *Client) get(ctx context.Context, urlStr string) (*http.Response, error) { - req, err := http.NewRequest("GET", urlStr, nil) - if err != nil { - return nil, err - } - return c.do(ctx, req) -} - -func (c *Client) head(ctx context.Context, urlStr string) (*http.Response, error) { - req, err := http.NewRequest("HEAD", urlStr, nil) - if err != nil { - return nil, err - } - return c.do(ctx, req) -} - -func (c *Client) post(ctx context.Context, urlStr, contentType string, body io.Reader) (*http.Response, error) { - req, err := http.NewRequest("POST", urlStr, body) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", contentType) - return c.do(ctx, req) -} - -func (c *Client) do(ctx context.Context, req *http.Request) (*http.Response, error) { - res, err := c.httpClient().Do(req.WithContext(ctx)) - if err != nil { - select { - case <-ctx.Done(): - // Prefer the unadorned context error. - // (The acme package had tests assuming this, previously from ctxhttp's - // behavior, predating net/http supporting contexts natively) - // TODO(bradfitz): reconsider this in the future. But for now this - // requires no test updates. - return nil, ctx.Err() - default: - return nil, err - } - } - return res, nil -} - func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) { - resp, err := c.head(ctx, url) + r, err := http.NewRequest("HEAD", url, nil) + if err != nil { + return "", err + } + resp, err := c.doNoRetry(ctx, r) if err != nil { return "", err } @@ -852,24 +789,6 @@ func (c *Client) responseCert(ctx context.Context, res *http.Response, bundle bo return cert, nil } -// responseError creates an error of Error type from resp. -func responseError(resp *http.Response) error { - // don't care if ReadAll returns an error: - // json.Unmarshal will fail in that case anyway - b, _ := ioutil.ReadAll(resp.Body) - e := &wireError{Status: resp.StatusCode} - if err := json.Unmarshal(b, e); err != nil { - // this is not a regular error response: - // populate detail with anything we received, - // e.Status will already contain HTTP response code value - e.Detail = string(b) - if e.Detail == "" { - e.Detail = resp.Status - } - } - return e.error(resp.Header) -} - // chainCert fetches CA certificate chain recursively by following "up" links. // Each recursive call increments the depth by 1, resulting in an error // if the recursion level reaches maxChainLen. @@ -880,14 +799,11 @@ func (c *Client) chainCert(ctx context.Context, url string, depth int) ([][]byte return nil, errors.New("acme: certificate chain is too deep") } - res, err := c.get(ctx, url) + res, err := c.get(ctx, url, wantStatus(http.StatusOK)) if err != nil { return nil, err } defer res.Body.Close() - if res.StatusCode != http.StatusOK { - return nil, responseError(res) - } b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1)) if err != nil { return nil, err @@ -932,65 +848,6 @@ func linkHeader(h http.Header, rel string) []string { return links } -// sleeper returns a function that accepts the Retry-After HTTP header value -// and an increment that's used with backoff to increasingly sleep on -// consecutive calls until the context is done. If the Retry-After header -// cannot be parsed, then backoff is used with a maximum sleep time of 10 -// seconds. -func sleeper(ctx context.Context) func(ra string, inc int) error { - var count int - return func(ra string, inc int) error { - count += inc - d := backoff(count, 10*time.Second) - d = retryAfter(ra, d) - wakeup := time.NewTimer(d) - defer wakeup.Stop() - select { - case <-ctx.Done(): - return ctx.Err() - case <-wakeup.C: - return nil - } - } -} - -// retryAfter parses a Retry-After HTTP header value, -// trying to convert v into an int (seconds) or use http.ParseTime otherwise. -// It returns d if v cannot be parsed. -func retryAfter(v string, d time.Duration) time.Duration { - if i, err := strconv.Atoi(v); err == nil { - return time.Duration(i) * time.Second - } - t, err := http.ParseTime(v) - if err != nil { - return d - } - return t.Sub(timeNow()) -} - -// backoff computes a duration after which an n+1 retry iteration should occur -// using truncated exponential backoff algorithm. -// -// The n argument is always bounded between 0 and 30. -// The max argument defines upper bound for the returned value. -func backoff(n int, max time.Duration) time.Duration { - if n < 0 { - n = 0 - } - if n > 30 { - n = 30 - } - var d time.Duration - if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil { - d = time.Duration(x.Int64()) * time.Millisecond - } - d += time.Duration(1< max { - return max - } - return d -} - // keyAuth generates a key authorization string for a given token. func keyAuth(pub crypto.PublicKey, token string) (string, error) { th, err := JWKThumbprint(pub) @@ -1000,15 +857,25 @@ func keyAuth(pub crypto.PublicKey, token string) (string, error) { return fmt.Sprintf("%s.%s", token, th), nil } +// defaultTLSChallengeCertTemplate is a template used to create challenge certs for TLS challenges. +func defaultTLSChallengeCertTemplate() *x509.Certificate { + return &x509.Certificate{ + SerialNumber: big.NewInt(1), + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + BasicConstraintsValid: true, + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + } +} + // tlsChallengeCert creates a temporary certificate for TLS-SNI challenges // with the given SANs and auto-generated public/private key pair. // The Subject Common Name is set to the first SAN to aid debugging. // To create a cert with a custom key pair, specify WithKey option. func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { - var ( - key crypto.Signer - tmpl *x509.Certificate - ) + var key crypto.Signer + tmpl := defaultTLSChallengeCertTemplate() for _, o := range opt { switch o := o.(type) { case *certOptKey: @@ -1017,7 +884,7 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { } key = o.key case *certOptTemplate: - var t = *(*x509.Certificate)(o) // shallow copy is ok + t := *(*x509.Certificate)(o) // shallow copy is ok tmpl = &t default: // package's fault, if we let this happen: @@ -1030,16 +897,6 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { return tls.Certificate{}, err } } - if tmpl == nil { - tmpl = &x509.Certificate{ - SerialNumber: big.NewInt(1), - NotBefore: time.Now(), - NotAfter: time.Now().Add(24 * time.Hour), - BasicConstraintsValid: true, - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - } - } tmpl.DNSNames = san if len(san) > 0 { tmpl.Subject.CommonName = san[0] diff --git a/vendor/golang.org/x/crypto/acme/autocert/autocert.go b/vendor/golang.org/x/crypto/acme/autocert/autocert.go index 263b291331..4c2fc07226 100644 --- a/vendor/golang.org/x/crypto/acme/autocert/autocert.go +++ b/vendor/golang.org/x/crypto/acme/autocert/autocert.go @@ -44,7 +44,7 @@ var createCertRetryAfter = time.Minute var pseudoRand *lockedMathRand func init() { - src := mathrand.NewSource(timeNow().UnixNano()) + src := mathrand.NewSource(time.Now().UnixNano()) pseudoRand = &lockedMathRand{rnd: mathrand.New(src)} } @@ -81,9 +81,9 @@ func defaultHostPolicy(context.Context, string) error { } // Manager is a stateful certificate manager built on top of acme.Client. -// It obtains and refreshes certificates automatically using "tls-sni-01", -// "tls-sni-02" and "http-01" challenge types, as well as providing them -// to a TLS server via tls.Config. +// It obtains and refreshes certificates automatically using "tls-alpn-01", +// "tls-sni-01", "tls-sni-02" and "http-01" challenge types, +// as well as providing them to a TLS server via tls.Config. // // You must specify a cache implementation, such as DirCache, // to reuse obtained certificates across program restarts. @@ -98,11 +98,11 @@ type Manager struct { // To always accept the terms, the callers can use AcceptTOS. Prompt func(tosURL string) bool - // Cache optionally stores and retrieves previously-obtained certificates. - // If nil, certs will only be cached for the lifetime of the Manager. + // Cache optionally stores and retrieves previously-obtained certificates + // and other state. If nil, certs will only be cached for the lifetime of + // the Manager. Multiple Managers can share the same Cache. // - // Manager passes the Cache certificates data encoded in PEM, with private/public - // parts combined in a single Cache.Put call, private key first. + // Using a persistent Cache, such as DirCache, is strongly recommended. Cache Cache // HostPolicy controls which domains the Manager will attempt @@ -127,8 +127,10 @@ type Manager struct { // Client is used to perform low-level operations, such as account registration // and requesting new certificates. + // // If Client is nil, a zero-value acme.Client is used with acme.LetsEncryptURL - // directory endpoint and a newly-generated ECDSA P-256 key. + // as directory endpoint. If the Client.Key is nil, a new ECDSA P-256 key is + // generated and, if Cache is not nil, stored in cache. // // Mutating the field after the first call of GetCertificate method will have no effect. Client *acme.Client @@ -140,22 +142,30 @@ type Manager struct { // If the Client's account key is already registered, Email is not used. Email string - // ForceRSA makes the Manager generate certificates with 2048-bit RSA keys. + // ForceRSA used to make the Manager generate RSA certificates. It is now ignored. // - // If false, a default is used. Currently the default - // is EC-based keys using the P-256 curve. + // Deprecated: the Manager will request the correct type of certificate based + // on what each client supports. ForceRSA bool + // ExtraExtensions are used when generating a new CSR (Certificate Request), + // thus allowing customization of the resulting certificate. + // For instance, TLS Feature Extension (RFC 7633) can be used + // to prevent an OCSP downgrade attack. + // + // The field value is passed to crypto/x509.CreateCertificateRequest + // in the template's ExtraExtensions field as is. + ExtraExtensions []pkix.Extension + clientMu sync.Mutex client *acme.Client // initialized by acmeClient method stateMu sync.Mutex - state map[string]*certState // keyed by domain name + state map[certKey]*certState // renewal tracks the set of domains currently running renewal timers. - // It is keyed by domain name. renewalMu sync.Mutex - renewal map[string]*domainRenewal + renewal map[certKey]*domainRenewal // tokensMu guards the rest of the fields: tryHTTP01, certTokens and httpTokens. tokensMu sync.RWMutex @@ -167,21 +177,60 @@ type Manager struct { // to be provisioned. // The entries are stored for the duration of the authorization flow. httpTokens map[string][]byte - // certTokens contains temporary certificates for tls-sni challenges + // certTokens contains temporary certificates for tls-sni and tls-alpn challenges // and is keyed by token domain name, which matches server name of ClientHello. - // Keys always have ".acme.invalid" suffix. + // Keys always have ".acme.invalid" suffix for tls-sni. Otherwise, they are domain names + // for tls-alpn. // The entries are stored for the duration of the authorization flow. certTokens map[string]*tls.Certificate + // nowFunc, if not nil, returns the current time. This may be set for + // testing purposes. + nowFunc func() time.Time +} + +// certKey is the key by which certificates are tracked in state, renewal and cache. +type certKey struct { + domain string // without trailing dot + isRSA bool // RSA cert for legacy clients (as opposed to default ECDSA) + isToken bool // tls-based challenge token cert; key type is undefined regardless of isRSA +} + +func (c certKey) String() string { + if c.isToken { + return c.domain + "+token" + } + if c.isRSA { + return c.domain + "+rsa" + } + return c.domain +} + +// TLSConfig creates a new TLS config suitable for net/http.Server servers, +// supporting HTTP/2 and the tls-alpn-01 ACME challenge type. +func (m *Manager) TLSConfig() *tls.Config { + return &tls.Config{ + GetCertificate: m.GetCertificate, + NextProtos: []string{ + "h2", "http/1.1", // enable HTTP/2 + acme.ALPNProto, // enable tls-alpn ACME challenges + }, + } } // GetCertificate implements the tls.Config.GetCertificate hook. // It provides a TLS certificate for hello.ServerName host, including answering -// *.acme.invalid (TLS-SNI) challenges. All other fields of hello are ignored. +// tls-alpn-01 and *.acme.invalid (tls-sni-01 and tls-sni-02) challenges. +// All other fields of hello are ignored. // // If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting // a new cert. A non-nil error returned from m.HostPolicy halts TLS negotiation. // The error is propagated back to the caller of GetCertificate and is user-visible. // This does not affect cached certs. See HostPolicy field description for more details. +// +// If GetCertificate is used directly, instead of via Manager.TLSConfig, package users will +// also have to add acme.ALPNProto to NextProtos for tls-alpn-01, or use HTTPHandler +// for http-01. (The tls-sni-* challenges have been deprecated by popular ACME providers +// due to security issues in the ecosystem.) func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { if m.Prompt == nil { return nil, errors.New("acme/autocert: Manager.Prompt not set") @@ -194,7 +243,7 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, if !strings.Contains(strings.Trim(name, "."), ".") { return nil, errors.New("acme/autocert: server name component count invalid") } - if strings.ContainsAny(name, `/\`) { + if strings.ContainsAny(name, `+/\`) { return nil, errors.New("acme/autocert: server name contains invalid character") } @@ -203,14 +252,17 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) defer cancel() - // check whether this is a token cert requested for TLS-SNI challenge - if strings.HasSuffix(name, ".acme.invalid") { + // Check whether this is a token cert requested for TLS-SNI or TLS-ALPN challenge. + if wantsTokenCert(hello) { m.tokensMu.RLock() defer m.tokensMu.RUnlock() + // It's ok to use the same token cert key for both tls-sni and tls-alpn + // because there's always at most 1 token cert per on-going domain authorization. + // See m.verify for details. if cert := m.certTokens[name]; cert != nil { return cert, nil } - if cert, err := m.cacheGet(ctx, name); err == nil { + if cert, err := m.cacheGet(ctx, certKey{domain: name, isToken: true}); err == nil { return cert, nil } // TODO: cache error results? @@ -218,8 +270,11 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, } // regular domain - name = strings.TrimSuffix(name, ".") // golang.org/issue/18114 - cert, err := m.cert(ctx, name) + ck := certKey{ + domain: strings.TrimSuffix(name, "."), // golang.org/issue/18114 + isRSA: !supportsECDSA(hello), + } + cert, err := m.cert(ctx, ck) if err == nil { return cert, nil } @@ -231,14 +286,71 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, if err := m.hostPolicy()(ctx, name); err != nil { return nil, err } - cert, err = m.createCert(ctx, name) + cert, err = m.createCert(ctx, ck) if err != nil { return nil, err } - m.cachePut(ctx, name, cert) + m.cachePut(ctx, ck, cert) return cert, nil } +// wantsTokenCert reports whether a TLS request with SNI is made by a CA server +// for a challenge verification. +func wantsTokenCert(hello *tls.ClientHelloInfo) bool { + // tls-alpn-01 + if len(hello.SupportedProtos) == 1 && hello.SupportedProtos[0] == acme.ALPNProto { + return true + } + // tls-sni-xx + return strings.HasSuffix(hello.ServerName, ".acme.invalid") +} + +func supportsECDSA(hello *tls.ClientHelloInfo) bool { + // The "signature_algorithms" extension, if present, limits the key exchange + // algorithms allowed by the cipher suites. See RFC 5246, section 7.4.1.4.1. + if hello.SignatureSchemes != nil { + ecdsaOK := false + schemeLoop: + for _, scheme := range hello.SignatureSchemes { + const tlsECDSAWithSHA1 tls.SignatureScheme = 0x0203 // constant added in Go 1.10 + switch scheme { + case tlsECDSAWithSHA1, tls.ECDSAWithP256AndSHA256, + tls.ECDSAWithP384AndSHA384, tls.ECDSAWithP521AndSHA512: + ecdsaOK = true + break schemeLoop + } + } + if !ecdsaOK { + return false + } + } + if hello.SupportedCurves != nil { + ecdsaOK := false + for _, curve := range hello.SupportedCurves { + if curve == tls.CurveP256 { + ecdsaOK = true + break + } + } + if !ecdsaOK { + return false + } + } + for _, suite := range hello.CipherSuites { + switch suite { + case tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: + return true + } + } + return false +} + // HTTPHandler configures the Manager to provision ACME "http-01" challenge responses. // It returns an http.Handler that responds to the challenges and must be // running on port 80. If it receives a request that is not an ACME challenge, @@ -252,8 +364,8 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, // Because the fallback handler is run with unencrypted port 80 requests, // the fallback should not serve TLS-only requests. // -// If HTTPHandler is never called, the Manager will only use TLS SNI -// challenges for domain verification. +// If HTTPHandler is never called, the Manager will only use the "tls-alpn-01" +// challenge for domain verification. func (m *Manager) HTTPHandler(fallback http.Handler) http.Handler { m.tokensMu.Lock() defer m.tokensMu.Unlock() @@ -304,16 +416,16 @@ func stripPort(hostport string) string { // cert returns an existing certificate either from m.state or cache. // If a certificate is found in cache but not in m.state, the latter will be filled // with the cached value. -func (m *Manager) cert(ctx context.Context, name string) (*tls.Certificate, error) { +func (m *Manager) cert(ctx context.Context, ck certKey) (*tls.Certificate, error) { m.stateMu.Lock() - if s, ok := m.state[name]; ok { + if s, ok := m.state[ck]; ok { m.stateMu.Unlock() s.RLock() defer s.RUnlock() return s.tlscert() } defer m.stateMu.Unlock() - cert, err := m.cacheGet(ctx, name) + cert, err := m.cacheGet(ctx, ck) if err != nil { return nil, err } @@ -322,25 +434,25 @@ func (m *Manager) cert(ctx context.Context, name string) (*tls.Certificate, erro return nil, errors.New("acme/autocert: private key cannot sign") } if m.state == nil { - m.state = make(map[string]*certState) + m.state = make(map[certKey]*certState) } s := &certState{ key: signer, cert: cert.Certificate, leaf: cert.Leaf, } - m.state[name] = s - go m.renew(name, s.key, s.leaf.NotAfter) + m.state[ck] = s + go m.renew(ck, s.key, s.leaf.NotAfter) return cert, nil } // cacheGet always returns a valid certificate, or an error otherwise. -// If a cached certficate exists but is not valid, ErrCacheMiss is returned. -func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate, error) { +// If a cached certificate exists but is not valid, ErrCacheMiss is returned. +func (m *Manager) cacheGet(ctx context.Context, ck certKey) (*tls.Certificate, error) { if m.Cache == nil { return nil, ErrCacheMiss } - data, err := m.Cache.Get(ctx, domain) + data, err := m.Cache.Get(ctx, ck.String()) if err != nil { return nil, err } @@ -371,7 +483,7 @@ func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate } // verify and create TLS cert - leaf, err := validCert(domain, pubDER, privKey) + leaf, err := validCert(ck, pubDER, privKey, m.now()) if err != nil { return nil, ErrCacheMiss } @@ -383,7 +495,7 @@ func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate return tlscert, nil } -func (m *Manager) cachePut(ctx context.Context, domain string, tlscert *tls.Certificate) error { +func (m *Manager) cachePut(ctx context.Context, ck certKey, tlscert *tls.Certificate) error { if m.Cache == nil { return nil } @@ -415,7 +527,7 @@ func (m *Manager) cachePut(ctx context.Context, domain string, tlscert *tls.Cert } } - return m.Cache.Put(ctx, domain, buf.Bytes()) + return m.Cache.Put(ctx, ck.String(), buf.Bytes()) } func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error { @@ -432,9 +544,9 @@ func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error { // // If the domain is already being verified, it waits for the existing verification to complete. // Either way, createCert blocks for the duration of the whole process. -func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certificate, error) { +func (m *Manager) createCert(ctx context.Context, ck certKey) (*tls.Certificate, error) { // TODO: maybe rewrite this whole piece using sync.Once - state, err := m.certState(domain) + state, err := m.certState(ck) if err != nil { return nil, err } @@ -452,44 +564,44 @@ func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certifica defer state.Unlock() state.locked = false - der, leaf, err := m.authorizedCert(ctx, state.key, domain) + der, leaf, err := m.authorizedCert(ctx, state.key, ck) if err != nil { // Remove the failed state after some time, // making the manager call createCert again on the following TLS hello. time.AfterFunc(createCertRetryAfter, func() { - defer testDidRemoveState(domain) + defer testDidRemoveState(ck) m.stateMu.Lock() defer m.stateMu.Unlock() // Verify the state hasn't changed and it's still invalid // before deleting. - s, ok := m.state[domain] + s, ok := m.state[ck] if !ok { return } - if _, err := validCert(domain, s.cert, s.key); err == nil { + if _, err := validCert(ck, s.cert, s.key, m.now()); err == nil { return } - delete(m.state, domain) + delete(m.state, ck) }) return nil, err } state.cert = der state.leaf = leaf - go m.renew(domain, state.key, state.leaf.NotAfter) + go m.renew(ck, state.key, state.leaf.NotAfter) return state.tlscert() } // certState returns a new or existing certState. // If a new certState is returned, state.exist is false and the state is locked. // The returned error is non-nil only in the case where a new state could not be created. -func (m *Manager) certState(domain string) (*certState, error) { +func (m *Manager) certState(ck certKey) (*certState, error) { m.stateMu.Lock() defer m.stateMu.Unlock() if m.state == nil { - m.state = make(map[string]*certState) + m.state = make(map[certKey]*certState) } // existing state - if state, ok := m.state[domain]; ok { + if state, ok := m.state[ck]; ok { return state, nil } @@ -498,7 +610,7 @@ func (m *Manager) certState(domain string) (*certState, error) { err error key crypto.Signer ) - if m.ForceRSA { + if ck.isRSA { key, err = rsa.GenerateKey(rand.Reader, 2048) } else { key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -512,22 +624,22 @@ func (m *Manager) certState(domain string) (*certState, error) { locked: true, } state.Lock() // will be unlocked by m.certState caller - m.state[domain] = state + m.state[ck] = state return state, nil } // authorizedCert starts the domain ownership verification process and requests a new cert upon success. // The key argument is the certificate private key. -func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) { +func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, ck certKey) (der [][]byte, leaf *x509.Certificate, err error) { client, err := m.acmeClient(ctx) if err != nil { return nil, nil, err } - if err := m.verify(ctx, client, domain); err != nil { + if err := m.verify(ctx, client, ck.domain); err != nil { return nil, nil, err } - csr, err := certRequest(key, domain) + csr, err := certRequest(key, ck.domain, m.ExtraExtensions) if err != nil { return nil, nil, err } @@ -535,25 +647,55 @@ func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain if err != nil { return nil, nil, err } - leaf, err = validCert(domain, der, key) + leaf, err = validCert(ck, der, key, m.now()) if err != nil { return nil, nil, err } return der, leaf, nil } +// revokePendingAuthz revokes all authorizations idenfied by the elements of uri slice. +// It ignores revocation errors. +func (m *Manager) revokePendingAuthz(ctx context.Context, uri []string) { + client, err := m.acmeClient(ctx) + if err != nil { + return + } + for _, u := range uri { + client.RevokeAuthorization(ctx, u) + } +} + // verify runs the identifier (domain) authorization flow // using each applicable ACME challenge type. func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string) error { // The list of challenge types we'll try to fulfill // in this specific order. - challengeTypes := []string{"tls-sni-02", "tls-sni-01"} + challengeTypes := []string{"tls-alpn-01", "tls-sni-02", "tls-sni-01"} m.tokensMu.RLock() if m.tryHTTP01 { challengeTypes = append(challengeTypes, "http-01") } m.tokensMu.RUnlock() + // Keep track of pending authzs and revoke the ones that did not validate. + pendingAuthzs := make(map[string]bool) + defer func() { + var uri []string + for k, pending := range pendingAuthzs { + if pending { + uri = append(uri, k) + } + } + if len(uri) > 0 { + // Use "detached" background context. + // The revocations need not happen in the current verification flow. + go m.revokePendingAuthz(context.Background(), uri) + } + }() + + // errs accumulates challenge failure errors, printed if all fail + errs := make(map[*acme.Challenge]error) var nextTyp int // challengeType index of the next challenge type to try for { // Start domain authorization and get the challenge. @@ -570,6 +712,8 @@ func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string return fmt.Errorf("acme/autocert: invalid authorization %q", authz.URI) } + pendingAuthzs[authz.URI] = true + // Pick the next preferred challenge. var chal *acme.Challenge for chal == nil && nextTyp < len(challengeTypes) { @@ -577,28 +721,44 @@ func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string nextTyp++ } if chal == nil { - return fmt.Errorf("acme/autocert: unable to authorize %q; tried %q", domain, challengeTypes) + errorMsg := fmt.Sprintf("acme/autocert: unable to authorize %q", domain) + for chal, err := range errs { + errorMsg += fmt.Sprintf("; challenge %q failed with error: %v", chal.Type, err) + } + return errors.New(errorMsg) } - cleanup, err := m.fulfill(ctx, client, chal) + cleanup, err := m.fulfill(ctx, client, chal, domain) if err != nil { + errs[chal] = err continue } defer cleanup() if _, err := client.Accept(ctx, chal); err != nil { + errs[chal] = err continue } // A challenge is fulfilled and accepted: wait for the CA to validate. - if _, err := client.WaitAuthorization(ctx, authz.URI); err == nil { - return nil + if _, err := client.WaitAuthorization(ctx, authz.URI); err != nil { + errs[chal] = err + continue } + delete(pendingAuthzs, authz.URI) + return nil } } // fulfill provisions a response to the challenge chal. // The cleanup is non-nil only if provisioning succeeded. -func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge) (cleanup func(), err error) { +func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge, domain string) (cleanup func(), err error) { switch chal.Type { + case "tls-alpn-01": + cert, err := client.TLSALPN01ChallengeCert(chal.Token, domain) + if err != nil { + return nil, err + } + m.putCertToken(ctx, domain, &cert) + return func() { go m.deleteCertToken(domain) }, nil case "tls-sni-01": cert, name, err := client.TLSSNI01ChallengeCert(chal.Token) if err != nil { @@ -634,8 +794,8 @@ func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge { return nil } -// putCertToken stores the cert under the named key in both m.certTokens map -// and m.Cache. +// putCertToken stores the token certificate with the specified name +// in both m.certTokens map and m.Cache. func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) { m.tokensMu.Lock() defer m.tokensMu.Unlock() @@ -643,17 +803,18 @@ func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certi m.certTokens = make(map[string]*tls.Certificate) } m.certTokens[name] = cert - m.cachePut(ctx, name, cert) + m.cachePut(ctx, certKey{domain: name, isToken: true}, cert) } -// deleteCertToken removes the token certificate for the specified domain name +// deleteCertToken removes the token certificate with the specified name // from both m.certTokens map and m.Cache. func (m *Manager) deleteCertToken(name string) { m.tokensMu.Lock() defer m.tokensMu.Unlock() delete(m.certTokens, name) if m.Cache != nil { - m.Cache.Delete(context.Background(), name) + ck := certKey{domain: name, isToken: true} + m.Cache.Delete(context.Background(), ck.String()) } } @@ -704,7 +865,7 @@ func (m *Manager) deleteHTTPToken(tokenPath string) { // httpTokenCacheKey returns a key at which an http-01 token value may be stored // in the Manager's optional Cache. func httpTokenCacheKey(tokenPath string) string { - return "http-01-" + path.Base(tokenPath) + return path.Base(tokenPath) + "+http-01" } // renew starts a cert renewal timer loop, one per domain. @@ -715,18 +876,18 @@ func httpTokenCacheKey(tokenPath string) string { // // The key argument is a certificate private key. // The exp argument is the cert expiration time (NotAfter). -func (m *Manager) renew(domain string, key crypto.Signer, exp time.Time) { +func (m *Manager) renew(ck certKey, key crypto.Signer, exp time.Time) { m.renewalMu.Lock() defer m.renewalMu.Unlock() - if m.renewal[domain] != nil { + if m.renewal[ck] != nil { // another goroutine is already on it return } if m.renewal == nil { - m.renewal = make(map[string]*domainRenewal) + m.renewal = make(map[certKey]*domainRenewal) } - dr := &domainRenewal{m: m, domain: domain, key: key} - m.renewal[domain] = dr + dr := &domainRenewal{m: m, ck: ck, key: key} + m.renewal[ck] = dr dr.start(exp) } @@ -742,7 +903,10 @@ func (m *Manager) stopRenew() { } func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) { - const keyName = "acme_account.key" + const keyName = "acme_account+key" + + // Previous versions of autocert stored the value under a different key. + const legacyKeyName = "acme_account.key" genKey := func() (*ecdsa.PrivateKey, error) { return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -753,6 +917,9 @@ func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) { } data, err := m.Cache.Get(ctx, keyName) + if err == ErrCacheMiss { + data, err = m.Cache.Get(ctx, legacyKeyName) + } if err == ErrCacheMiss { key, err := genKey() if err != nil { @@ -824,6 +991,13 @@ func (m *Manager) renewBefore() time.Duration { return 720 * time.Hour // 30 days } +func (m *Manager) now() time.Time { + if m.nowFunc != nil { + return m.nowFunc() + } + return time.Now() +} + // certState is ready when its mutex is unlocked for reading. type certState struct { sync.RWMutex @@ -849,12 +1023,12 @@ func (s *certState) tlscert() (*tls.Certificate, error) { }, nil } -// certRequest creates a certificate request for the given common name cn -// and optional SANs. -func certRequest(key crypto.Signer, cn string, san ...string) ([]byte, error) { +// certRequest generates a CSR for the given common name cn and optional SANs. +func certRequest(key crypto.Signer, cn string, ext []pkix.Extension, san ...string) ([]byte, error) { req := &x509.CertificateRequest{ - Subject: pkix.Name{CommonName: cn}, - DNSNames: san, + Subject: pkix.Name{CommonName: cn}, + DNSNames: san, + ExtraExtensions: ext, } return x509.CreateCertificateRequest(rand.Reader, req, key) } @@ -885,12 +1059,12 @@ func parsePrivateKey(der []byte) (crypto.Signer, error) { return nil, errors.New("acme/autocert: failed to parse private key") } -// validCert parses a cert chain provided as der argument and verifies the leaf, der[0], -// corresponds to the private key, as well as the domain match and expiration dates. -// It doesn't do any revocation checking. +// validCert parses a cert chain provided as der argument and verifies the leaf and der[0] +// correspond to the private key, the domain and key type match, and expiration dates +// are valid. It doesn't do any revocation checking. // // The returned value is the verified leaf cert. -func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certificate, err error) { +func validCert(ck certKey, der [][]byte, key crypto.Signer, now time.Time) (leaf *x509.Certificate, err error) { // parse public part(s) var n int for _, b := range der { @@ -902,22 +1076,21 @@ func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certi n += copy(pub[n:], b) } x509Cert, err := x509.ParseCertificates(pub) - if len(x509Cert) == 0 { + if err != nil || len(x509Cert) == 0 { return nil, errors.New("acme/autocert: no public key found") } // verify the leaf is not expired and matches the domain name leaf = x509Cert[0] - now := timeNow() if now.Before(leaf.NotBefore) { return nil, errors.New("acme/autocert: certificate is not valid yet") } if now.After(leaf.NotAfter) { return nil, errors.New("acme/autocert: expired certificate") } - if err := leaf.VerifyHostname(domain); err != nil { + if err := leaf.VerifyHostname(ck.domain); err != nil { return nil, err } - // ensure the leaf corresponds to the private key + // ensure the leaf corresponds to the private key and matches the certKey type switch pub := leaf.PublicKey.(type) { case *rsa.PublicKey: prv, ok := key.(*rsa.PrivateKey) @@ -927,6 +1100,9 @@ func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certi if pub.N.Cmp(prv.N) != 0 { return nil, errors.New("acme/autocert: private key does not match public key") } + if !ck.isRSA && !ck.isToken { + return nil, errors.New("acme/autocert: key type does not match expected value") + } case *ecdsa.PublicKey: prv, ok := key.(*ecdsa.PrivateKey) if !ok { @@ -935,6 +1111,9 @@ func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certi if pub.X.Cmp(prv.X) != 0 || pub.Y.Cmp(prv.Y) != 0 { return nil, errors.New("acme/autocert: private key does not match public key") } + if ck.isRSA && !ck.isToken { + return nil, errors.New("acme/autocert: key type does not match expected value") + } default: return nil, errors.New("acme/autocert: unknown public key algorithm") } @@ -955,8 +1134,6 @@ func (r *lockedMathRand) int63n(max int64) int64 { // For easier testing. var ( - timeNow = time.Now - // Called when a state is removed. - testDidRemoveState = func(domain string) {} + testDidRemoveState = func(certKey) {} ) diff --git a/vendor/golang.org/x/crypto/acme/autocert/cache.go b/vendor/golang.org/x/crypto/acme/autocert/cache.go index 61a5fd239a..aa9aa845c8 100644 --- a/vendor/golang.org/x/crypto/acme/autocert/cache.go +++ b/vendor/golang.org/x/crypto/acme/autocert/cache.go @@ -16,10 +16,10 @@ import ( var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss") // Cache is used by Manager to store and retrieve previously obtained certificates -// as opaque data. +// and other account data as opaque blobs. // -// The key argument of the methods refers to a domain name but need not be an FQDN. -// Cache implementations should not rely on the key naming pattern. +// Cache implementations should not rely on the key naming pattern. Keys can +// include any printable ASCII characters, except the following: \/:*?"<>| type Cache interface { // Get returns a certificate data for the specified key. // If there's no such key, Get returns ErrCacheMiss. diff --git a/vendor/golang.org/x/crypto/acme/autocert/listener.go b/vendor/golang.org/x/crypto/acme/autocert/listener.go index d744df0ed0..1e069818a5 100644 --- a/vendor/golang.org/x/crypto/acme/autocert/listener.go +++ b/vendor/golang.org/x/crypto/acme/autocert/listener.go @@ -72,11 +72,8 @@ func NewListener(domains ...string) net.Listener { // the Manager m's Prompt, Cache, HostPolicy, and other desired options. func (m *Manager) Listener() net.Listener { ln := &listener{ - m: m, - conf: &tls.Config{ - GetCertificate: m.GetCertificate, // bonus: panic on nil m - NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2 - }, + m: m, + conf: m.TLSConfig(), } ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443") return ln diff --git a/vendor/golang.org/x/crypto/acme/autocert/renewal.go b/vendor/golang.org/x/crypto/acme/autocert/renewal.go index 3fa4d61a22..665f870dcd 100644 --- a/vendor/golang.org/x/crypto/acme/autocert/renewal.go +++ b/vendor/golang.org/x/crypto/acme/autocert/renewal.go @@ -17,9 +17,9 @@ const renewJitter = time.Hour // domainRenewal tracks the state used by the periodic timers // renewing a single domain's cert. type domainRenewal struct { - m *Manager - domain string - key crypto.Signer + m *Manager + ck certKey + key crypto.Signer timerMu sync.Mutex timer *time.Timer @@ -77,7 +77,7 @@ func (dr *domainRenewal) updateState(state *certState) { dr.m.stateMu.Lock() defer dr.m.stateMu.Unlock() dr.key = state.key - dr.m.state[dr.domain] = state + dr.m.state[dr.ck] = state } // do is similar to Manager.createCert but it doesn't lock a Manager.state item. @@ -91,7 +91,7 @@ func (dr *domainRenewal) updateState(state *certState) { func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) { // a race is likely unavoidable in a distributed environment // but we try nonetheless - if tlscert, err := dr.m.cacheGet(ctx, dr.domain); err == nil { + if tlscert, err := dr.m.cacheGet(ctx, dr.ck); err == nil { next := dr.next(tlscert.Leaf.NotAfter) if next > dr.m.renewBefore()+renewJitter { signer, ok := tlscert.PrivateKey.(crypto.Signer) @@ -107,7 +107,7 @@ func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) { } } - der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.domain) + der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.ck) if err != nil { return 0, err } @@ -120,7 +120,7 @@ func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) { if err != nil { return 0, err } - if err := dr.m.cachePut(ctx, dr.domain, tlscert); err != nil { + if err := dr.m.cachePut(ctx, dr.ck, tlscert); err != nil { return 0, err } dr.updateState(state) @@ -128,7 +128,7 @@ func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) { } func (dr *domainRenewal) next(expiry time.Time) time.Duration { - d := expiry.Sub(timeNow()) - dr.m.renewBefore() + d := expiry.Sub(dr.m.now()) - dr.m.renewBefore() // add a bit of randomness to renew deadline n := pseudoRand.int63n(int64(renewJitter)) d -= time.Duration(n) diff --git a/vendor/golang.org/x/crypto/acme/http.go b/vendor/golang.org/x/crypto/acme/http.go new file mode 100644 index 0000000000..a43ce6a5fe --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/http.go @@ -0,0 +1,281 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package acme + +import ( + "bytes" + "context" + "crypto" + "crypto/rand" + "encoding/json" + "fmt" + "io/ioutil" + "math/big" + "net/http" + "strconv" + "strings" + "time" +) + +// retryTimer encapsulates common logic for retrying unsuccessful requests. +// It is not safe for concurrent use. +type retryTimer struct { + // backoffFn provides backoff delay sequence for retries. + // See Client.RetryBackoff doc comment. + backoffFn func(n int, r *http.Request, res *http.Response) time.Duration + // n is the current retry attempt. + n int +} + +func (t *retryTimer) inc() { + t.n++ +} + +// backoff pauses the current goroutine as described in Client.RetryBackoff. +func (t *retryTimer) backoff(ctx context.Context, r *http.Request, res *http.Response) error { + d := t.backoffFn(t.n, r, res) + if d <= 0 { + return fmt.Errorf("acme: no more retries for %s; tried %d time(s)", r.URL, t.n) + } + wakeup := time.NewTimer(d) + defer wakeup.Stop() + select { + case <-ctx.Done(): + return ctx.Err() + case <-wakeup.C: + return nil + } +} + +func (c *Client) retryTimer() *retryTimer { + f := c.RetryBackoff + if f == nil { + f = defaultBackoff + } + return &retryTimer{backoffFn: f} +} + +// defaultBackoff provides default Client.RetryBackoff implementation +// using a truncated exponential backoff algorithm, +// as described in Client.RetryBackoff. +// +// The n argument is always bounded between 1 and 30. +// The returned value is always greater than 0. +func defaultBackoff(n int, r *http.Request, res *http.Response) time.Duration { + const max = 10 * time.Second + var jitter time.Duration + if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil { + // Set the minimum to 1ms to avoid a case where + // an invalid Retry-After value is parsed into 0 below, + // resulting in the 0 returned value which would unintentionally + // stop the retries. + jitter = (1 + time.Duration(x.Int64())) * time.Millisecond + } + if v, ok := res.Header["Retry-After"]; ok { + return retryAfter(v[0]) + jitter + } + + if n < 1 { + n = 1 + } + if n > 30 { + n = 30 + } + d := time.Duration(1< max { + return max + } + return d +} + +// retryAfter parses a Retry-After HTTP header value, +// trying to convert v into an int (seconds) or use http.ParseTime otherwise. +// It returns zero value if v cannot be parsed. +func retryAfter(v string) time.Duration { + if i, err := strconv.Atoi(v); err == nil { + return time.Duration(i) * time.Second + } + t, err := http.ParseTime(v) + if err != nil { + return 0 + } + return t.Sub(timeNow()) +} + +// resOkay is a function that reports whether the provided response is okay. +// It is expected to keep the response body unread. +type resOkay func(*http.Response) bool + +// wantStatus returns a function which reports whether the code +// matches the status code of a response. +func wantStatus(codes ...int) resOkay { + return func(res *http.Response) bool { + for _, code := range codes { + if code == res.StatusCode { + return true + } + } + return false + } +} + +// get issues an unsigned GET request to the specified URL. +// It returns a non-error value only when ok reports true. +// +// get retries unsuccessful attempts according to c.RetryBackoff +// until the context is done or a non-retriable error is received. +func (c *Client) get(ctx context.Context, url string, ok resOkay) (*http.Response, error) { + retry := c.retryTimer() + for { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + res, err := c.doNoRetry(ctx, req) + switch { + case err != nil: + return nil, err + case ok(res): + return res, nil + case isRetriable(res.StatusCode): + retry.inc() + resErr := responseError(res) + res.Body.Close() + // Ignore the error value from retry.backoff + // and return the one from last retry, as received from the CA. + if retry.backoff(ctx, req, res) != nil { + return nil, resErr + } + default: + defer res.Body.Close() + return nil, responseError(res) + } + } +} + +// post issues a signed POST request in JWS format using the provided key +// to the specified URL. +// It returns a non-error value only when ok reports true. +// +// post retries unsuccessful attempts according to c.RetryBackoff +// until the context is done or a non-retriable error is received. +// It uses postNoRetry to make individual requests. +func (c *Client) post(ctx context.Context, key crypto.Signer, url string, body interface{}, ok resOkay) (*http.Response, error) { + retry := c.retryTimer() + for { + res, req, err := c.postNoRetry(ctx, key, url, body) + if err != nil { + return nil, err + } + if ok(res) { + return res, nil + } + resErr := responseError(res) + res.Body.Close() + switch { + // Check for bad nonce before isRetriable because it may have been returned + // with an unretriable response code such as 400 Bad Request. + case isBadNonce(resErr): + // Consider any previously stored nonce values to be invalid. + c.clearNonces() + case !isRetriable(res.StatusCode): + return nil, resErr + } + retry.inc() + // Ignore the error value from retry.backoff + // and return the one from last retry, as received from the CA. + if err := retry.backoff(ctx, req, res); err != nil { + return nil, resErr + } + } +} + +// postNoRetry signs the body with the given key and POSTs it to the provided url. +// The body argument must be JSON-serializable. +// It is used by c.post to retry unsuccessful attempts. +func (c *Client) postNoRetry(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, *http.Request, error) { + nonce, err := c.popNonce(ctx, url) + if err != nil { + return nil, nil, err + } + b, err := jwsEncodeJSON(body, key, nonce) + if err != nil { + return nil, nil, err + } + req, err := http.NewRequest("POST", url, bytes.NewReader(b)) + if err != nil { + return nil, nil, err + } + req.Header.Set("Content-Type", "application/jose+json") + res, err := c.doNoRetry(ctx, req) + if err != nil { + return nil, nil, err + } + c.addNonce(res.Header) + return res, req, nil +} + +// doNoRetry issues a request req, replacing its context (if any) with ctx. +func (c *Client) doNoRetry(ctx context.Context, req *http.Request) (*http.Response, error) { + res, err := c.httpClient().Do(req.WithContext(ctx)) + if err != nil { + select { + case <-ctx.Done(): + // Prefer the unadorned context error. + // (The acme package had tests assuming this, previously from ctxhttp's + // behavior, predating net/http supporting contexts natively) + // TODO(bradfitz): reconsider this in the future. But for now this + // requires no test updates. + return nil, ctx.Err() + default: + return nil, err + } + } + return res, nil +} + +func (c *Client) httpClient() *http.Client { + if c.HTTPClient != nil { + return c.HTTPClient + } + return http.DefaultClient +} + +// isBadNonce reports whether err is an ACME "badnonce" error. +func isBadNonce(err error) bool { + // According to the spec badNonce is urn:ietf:params:acme:error:badNonce. + // However, ACME servers in the wild return their versions of the error. + // See https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4 + // and https://github.com/letsencrypt/boulder/blob/0e07eacb/docs/acme-divergences.md#section-66. + ae, ok := err.(*Error) + return ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") +} + +// isRetriable reports whether a request can be retried +// based on the response status code. +// +// Note that a "bad nonce" error is returned with a non-retriable 400 Bad Request code. +// Callers should parse the response and check with isBadNonce. +func isRetriable(code int) bool { + return code <= 399 || code >= 500 || code == http.StatusTooManyRequests +} + +// responseError creates an error of Error type from resp. +func responseError(resp *http.Response) error { + // don't care if ReadAll returns an error: + // json.Unmarshal will fail in that case anyway + b, _ := ioutil.ReadAll(resp.Body) + e := &wireError{Status: resp.StatusCode} + if err := json.Unmarshal(b, e); err != nil { + // this is not a regular error response: + // populate detail with anything we received, + // e.Status will already contain HTTP response code value + e.Detail = string(b) + if e.Detail == "" { + e.Detail = resp.Status + } + } + return e.error(resp.Header) +} diff --git a/vendor/golang.org/x/crypto/acme/types.go b/vendor/golang.org/x/crypto/acme/types.go index 3e199749ec..54792c0650 100644 --- a/vendor/golang.org/x/crypto/acme/types.go +++ b/vendor/golang.org/x/crypto/acme/types.go @@ -104,7 +104,7 @@ func RateLimit(err error) (time.Duration, bool) { if e.Header == nil { return 0, true } - return retryAfter(e.Header.Get("Retry-After"), 0), true + return retryAfter(e.Header.Get("Retry-After")), true } // Account is a user account. It is associated with a private key. @@ -296,8 +296,8 @@ func (e *wireError) error(h http.Header) *Error { } } -// CertOption is an optional argument type for the TLSSNIxChallengeCert methods for -// customizing a temporary certificate for TLS-SNI challenges. +// CertOption is an optional argument type for the TLS ChallengeCert methods for +// customizing a temporary certificate for TLS-based challenges. type CertOption interface { privateCertOpt() } @@ -317,7 +317,7 @@ func (*certOptKey) privateCertOpt() {} // WithTemplate creates an option for specifying a certificate template. // See x509.CreateCertificate for template usage details. // -// In TLSSNIxChallengeCert methods, the template is also used as parent, +// In TLS ChallengeCert methods, the template is also used as parent, // resulting in a self-signed certificate. // The DNSNames field of t is always overwritten for tls-sni challenge certs. func WithTemplate(t *x509.Certificate) CertOption { diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go index a57771a1ed..d6f683ba3f 100644 --- a/vendor/golang.org/x/crypto/ed25519/ed25519.go +++ b/vendor/golang.org/x/crypto/ed25519/ed25519.go @@ -6,7 +6,10 @@ // https://ed25519.cr.yp.to/. // // These functions are also compatible with the “Ed25519” function defined in -// RFC 8032. +// RFC 8032. However, unlike RFC 8032's formulation, this package's private key +// representation includes a public key suffix to make multiple signing +// operations with the same key more efficient. This package refers to the RFC +// 8032 private key as the “seed”. package ed25519 // This code is a port of the public domain, “ref10” implementation of ed25519 @@ -31,6 +34,8 @@ const ( PrivateKeySize = 64 // SignatureSize is the size, in bytes, of signatures generated and verified by this package. SignatureSize = 64 + // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. + SeedSize = 32 ) // PublicKey is the type of Ed25519 public keys. @@ -46,6 +51,15 @@ func (priv PrivateKey) Public() crypto.PublicKey { return PublicKey(publicKey) } +// Seed returns the private key seed corresponding to priv. It is provided for +// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds +// in this package. +func (priv PrivateKey) Seed() []byte { + seed := make([]byte, SeedSize) + copy(seed, priv[:32]) + return seed +} + // Sign signs the given message with priv. // Ed25519 performs two passes over messages to be signed and therefore cannot // handle pre-hashed messages. Thus opts.HashFunc() must return zero to @@ -61,19 +75,33 @@ func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOp // GenerateKey generates a public/private key pair using entropy from rand. // If rand is nil, crypto/rand.Reader will be used. -func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) { +func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { if rand == nil { rand = cryptorand.Reader } - privateKey = make([]byte, PrivateKeySize) - publicKey = make([]byte, PublicKeySize) - _, err = io.ReadFull(rand, privateKey[:32]) - if err != nil { + seed := make([]byte, SeedSize) + if _, err := io.ReadFull(rand, seed); err != nil { return nil, nil, err } - digest := sha512.Sum512(privateKey[:32]) + privateKey := NewKeyFromSeed(seed) + publicKey := make([]byte, PublicKeySize) + copy(publicKey, privateKey[32:]) + + return publicKey, privateKey, nil +} + +// NewKeyFromSeed calculates a private key from a seed. It will panic if +// len(seed) is not SeedSize. This function is provided for interoperability +// with RFC 8032. RFC 8032's private keys correspond to seeds in this +// package. +func NewKeyFromSeed(seed []byte) PrivateKey { + if l := len(seed); l != SeedSize { + panic("ed25519: bad seed length: " + strconv.Itoa(l)) + } + + digest := sha512.Sum512(seed) digest[0] &= 248 digest[31] &= 127 digest[31] |= 64 @@ -85,10 +113,11 @@ func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, er var publicKeyBytes [32]byte A.ToBytes(&publicKeyBytes) + privateKey := make([]byte, PrivateKeySize) + copy(privateKey, seed) copy(privateKey[32:], publicKeyBytes[:]) - copy(publicKey, publicKeyBytes[:]) - return publicKey, privateKey, nil + return privateKey } // Sign signs the message with privateKey and returns a signature. It will diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go index 7c7269676a..6570847f5e 100644 --- a/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go +++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go @@ -9,6 +9,8 @@ package chacha20 import ( "crypto/cipher" "encoding/binary" + + "golang.org/x/crypto/internal/subtle" ) // assert that *Cipher implements cipher.Stream @@ -18,10 +20,10 @@ var _ cipher.Stream = (*Cipher)(nil) // and nonce. A *Cipher implements the cipher.Stream interface. type Cipher struct { key [8]uint32 + counter uint32 // incremented after each block nonce [3]uint32 - counter uint32 // incremented after each block - buf [64]byte // buffer for unused keystream bytes - len int // number of unused keystream bytes at end of buf + buf [bufSize]byte // buffer for unused keystream bytes + len int // number of unused keystream bytes at end of buf } // New creates a new ChaCha20 stream cipher with the given key and nonce. @@ -30,6 +32,30 @@ func New(key [8]uint32, nonce [3]uint32) *Cipher { return &Cipher{key: key, nonce: nonce} } +// ChaCha20 constants spelling "expand 32-byte k" +const ( + j0 uint32 = 0x61707865 + j1 uint32 = 0x3320646e + j2 uint32 = 0x79622d32 + j3 uint32 = 0x6b206574 +) + +func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) { + a += b + d ^= a + d = (d << 16) | (d >> 16) + c += d + b ^= c + b = (b << 12) | (b >> 20) + a += b + d ^= a + d = (d << 8) | (d >> 24) + c += d + b ^= c + b = (b << 7) | (b >> 25) + return a, b, c, d +} + // XORKeyStream XORs each byte in the given slice with a byte from the // cipher's key stream. Dst and src must overlap entirely or not at all. // @@ -41,6 +67,13 @@ func New(key [8]uint32, nonce [3]uint32) *Cipher { // the src buffers was passed in a single run. That is, Cipher // maintains state and does not reset at each XORKeyStream call. func (s *Cipher) XORKeyStream(dst, src []byte) { + if len(dst) < len(src) { + panic("chacha20: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("chacha20: invalid buffer overlap") + } + // xor src with buffered keystream first if s.len != 0 { buf := s.buf[len(s.buf)-s.len:] @@ -63,6 +96,13 @@ func (s *Cipher) XORKeyStream(dst, src []byte) { if len(src) == 0 { return } + if haveAsm { + if uint64(len(src))+uint64(s.counter)*64 > (1<<38)-64 { + panic("chacha20: counter overflow") + } + s.xorKeyStreamAsm(dst, src) + return + } // set up a 64-byte buffer to pad out the final block if needed // (hoisted out of the main loop to avoid spills) @@ -72,59 +112,34 @@ func (s *Cipher) XORKeyStream(dst, src []byte) { copy(s.buf[len(s.buf)-64:], src[fin:]) } - // qr calculates a quarter round - qr := func(a, b, c, d uint32) (uint32, uint32, uint32, uint32) { - a += b - d ^= a - d = (d << 16) | (d >> 16) - c += d - b ^= c - b = (b << 12) | (b >> 20) - a += b - d ^= a - d = (d << 8) | (d >> 24) - c += d - b ^= c - b = (b << 7) | (b >> 25) - return a, b, c, d - } - - // ChaCha20 constants - const ( - j0 = 0x61707865 - j1 = 0x3320646e - j2 = 0x79622d32 - j3 = 0x6b206574 - ) - // pre-calculate most of the first round - s1, s5, s9, s13 := qr(j1, s.key[1], s.key[5], s.nonce[0]) - s2, s6, s10, s14 := qr(j2, s.key[2], s.key[6], s.nonce[1]) - s3, s7, s11, s15 := qr(j3, s.key[3], s.key[7], s.nonce[2]) + s1, s5, s9, s13 := quarterRound(j1, s.key[1], s.key[5], s.nonce[0]) + s2, s6, s10, s14 := quarterRound(j2, s.key[2], s.key[6], s.nonce[1]) + s3, s7, s11, s15 := quarterRound(j3, s.key[3], s.key[7], s.nonce[2]) n := len(src) src, dst = src[:n:n], dst[:n:n] // BCE hint for i := 0; i < n; i += 64 { // calculate the remainder of the first round - s0, s4, s8, s12 := qr(j0, s.key[0], s.key[4], s.counter) + s0, s4, s8, s12 := quarterRound(j0, s.key[0], s.key[4], s.counter) // execute the second round - x0, x5, x10, x15 := qr(s0, s5, s10, s15) - x1, x6, x11, x12 := qr(s1, s6, s11, s12) - x2, x7, x8, x13 := qr(s2, s7, s8, s13) - x3, x4, x9, x14 := qr(s3, s4, s9, s14) + x0, x5, x10, x15 := quarterRound(s0, s5, s10, s15) + x1, x6, x11, x12 := quarterRound(s1, s6, s11, s12) + x2, x7, x8, x13 := quarterRound(s2, s7, s8, s13) + x3, x4, x9, x14 := quarterRound(s3, s4, s9, s14) // execute the remaining 18 rounds for i := 0; i < 9; i++ { - x0, x4, x8, x12 = qr(x0, x4, x8, x12) - x1, x5, x9, x13 = qr(x1, x5, x9, x13) - x2, x6, x10, x14 = qr(x2, x6, x10, x14) - x3, x7, x11, x15 = qr(x3, x7, x11, x15) + x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) + x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) + x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) + x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) - x0, x5, x10, x15 = qr(x0, x5, x10, x15) - x1, x6, x11, x12 = qr(x1, x6, x11, x12) - x2, x7, x8, x13 = qr(x2, x7, x8, x13) - x3, x4, x9, x14 = qr(x3, x4, x9, x14) + x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) + x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) + x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) + x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) } x0 += j0 @@ -221,3 +236,29 @@ func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { } s.XORKeyStream(out, in) } + +// HChaCha20 uses the ChaCha20 core to generate a derived key from a key and a +// nonce. It should only be used as part of the XChaCha20 construction. +func HChaCha20(key *[8]uint32, nonce *[4]uint32) [8]uint32 { + x0, x1, x2, x3 := j0, j1, j2, j3 + x4, x5, x6, x7 := key[0], key[1], key[2], key[3] + x8, x9, x10, x11 := key[4], key[5], key[6], key[7] + x12, x13, x14, x15 := nonce[0], nonce[1], nonce[2], nonce[3] + + for i := 0; i < 10; i++ { + x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) + x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) + x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) + x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) + + x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) + x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) + x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) + x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) + } + + var out [8]uint32 + out[0], out[1], out[2], out[3] = x0, x1, x2, x3 + out[4], out[5], out[6], out[7] = x12, x13, x14, x15 + return out +} diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go new file mode 100644 index 0000000000..91520d1de0 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go @@ -0,0 +1,16 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !s390x gccgo appengine + +package chacha20 + +const ( + bufSize = 64 + haveAsm = false +) + +func (*Cipher) xorKeyStreamAsm(dst, src []byte) { + panic("not implemented") +} diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go new file mode 100644 index 0000000000..0c1c671c40 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go @@ -0,0 +1,30 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build s390x,!gccgo,!appengine + +package chacha20 + +var haveAsm = hasVectorFacility() + +const bufSize = 256 + +// hasVectorFacility reports whether the machine supports the vector +// facility (vx). +// Implementation in asm_s390x.s. +func hasVectorFacility() bool + +// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only +// be called when the vector facility is available. +// Implementation in asm_s390x.s. +//go:noescape +func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32, buf *[256]byte, len *int) + +func (c *Cipher) xorKeyStreamAsm(dst, src []byte) { + xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter, &c.buf, &c.len) +} + +// EXRL targets, DO NOT CALL! +func mvcSrcToBuf() +func mvcBufToDst() diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.s b/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.s new file mode 100644 index 0000000000..98427c5e22 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.s @@ -0,0 +1,283 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build s390x,!gccgo,!appengine + +#include "go_asm.h" +#include "textflag.h" + +// This is an implementation of the ChaCha20 encryption algorithm as +// specified in RFC 7539. It uses vector instructions to compute +// 4 keystream blocks in parallel (256 bytes) which are then XORed +// with the bytes in the input slice. + +GLOBL ·constants<>(SB), RODATA|NOPTR, $32 +// BSWAP: swap bytes in each 4-byte element +DATA ·constants<>+0x00(SB)/4, $0x03020100 +DATA ·constants<>+0x04(SB)/4, $0x07060504 +DATA ·constants<>+0x08(SB)/4, $0x0b0a0908 +DATA ·constants<>+0x0c(SB)/4, $0x0f0e0d0c +// J0: [j0, j1, j2, j3] +DATA ·constants<>+0x10(SB)/4, $0x61707865 +DATA ·constants<>+0x14(SB)/4, $0x3320646e +DATA ·constants<>+0x18(SB)/4, $0x79622d32 +DATA ·constants<>+0x1c(SB)/4, $0x6b206574 + +// EXRL targets: +TEXT ·mvcSrcToBuf(SB), NOFRAME|NOSPLIT, $0 + MVC $1, (R1), (R8) + RET + +TEXT ·mvcBufToDst(SB), NOFRAME|NOSPLIT, $0 + MVC $1, (R8), (R9) + RET + +#define BSWAP V5 +#define J0 V6 +#define KEY0 V7 +#define KEY1 V8 +#define NONCE V9 +#define CTR V10 +#define M0 V11 +#define M1 V12 +#define M2 V13 +#define M3 V14 +#define INC V15 +#define X0 V16 +#define X1 V17 +#define X2 V18 +#define X3 V19 +#define X4 V20 +#define X5 V21 +#define X6 V22 +#define X7 V23 +#define X8 V24 +#define X9 V25 +#define X10 V26 +#define X11 V27 +#define X12 V28 +#define X13 V29 +#define X14 V30 +#define X15 V31 + +#define NUM_ROUNDS 20 + +#define ROUND4(a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3) \ + VAF a1, a0, a0 \ + VAF b1, b0, b0 \ + VAF c1, c0, c0 \ + VAF d1, d0, d0 \ + VX a0, a2, a2 \ + VX b0, b2, b2 \ + VX c0, c2, c2 \ + VX d0, d2, d2 \ + VERLLF $16, a2, a2 \ + VERLLF $16, b2, b2 \ + VERLLF $16, c2, c2 \ + VERLLF $16, d2, d2 \ + VAF a2, a3, a3 \ + VAF b2, b3, b3 \ + VAF c2, c3, c3 \ + VAF d2, d3, d3 \ + VX a3, a1, a1 \ + VX b3, b1, b1 \ + VX c3, c1, c1 \ + VX d3, d1, d1 \ + VERLLF $12, a1, a1 \ + VERLLF $12, b1, b1 \ + VERLLF $12, c1, c1 \ + VERLLF $12, d1, d1 \ + VAF a1, a0, a0 \ + VAF b1, b0, b0 \ + VAF c1, c0, c0 \ + VAF d1, d0, d0 \ + VX a0, a2, a2 \ + VX b0, b2, b2 \ + VX c0, c2, c2 \ + VX d0, d2, d2 \ + VERLLF $8, a2, a2 \ + VERLLF $8, b2, b2 \ + VERLLF $8, c2, c2 \ + VERLLF $8, d2, d2 \ + VAF a2, a3, a3 \ + VAF b2, b3, b3 \ + VAF c2, c3, c3 \ + VAF d2, d3, d3 \ + VX a3, a1, a1 \ + VX b3, b1, b1 \ + VX c3, c1, c1 \ + VX d3, d1, d1 \ + VERLLF $7, a1, a1 \ + VERLLF $7, b1, b1 \ + VERLLF $7, c1, c1 \ + VERLLF $7, d1, d1 + +#define PERMUTE(mask, v0, v1, v2, v3) \ + VPERM v0, v0, mask, v0 \ + VPERM v1, v1, mask, v1 \ + VPERM v2, v2, mask, v2 \ + VPERM v3, v3, mask, v3 + +#define ADDV(x, v0, v1, v2, v3) \ + VAF x, v0, v0 \ + VAF x, v1, v1 \ + VAF x, v2, v2 \ + VAF x, v3, v3 + +#define XORV(off, dst, src, v0, v1, v2, v3) \ + VLM off(src), M0, M3 \ + PERMUTE(BSWAP, v0, v1, v2, v3) \ + VX v0, M0, M0 \ + VX v1, M1, M1 \ + VX v2, M2, M2 \ + VX v3, M3, M3 \ + VSTM M0, M3, off(dst) + +#define SHUFFLE(a, b, c, d, t, u, v, w) \ + VMRHF a, c, t \ // t = {a[0], c[0], a[1], c[1]} + VMRHF b, d, u \ // u = {b[0], d[0], b[1], d[1]} + VMRLF a, c, v \ // v = {a[2], c[2], a[3], c[3]} + VMRLF b, d, w \ // w = {b[2], d[2], b[3], d[3]} + VMRHF t, u, a \ // a = {a[0], b[0], c[0], d[0]} + VMRLF t, u, b \ // b = {a[1], b[1], c[1], d[1]} + VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]} + VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]} + +// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32, buf *[256]byte, len *int) +TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0 + MOVD $·constants<>(SB), R1 + MOVD dst+0(FP), R2 // R2=&dst[0] + LMG src+24(FP), R3, R4 // R3=&src[0] R4=len(src) + MOVD key+48(FP), R5 // R5=key + MOVD nonce+56(FP), R6 // R6=nonce + MOVD counter+64(FP), R7 // R7=counter + MOVD buf+72(FP), R8 // R8=buf + MOVD len+80(FP), R9 // R9=len + + // load BSWAP and J0 + VLM (R1), BSWAP, J0 + + // set up tail buffer + ADD $-1, R4, R12 + MOVBZ R12, R12 + CMPUBEQ R12, $255, aligned + MOVD R4, R1 + AND $~255, R1 + MOVD $(R3)(R1*1), R1 + EXRL $·mvcSrcToBuf(SB), R12 + MOVD $255, R0 + SUB R12, R0 + MOVD R0, (R9) // update len + +aligned: + // setup + MOVD $95, R0 + VLM (R5), KEY0, KEY1 + VLL R0, (R6), NONCE + VZERO M0 + VLEIB $7, $32, M0 + VSRLB M0, NONCE, NONCE + + // initialize counter values + VLREPF (R7), CTR + VZERO INC + VLEIF $1, $1, INC + VLEIF $2, $2, INC + VLEIF $3, $3, INC + VAF INC, CTR, CTR + VREPIF $4, INC + +chacha: + VREPF $0, J0, X0 + VREPF $1, J0, X1 + VREPF $2, J0, X2 + VREPF $3, J0, X3 + VREPF $0, KEY0, X4 + VREPF $1, KEY0, X5 + VREPF $2, KEY0, X6 + VREPF $3, KEY0, X7 + VREPF $0, KEY1, X8 + VREPF $1, KEY1, X9 + VREPF $2, KEY1, X10 + VREPF $3, KEY1, X11 + VLR CTR, X12 + VREPF $1, NONCE, X13 + VREPF $2, NONCE, X14 + VREPF $3, NONCE, X15 + + MOVD $(NUM_ROUNDS/2), R1 + +loop: + ROUND4(X0, X4, X12, X8, X1, X5, X13, X9, X2, X6, X14, X10, X3, X7, X15, X11) + ROUND4(X0, X5, X15, X10, X1, X6, X12, X11, X2, X7, X13, X8, X3, X4, X14, X9) + + ADD $-1, R1 + BNE loop + + // decrement length + ADD $-256, R4 + BLT tail + +continue: + // rearrange vectors + SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3) + ADDV(J0, X0, X1, X2, X3) + SHUFFLE(X4, X5, X6, X7, M0, M1, M2, M3) + ADDV(KEY0, X4, X5, X6, X7) + SHUFFLE(X8, X9, X10, X11, M0, M1, M2, M3) + ADDV(KEY1, X8, X9, X10, X11) + VAF CTR, X12, X12 + SHUFFLE(X12, X13, X14, X15, M0, M1, M2, M3) + ADDV(NONCE, X12, X13, X14, X15) + + // increment counters + VAF INC, CTR, CTR + + // xor keystream with plaintext + XORV(0*64, R2, R3, X0, X4, X8, X12) + XORV(1*64, R2, R3, X1, X5, X9, X13) + XORV(2*64, R2, R3, X2, X6, X10, X14) + XORV(3*64, R2, R3, X3, X7, X11, X15) + + // increment pointers + MOVD $256(R2), R2 + MOVD $256(R3), R3 + + CMPBNE R4, $0, chacha + CMPUBEQ R12, $255, return + EXRL $·mvcBufToDst(SB), R12 // len was updated during setup + +return: + VSTEF $0, CTR, (R7) + RET + +tail: + MOVD R2, R9 + MOVD R8, R2 + MOVD R8, R3 + MOVD $0, R4 + JMP continue + +// func hasVectorFacility() bool +TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1 + MOVD $x-24(SP), R1 + XC $24, 0(R1), 0(R1) // clear the storage + MOVD $2, R0 // R0 is the number of double words stored -1 + WORD $0xB2B01000 // STFLE 0(R1) + XOR R0, R0 // reset the value of R0 + MOVBZ z-8(SP), R1 + AND $0x40, R1 + BEQ novector + +vectorinstalled: + // check if the vector instruction has been enabled + VLEIB $0, $0xF, V16 + VLGVB $0, V16, R1 + CMPBNE R1, $0xF, novector + MOVB $1, ret+0(FP) // have vx + RET + +novector: + MOVB $0, ret+0(FP) // no vx + RET diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing.go new file mode 100644 index 0000000000..f38797bfa1 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/subtle/aliasing.go @@ -0,0 +1,32 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine + +// Package subtle implements functions that are often useful in cryptographic +// code but require careful thought to use correctly. +package subtle // import "golang.org/x/crypto/internal/subtle" + +import "unsafe" + +// AnyOverlap reports whether x and y share memory at any (not necessarily +// corresponding) index. The memory beyond the slice length is ignored. +func AnyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && + uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) +} + +// InexactOverlap reports whether x and y share memory at any non-corresponding +// index. The memory beyond the slice length is ignored. Note that x and y can +// have different lengths and still not have any inexact overlap. +// +// InexactOverlap can be used to implement the requirements of the crypto/cipher +// AEAD, Block, BlockMode and Stream interfaces. +func InexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return AnyOverlap(x, y) +} diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go new file mode 100644 index 0000000000..0cc4a8a642 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go @@ -0,0 +1,35 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build appengine + +// Package subtle implements functions that are often useful in cryptographic +// code but require careful thought to use correctly. +package subtle // import "golang.org/x/crypto/internal/subtle" + +// This is the Google App Engine standard variant based on reflect +// because the unsafe package and cgo are disallowed. + +import "reflect" + +// AnyOverlap reports whether x and y share memory at any (not necessarily +// corresponding) index. The memory beyond the slice length is ignored. +func AnyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() && + reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer() +} + +// InexactOverlap reports whether x and y share memory at any non-corresponding +// index. The memory beyond the slice length is ignored. Note that x and y can +// have different lengths and still not have any inexact overlap. +// +// InexactOverlap can be used to implement the requirements of the crypto/cipher +// AEAD, Block, BlockMode and Stream interfaces. +func InexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return AnyOverlap(x, y) +} diff --git a/vendor/golang.org/x/crypto/openpgp/keys.go b/vendor/golang.org/x/crypto/openpgp/keys.go index fd582a89c0..a79a8c13ae 100644 --- a/vendor/golang.org/x/crypto/openpgp/keys.go +++ b/vendor/golang.org/x/crypto/openpgp/keys.go @@ -346,22 +346,25 @@ EachPacket: switch pkt := p.(type) { case *packet.UserId: + // Make a new Identity object, that we might wind up throwing away. + // We'll only add it if we get a valid self-signature over this + // userID. current = new(Identity) current.Name = pkt.Id current.UserId = pkt - e.Identities[pkt.Id] = current for { p, err = packets.Next() if err == io.EOF { - return nil, io.ErrUnexpectedEOF + break EachPacket } else if err != nil { return nil, err } sig, ok := p.(*packet.Signature) if !ok { - return nil, errors.StructuralError("user ID packet not followed by self-signature") + packets.Unread(p) + continue EachPacket } if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { @@ -369,9 +372,10 @@ EachPacket: return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error()) } current.SelfSignature = sig - break + e.Identities[pkt.Id] = current + } else { + current.Signatures = append(current.Signatures, sig) } - current.Signatures = append(current.Signatures, sig) } case *packet.Signature: if pkt.SigType == packet.SigTypeKeyRevocation { @@ -500,6 +504,10 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err IssuerKeyId: &e.PrimaryKey.KeyId, }, } + err = e.Identities[uid.Id].SelfSignature.SignUserId(uid.Id, e.PrimaryKey, e.PrivateKey, config) + if err != nil { + return nil, err + } // If the user passes in a DefaultHash via packet.Config, // set the PreferredHash for the SelfSignature. @@ -529,13 +537,16 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err } e.Subkeys[0].PublicKey.IsSubkey = true e.Subkeys[0].PrivateKey.IsSubkey = true - + err = e.Subkeys[0].Sig.SignKey(e.Subkeys[0].PublicKey, e.PrivateKey, config) + if err != nil { + return nil, err + } return e, nil } -// SerializePrivate serializes an Entity, including private key material, to -// the given Writer. For now, it must only be used on an Entity returned from -// NewEntity. +// SerializePrivate serializes an Entity, including private key material, but +// excluding signatures from other entities, to the given Writer. +// Identities and subkeys are re-signed in case they changed since NewEntry. // If config is nil, sensible defaults will be used. func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { err = e.PrivateKey.Serialize(w) @@ -573,8 +584,8 @@ func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error return nil } -// Serialize writes the public part of the given Entity to w. (No private -// key material will be output). +// Serialize writes the public part of the given Entity to w, including +// signatures from other entities. No private key material will be output. func (e *Entity) Serialize(w io.Writer) error { err := e.PrimaryKey.Serialize(w) if err != nil { diff --git a/vendor/golang.org/x/crypto/openpgp/write.go b/vendor/golang.org/x/crypto/openpgp/write.go index 65a304cc86..d6dede74e9 100644 --- a/vendor/golang.org/x/crypto/openpgp/write.go +++ b/vendor/golang.org/x/crypto/openpgp/write.go @@ -164,12 +164,12 @@ func hashToHashId(h crypto.Hash) uint8 { return v } -// Encrypt encrypts a message to a number of recipients and, optionally, signs -// it. hints contains optional information, that is also encrypted, that aids -// the recipients in processing the message. The resulting WriteCloser must -// be closed after the contents of the file have been written. -// If config is nil, sensible defaults will be used. -func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { +// writeAndSign writes the data as a payload package and, optionally, signs +// it. hints contains optional information, that is also encrypted, +// that aids the recipients in processing the message. The resulting +// WriteCloser must be closed after the contents of the file have been +// written. If config is nil, sensible defaults will be used. +func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { var signer *packet.PrivateKey if signed != nil { signKey, ok := signed.signingKey(config.Now()) @@ -185,6 +185,83 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint } } + var hash crypto.Hash + for _, hashId := range candidateHashes { + if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() { + hash = h + break + } + } + + // If the hash specified by config is a candidate, we'll use that. + if configuredHash := config.Hash(); configuredHash.Available() { + for _, hashId := range candidateHashes { + if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash { + hash = h + break + } + } + } + + if hash == 0 { + hashId := candidateHashes[0] + name, ok := s2k.HashIdToString(hashId) + if !ok { + name = "#" + strconv.Itoa(int(hashId)) + } + return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)") + } + + if signer != nil { + ops := &packet.OnePassSignature{ + SigType: packet.SigTypeBinary, + Hash: hash, + PubKeyAlgo: signer.PubKeyAlgo, + KeyId: signer.KeyId, + IsLast: true, + } + if err := ops.Serialize(payload); err != nil { + return nil, err + } + } + + if hints == nil { + hints = &FileHints{} + } + + w := payload + if signer != nil { + // If we need to write a signature packet after the literal + // data then we need to stop literalData from closing + // encryptedData. + w = noOpCloser{w} + + } + var epochSeconds uint32 + if !hints.ModTime.IsZero() { + epochSeconds = uint32(hints.ModTime.Unix()) + } + literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) + if err != nil { + return nil, err + } + + if signer != nil { + return signatureWriter{payload, literalData, hash, hash.New(), signer, config}, nil + } + return literalData, nil +} + +// Encrypt encrypts a message to a number of recipients and, optionally, signs +// it. hints contains optional information, that is also encrypted, that aids +// the recipients in processing the message. The resulting WriteCloser must +// be closed after the contents of the file have been written. +// If config is nil, sensible defaults will be used. +func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + if len(to) == 0 { + return nil, errors.InvalidArgumentError("no encryption recipient provided") + } + // These are the possible ciphers that we'll use for the message. candidateCiphers := []uint8{ uint8(packet.CipherAES128), @@ -241,33 +318,6 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint } } - var hash crypto.Hash - for _, hashId := range candidateHashes { - if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() { - hash = h - break - } - } - - // If the hash specified by config is a candidate, we'll use that. - if configuredHash := config.Hash(); configuredHash.Available() { - for _, hashId := range candidateHashes { - if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash { - hash = h - break - } - } - } - - if hash == 0 { - hashId := candidateHashes[0] - name, ok := s2k.HashIdToString(hashId) - if !ok { - name = "#" + strconv.Itoa(int(hashId)) - } - return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)") - } - symKey := make([]byte, cipher.KeySize()) if _, err := io.ReadFull(config.Random(), symKey); err != nil { return nil, err @@ -279,49 +329,37 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint } } - encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) + payload, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) if err != nil { return } - if signer != nil { - ops := &packet.OnePassSignature{ - SigType: packet.SigTypeBinary, - Hash: hash, - PubKeyAlgo: signer.PubKeyAlgo, - KeyId: signer.KeyId, - IsLast: true, - } - if err := ops.Serialize(encryptedData); err != nil { - return nil, err - } + return writeAndSign(payload, candidateHashes, signed, hints, config) +} + +// Sign signs a message. The resulting WriteCloser must be closed after the +// contents of the file have been written. hints contains optional information +// that aids the recipients in processing the message. +// If config is nil, sensible defaults will be used. +func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Config) (input io.WriteCloser, err error) { + if signed == nil { + return nil, errors.InvalidArgumentError("no signer provided") } - if hints == nil { - hints = &FileHints{} + // These are the possible hash functions that we'll use for the signature. + candidateHashes := []uint8{ + hashToHashId(crypto.SHA256), + hashToHashId(crypto.SHA512), + hashToHashId(crypto.SHA1), + hashToHashId(crypto.RIPEMD160), } - - w := encryptedData - if signer != nil { - // If we need to write a signature packet after the literal - // data then we need to stop literalData from closing - // encryptedData. - w = noOpCloser{encryptedData} - + defaultHashes := candidateHashes[len(candidateHashes)-1:] + preferredHashes := signed.primaryIdentity().SelfSignature.PreferredHash + if len(preferredHashes) == 0 { + preferredHashes = defaultHashes } - var epochSeconds uint32 - if !hints.ModTime.IsZero() { - epochSeconds = uint32(hints.ModTime.Unix()) - } - literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) - if err != nil { - return nil, err - } - - if signer != nil { - return signatureWriter{encryptedData, literalData, hash, hash.New(), signer, config}, nil - } - return literalData, nil + candidateHashes = intersectPreferences(candidateHashes, preferredHashes) + return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, config) } // signatureWriter hashes the contents of a message while passing it along to diff --git a/vendor/golang.org/x/crypto/poly1305/sum_noasm.go b/vendor/golang.org/x/crypto/poly1305/sum_noasm.go new file mode 100644 index 0000000000..751eec5274 --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_noasm.go @@ -0,0 +1,14 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build s390x,!go1.11 !arm,!amd64,!s390x gccgo appengine nacl + +package poly1305 + +// Sum generates an authenticator for msg using a one-time key and puts the +// 16-byte result into out. Authenticating two different messages with the same +// key allows an attacker to forge messages at will. +func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) { + sumGeneric(out, msg, key) +} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ref.go b/vendor/golang.org/x/crypto/poly1305/sum_ref.go index b2805a5ca1..c4d59bd098 100644 --- a/vendor/golang.org/x/crypto/poly1305/sum_ref.go +++ b/vendor/golang.org/x/crypto/poly1305/sum_ref.go @@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64,!arm gccgo appengine nacl - package poly1305 import "encoding/binary" -// Sum generates an authenticator for msg using a one-time key and puts the -// 16-byte result into out. Authenticating two different messages with the same -// key allows an attacker to forge messages at will. -func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) { +// sumGeneric generates an authenticator for msg using a one-time key and +// puts the 16-byte result into out. This is the generic implementation of +// Sum and should be called if no assembly implementation is available. +func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) { var ( h0, h1, h2, h3, h4 uint32 // the hash accumulators r0, r1, r2, r3, r4 uint64 // the r part of the key diff --git a/vendor/golang.org/x/crypto/poly1305/sum_s390x.go b/vendor/golang.org/x/crypto/poly1305/sum_s390x.go new file mode 100644 index 0000000000..7a266cece4 --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_s390x.go @@ -0,0 +1,49 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build s390x,go1.11,!gccgo,!appengine + +package poly1305 + +// hasVectorFacility reports whether the machine supports +// the vector facility (vx). +func hasVectorFacility() bool + +// hasVMSLFacility reports whether the machine supports +// Vector Multiply Sum Logical (VMSL). +func hasVMSLFacility() bool + +var hasVX = hasVectorFacility() +var hasVMSL = hasVMSLFacility() + +// poly1305vx is an assembly implementation of Poly1305 that uses vector +// instructions. It must only be called if the vector facility (vx) is +// available. +//go:noescape +func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]byte) + +// poly1305vmsl is an assembly implementation of Poly1305 that uses vector +// instructions, including VMSL. It must only be called if the vector facility (vx) is +// available and if VMSL is supported. +//go:noescape +func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]byte) + +// Sum generates an authenticator for m using a one-time key and puts the +// 16-byte result into out. Authenticating two different messages with the same +// key allows an attacker to forge messages at will. +func Sum(out *[16]byte, m []byte, key *[32]byte) { + if hasVX { + var mPtr *byte + if len(m) > 0 { + mPtr = &m[0] + } + if hasVMSL && len(m) > 256 { + poly1305vmsl(out, mPtr, uint64(len(m)), key) + } else { + poly1305vx(out, mPtr, uint64(len(m)), key) + } + } else { + sumGeneric(out, m, key) + } +} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_s390x.s b/vendor/golang.org/x/crypto/poly1305/sum_s390x.s new file mode 100644 index 0000000000..356c07a6c2 --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_s390x.s @@ -0,0 +1,400 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build s390x,go1.11,!gccgo,!appengine + +#include "textflag.h" + +// Implementation of Poly1305 using the vector facility (vx). + +// constants +#define MOD26 V0 +#define EX0 V1 +#define EX1 V2 +#define EX2 V3 + +// temporaries +#define T_0 V4 +#define T_1 V5 +#define T_2 V6 +#define T_3 V7 +#define T_4 V8 + +// key (r) +#define R_0 V9 +#define R_1 V10 +#define R_2 V11 +#define R_3 V12 +#define R_4 V13 +#define R5_1 V14 +#define R5_2 V15 +#define R5_3 V16 +#define R5_4 V17 +#define RSAVE_0 R5 +#define RSAVE_1 R6 +#define RSAVE_2 R7 +#define RSAVE_3 R8 +#define RSAVE_4 R9 +#define R5SAVE_1 V28 +#define R5SAVE_2 V29 +#define R5SAVE_3 V30 +#define R5SAVE_4 V31 + +// message block +#define F_0 V18 +#define F_1 V19 +#define F_2 V20 +#define F_3 V21 +#define F_4 V22 + +// accumulator +#define H_0 V23 +#define H_1 V24 +#define H_2 V25 +#define H_3 V26 +#define H_4 V27 + +GLOBL ·keyMask<>(SB), RODATA, $16 +DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f +DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f + +GLOBL ·bswapMask<>(SB), RODATA, $16 +DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908 +DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100 + +GLOBL ·constants<>(SB), RODATA, $64 +// MOD26 +DATA ·constants<>+0(SB)/8, $0x3ffffff +DATA ·constants<>+8(SB)/8, $0x3ffffff +// EX0 +DATA ·constants<>+16(SB)/8, $0x0006050403020100 +DATA ·constants<>+24(SB)/8, $0x1016151413121110 +// EX1 +DATA ·constants<>+32(SB)/8, $0x060c0b0a09080706 +DATA ·constants<>+40(SB)/8, $0x161c1b1a19181716 +// EX2 +DATA ·constants<>+48(SB)/8, $0x0d0d0d0d0d0f0e0d +DATA ·constants<>+56(SB)/8, $0x1d1d1d1d1d1f1e1d + +// h = (f*g) % (2**130-5) [partial reduction] +#define MULTIPLY(f0, f1, f2, f3, f4, g0, g1, g2, g3, g4, g51, g52, g53, g54, h0, h1, h2, h3, h4) \ + VMLOF f0, g0, h0 \ + VMLOF f0, g1, h1 \ + VMLOF f0, g2, h2 \ + VMLOF f0, g3, h3 \ + VMLOF f0, g4, h4 \ + VMLOF f1, g54, T_0 \ + VMLOF f1, g0, T_1 \ + VMLOF f1, g1, T_2 \ + VMLOF f1, g2, T_3 \ + VMLOF f1, g3, T_4 \ + VMALOF f2, g53, h0, h0 \ + VMALOF f2, g54, h1, h1 \ + VMALOF f2, g0, h2, h2 \ + VMALOF f2, g1, h3, h3 \ + VMALOF f2, g2, h4, h4 \ + VMALOF f3, g52, T_0, T_0 \ + VMALOF f3, g53, T_1, T_1 \ + VMALOF f3, g54, T_2, T_2 \ + VMALOF f3, g0, T_3, T_3 \ + VMALOF f3, g1, T_4, T_4 \ + VMALOF f4, g51, h0, h0 \ + VMALOF f4, g52, h1, h1 \ + VMALOF f4, g53, h2, h2 \ + VMALOF f4, g54, h3, h3 \ + VMALOF f4, g0, h4, h4 \ + VAG T_0, h0, h0 \ + VAG T_1, h1, h1 \ + VAG T_2, h2, h2 \ + VAG T_3, h3, h3 \ + VAG T_4, h4, h4 + +// carry h0->h1 h3->h4, h1->h2 h4->h0, h0->h1 h2->h3, h3->h4 +#define REDUCE(h0, h1, h2, h3, h4) \ + VESRLG $26, h0, T_0 \ + VESRLG $26, h3, T_1 \ + VN MOD26, h0, h0 \ + VN MOD26, h3, h3 \ + VAG T_0, h1, h1 \ + VAG T_1, h4, h4 \ + VESRLG $26, h1, T_2 \ + VESRLG $26, h4, T_3 \ + VN MOD26, h1, h1 \ + VN MOD26, h4, h4 \ + VESLG $2, T_3, T_4 \ + VAG T_3, T_4, T_4 \ + VAG T_2, h2, h2 \ + VAG T_4, h0, h0 \ + VESRLG $26, h2, T_0 \ + VESRLG $26, h0, T_1 \ + VN MOD26, h2, h2 \ + VN MOD26, h0, h0 \ + VAG T_0, h3, h3 \ + VAG T_1, h1, h1 \ + VESRLG $26, h3, T_2 \ + VN MOD26, h3, h3 \ + VAG T_2, h4, h4 + +// expand in0 into d[0] and in1 into d[1] +#define EXPAND(in0, in1, d0, d1, d2, d3, d4) \ + VGBM $0x0707, d1 \ // d1=tmp + VPERM in0, in1, EX2, d4 \ + VPERM in0, in1, EX0, d0 \ + VPERM in0, in1, EX1, d2 \ + VN d1, d4, d4 \ + VESRLG $26, d0, d1 \ + VESRLG $30, d2, d3 \ + VESRLG $4, d2, d2 \ + VN MOD26, d0, d0 \ + VN MOD26, d1, d1 \ + VN MOD26, d2, d2 \ + VN MOD26, d3, d3 + +// pack h4:h0 into h1:h0 (no carry) +#define PACK(h0, h1, h2, h3, h4) \ + VESLG $26, h1, h1 \ + VESLG $26, h3, h3 \ + VO h0, h1, h0 \ + VO h2, h3, h2 \ + VESLG $4, h2, h2 \ + VLEIB $7, $48, h1 \ + VSLB h1, h2, h2 \ + VO h0, h2, h0 \ + VLEIB $7, $104, h1 \ + VSLB h1, h4, h3 \ + VO h3, h0, h0 \ + VLEIB $7, $24, h1 \ + VSRLB h1, h4, h1 + +// if h > 2**130-5 then h -= 2**130-5 +#define MOD(h0, h1, t0, t1, t2) \ + VZERO t0 \ + VLEIG $1, $5, t0 \ + VACCQ h0, t0, t1 \ + VAQ h0, t0, t0 \ + VONE t2 \ + VLEIG $1, $-4, t2 \ + VAQ t2, t1, t1 \ + VACCQ h1, t1, t1 \ + VONE t2 \ + VAQ t2, t1, t1 \ + VN h0, t1, t2 \ + VNC t0, t1, t1 \ + VO t1, t2, h0 + +// func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]key) +TEXT ·poly1305vx(SB), $0-32 + // This code processes up to 2 blocks (32 bytes) per iteration + // using the algorithm described in: + // NEON crypto, Daniel J. Bernstein & Peter Schwabe + // https://cryptojedi.org/papers/neoncrypto-20120320.pdf + LMG out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key + + // load MOD26, EX0, EX1 and EX2 + MOVD $·constants<>(SB), R5 + VLM (R5), MOD26, EX2 + + // setup r + VL (R4), T_0 + MOVD $·keyMask<>(SB), R6 + VL (R6), T_1 + VN T_0, T_1, T_0 + EXPAND(T_0, T_0, R_0, R_1, R_2, R_3, R_4) + + // setup r*5 + VLEIG $0, $5, T_0 + VLEIG $1, $5, T_0 + + // store r (for final block) + VMLOF T_0, R_1, R5SAVE_1 + VMLOF T_0, R_2, R5SAVE_2 + VMLOF T_0, R_3, R5SAVE_3 + VMLOF T_0, R_4, R5SAVE_4 + VLGVG $0, R_0, RSAVE_0 + VLGVG $0, R_1, RSAVE_1 + VLGVG $0, R_2, RSAVE_2 + VLGVG $0, R_3, RSAVE_3 + VLGVG $0, R_4, RSAVE_4 + + // skip r**2 calculation + CMPBLE R3, $16, skip + + // calculate r**2 + MULTIPLY(R_0, R_1, R_2, R_3, R_4, R_0, R_1, R_2, R_3, R_4, R5SAVE_1, R5SAVE_2, R5SAVE_3, R5SAVE_4, H_0, H_1, H_2, H_3, H_4) + REDUCE(H_0, H_1, H_2, H_3, H_4) + VLEIG $0, $5, T_0 + VLEIG $1, $5, T_0 + VMLOF T_0, H_1, R5_1 + VMLOF T_0, H_2, R5_2 + VMLOF T_0, H_3, R5_3 + VMLOF T_0, H_4, R5_4 + VLR H_0, R_0 + VLR H_1, R_1 + VLR H_2, R_2 + VLR H_3, R_3 + VLR H_4, R_4 + + // initialize h + VZERO H_0 + VZERO H_1 + VZERO H_2 + VZERO H_3 + VZERO H_4 + +loop: + CMPBLE R3, $32, b2 + VLM (R2), T_0, T_1 + SUB $32, R3 + MOVD $32(R2), R2 + EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4) + VLEIB $4, $1, F_4 + VLEIB $12, $1, F_4 + +multiply: + VAG H_0, F_0, F_0 + VAG H_1, F_1, F_1 + VAG H_2, F_2, F_2 + VAG H_3, F_3, F_3 + VAG H_4, F_4, F_4 + MULTIPLY(F_0, F_1, F_2, F_3, F_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, H_0, H_1, H_2, H_3, H_4) + REDUCE(H_0, H_1, H_2, H_3, H_4) + CMPBNE R3, $0, loop + +finish: + // sum vectors + VZERO T_0 + VSUMQG H_0, T_0, H_0 + VSUMQG H_1, T_0, H_1 + VSUMQG H_2, T_0, H_2 + VSUMQG H_3, T_0, H_3 + VSUMQG H_4, T_0, H_4 + + // h may be >= 2*(2**130-5) so we need to reduce it again + REDUCE(H_0, H_1, H_2, H_3, H_4) + + // carry h1->h4 + VESRLG $26, H_1, T_1 + VN MOD26, H_1, H_1 + VAQ T_1, H_2, H_2 + VESRLG $26, H_2, T_2 + VN MOD26, H_2, H_2 + VAQ T_2, H_3, H_3 + VESRLG $26, H_3, T_3 + VN MOD26, H_3, H_3 + VAQ T_3, H_4, H_4 + + // h is now < 2*(2**130-5) + // pack h into h1 (hi) and h0 (lo) + PACK(H_0, H_1, H_2, H_3, H_4) + + // if h > 2**130-5 then h -= 2**130-5 + MOD(H_0, H_1, T_0, T_1, T_2) + + // h += s + MOVD $·bswapMask<>(SB), R5 + VL (R5), T_1 + VL 16(R4), T_0 + VPERM T_0, T_0, T_1, T_0 // reverse bytes (to big) + VAQ T_0, H_0, H_0 + VPERM H_0, H_0, T_1, H_0 // reverse bytes (to little) + VST H_0, (R1) + + RET + +b2: + CMPBLE R3, $16, b1 + + // 2 blocks remaining + SUB $17, R3 + VL (R2), T_0 + VLL R3, 16(R2), T_1 + ADD $1, R3 + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, T_1 + EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4) + CMPBNE R3, $16, 2(PC) + VLEIB $12, $1, F_4 + VLEIB $4, $1, F_4 + + // setup [r²,r] + VLVGG $1, RSAVE_0, R_0 + VLVGG $1, RSAVE_1, R_1 + VLVGG $1, RSAVE_2, R_2 + VLVGG $1, RSAVE_3, R_3 + VLVGG $1, RSAVE_4, R_4 + VPDI $0, R5_1, R5SAVE_1, R5_1 + VPDI $0, R5_2, R5SAVE_2, R5_2 + VPDI $0, R5_3, R5SAVE_3, R5_3 + VPDI $0, R5_4, R5SAVE_4, R5_4 + + MOVD $0, R3 + BR multiply + +skip: + VZERO H_0 + VZERO H_1 + VZERO H_2 + VZERO H_3 + VZERO H_4 + + CMPBEQ R3, $0, finish + +b1: + // 1 block remaining + SUB $1, R3 + VLL R3, (R2), T_0 + ADD $1, R3 + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, T_0 + VZERO T_1 + EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4) + CMPBNE R3, $16, 2(PC) + VLEIB $4, $1, F_4 + VLEIG $1, $1, R_0 + VZERO R_1 + VZERO R_2 + VZERO R_3 + VZERO R_4 + VZERO R5_1 + VZERO R5_2 + VZERO R5_3 + VZERO R5_4 + + // setup [r, 1] + VLVGG $0, RSAVE_0, R_0 + VLVGG $0, RSAVE_1, R_1 + VLVGG $0, RSAVE_2, R_2 + VLVGG $0, RSAVE_3, R_3 + VLVGG $0, RSAVE_4, R_4 + VPDI $0, R5SAVE_1, R5_1, R5_1 + VPDI $0, R5SAVE_2, R5_2, R5_2 + VPDI $0, R5SAVE_3, R5_3, R5_3 + VPDI $0, R5SAVE_4, R5_4, R5_4 + + MOVD $0, R3 + BR multiply + +TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1 + MOVD $x-24(SP), R1 + XC $24, 0(R1), 0(R1) // clear the storage + MOVD $2, R0 // R0 is the number of double words stored -1 + WORD $0xB2B01000 // STFLE 0(R1) + XOR R0, R0 // reset the value of R0 + MOVBZ z-8(SP), R1 + AND $0x40, R1 + BEQ novector + +vectorinstalled: + // check if the vector instruction has been enabled + VLEIB $0, $0xF, V16 + VLGVB $0, V16, R1 + CMPBNE R1, $0xF, novector + MOVB $1, ret+0(FP) // have vx + RET + +novector: + MOVB $0, ret+0(FP) // no vx + RET diff --git a/vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s b/vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s new file mode 100644 index 0000000000..e548020b14 --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s @@ -0,0 +1,931 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build s390x,go1.11,!gccgo,!appengine + +#include "textflag.h" + +// Implementation of Poly1305 using the vector facility (vx) and the VMSL instruction. + +// constants +#define EX0 V1 +#define EX1 V2 +#define EX2 V3 + +// temporaries +#define T_0 V4 +#define T_1 V5 +#define T_2 V6 +#define T_3 V7 +#define T_4 V8 +#define T_5 V9 +#define T_6 V10 +#define T_7 V11 +#define T_8 V12 +#define T_9 V13 +#define T_10 V14 + +// r**2 & r**4 +#define R_0 V15 +#define R_1 V16 +#define R_2 V17 +#define R5_1 V18 +#define R5_2 V19 +// key (r) +#define RSAVE_0 R7 +#define RSAVE_1 R8 +#define RSAVE_2 R9 +#define R5SAVE_1 R10 +#define R5SAVE_2 R11 + +// message block +#define M0 V20 +#define M1 V21 +#define M2 V22 +#define M3 V23 +#define M4 V24 +#define M5 V25 + +// accumulator +#define H0_0 V26 +#define H1_0 V27 +#define H2_0 V28 +#define H0_1 V29 +#define H1_1 V30 +#define H2_1 V31 + +GLOBL ·keyMask<>(SB), RODATA, $16 +DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f +DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f + +GLOBL ·bswapMask<>(SB), RODATA, $16 +DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908 +DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100 + +GLOBL ·constants<>(SB), RODATA, $48 +// EX0 +DATA ·constants<>+0(SB)/8, $0x18191a1b1c1d1e1f +DATA ·constants<>+8(SB)/8, $0x0000050403020100 +// EX1 +DATA ·constants<>+16(SB)/8, $0x18191a1b1c1d1e1f +DATA ·constants<>+24(SB)/8, $0x00000a0908070605 +// EX2 +DATA ·constants<>+32(SB)/8, $0x18191a1b1c1d1e1f +DATA ·constants<>+40(SB)/8, $0x0000000f0e0d0c0b + +GLOBL ·c<>(SB), RODATA, $48 +// EX0 +DATA ·c<>+0(SB)/8, $0x0000050403020100 +DATA ·c<>+8(SB)/8, $0x0000151413121110 +// EX1 +DATA ·c<>+16(SB)/8, $0x00000a0908070605 +DATA ·c<>+24(SB)/8, $0x00001a1918171615 +// EX2 +DATA ·c<>+32(SB)/8, $0x0000000f0e0d0c0b +DATA ·c<>+40(SB)/8, $0x0000001f1e1d1c1b + +GLOBL ·reduce<>(SB), RODATA, $32 +// 44 bit +DATA ·reduce<>+0(SB)/8, $0x0 +DATA ·reduce<>+8(SB)/8, $0xfffffffffff +// 42 bit +DATA ·reduce<>+16(SB)/8, $0x0 +DATA ·reduce<>+24(SB)/8, $0x3ffffffffff + +// h = (f*g) % (2**130-5) [partial reduction] +// uses T_0...T_9 temporary registers +// input: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2 +// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9 +// output: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2 +#define MULTIPLY(m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) \ + \ // Eliminate the dependency for the last 2 VMSLs + VMSLG m02_0, r_2, m4_2, m4_2 \ + VMSLG m13_0, r_2, m5_2, m5_2 \ // 8 VMSLs pipelined + VMSLG m02_0, r_0, m4_0, m4_0 \ + VMSLG m02_1, r5_2, V0, T_0 \ + VMSLG m02_0, r_1, m4_1, m4_1 \ + VMSLG m02_1, r_0, V0, T_1 \ + VMSLG m02_1, r_1, V0, T_2 \ + VMSLG m02_2, r5_1, V0, T_3 \ + VMSLG m02_2, r5_2, V0, T_4 \ + VMSLG m13_0, r_0, m5_0, m5_0 \ + VMSLG m13_1, r5_2, V0, T_5 \ + VMSLG m13_0, r_1, m5_1, m5_1 \ + VMSLG m13_1, r_0, V0, T_6 \ + VMSLG m13_1, r_1, V0, T_7 \ + VMSLG m13_2, r5_1, V0, T_8 \ + VMSLG m13_2, r5_2, V0, T_9 \ + VMSLG m02_2, r_0, m4_2, m4_2 \ + VMSLG m13_2, r_0, m5_2, m5_2 \ + VAQ m4_0, T_0, m02_0 \ + VAQ m4_1, T_1, m02_1 \ + VAQ m5_0, T_5, m13_0 \ + VAQ m5_1, T_6, m13_1 \ + VAQ m02_0, T_3, m02_0 \ + VAQ m02_1, T_4, m02_1 \ + VAQ m13_0, T_8, m13_0 \ + VAQ m13_1, T_9, m13_1 \ + VAQ m4_2, T_2, m02_2 \ + VAQ m5_2, T_7, m13_2 \ + +// SQUARE uses three limbs of r and r_2*5 to output square of r +// uses T_1, T_5 and T_7 temporary registers +// input: r_0, r_1, r_2, r5_2 +// temp: TEMP0, TEMP1, TEMP2 +// output: p0, p1, p2 +#define SQUARE(r_0, r_1, r_2, r5_2, p0, p1, p2, TEMP0, TEMP1, TEMP2) \ + VMSLG r_0, r_0, p0, p0 \ + VMSLG r_1, r5_2, V0, TEMP0 \ + VMSLG r_2, r5_2, p1, p1 \ + VMSLG r_0, r_1, V0, TEMP1 \ + VMSLG r_1, r_1, p2, p2 \ + VMSLG r_0, r_2, V0, TEMP2 \ + VAQ TEMP0, p0, p0 \ + VAQ TEMP1, p1, p1 \ + VAQ TEMP2, p2, p2 \ + VAQ TEMP0, p0, p0 \ + VAQ TEMP1, p1, p1 \ + VAQ TEMP2, p2, p2 \ + +// carry h0->h1->h2->h0 || h3->h4->h5->h3 +// uses T_2, T_4, T_5, T_7, T_8, T_9 +// t6, t7, t8, t9, t10, t11 +// input: h0, h1, h2, h3, h4, h5 +// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11 +// output: h0, h1, h2, h3, h4, h5 +#define REDUCE(h0, h1, h2, h3, h4, h5, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) \ + VLM (R12), t6, t7 \ // 44 and 42 bit clear mask + VLEIB $7, $0x28, t10 \ // 5 byte shift mask + VREPIB $4, t8 \ // 4 bit shift mask + VREPIB $2, t11 \ // 2 bit shift mask + VSRLB t10, h0, t0 \ // h0 byte shift + VSRLB t10, h1, t1 \ // h1 byte shift + VSRLB t10, h2, t2 \ // h2 byte shift + VSRLB t10, h3, t3 \ // h3 byte shift + VSRLB t10, h4, t4 \ // h4 byte shift + VSRLB t10, h5, t5 \ // h5 byte shift + VSRL t8, t0, t0 \ // h0 bit shift + VSRL t8, t1, t1 \ // h2 bit shift + VSRL t11, t2, t2 \ // h2 bit shift + VSRL t8, t3, t3 \ // h3 bit shift + VSRL t8, t4, t4 \ // h4 bit shift + VESLG $2, t2, t9 \ // h2 carry x5 + VSRL t11, t5, t5 \ // h5 bit shift + VN t6, h0, h0 \ // h0 clear carry + VAQ t2, t9, t2 \ // h2 carry x5 + VESLG $2, t5, t9 \ // h5 carry x5 + VN t6, h1, h1 \ // h1 clear carry + VN t7, h2, h2 \ // h2 clear carry + VAQ t5, t9, t5 \ // h5 carry x5 + VN t6, h3, h3 \ // h3 clear carry + VN t6, h4, h4 \ // h4 clear carry + VN t7, h5, h5 \ // h5 clear carry + VAQ t0, h1, h1 \ // h0->h1 + VAQ t3, h4, h4 \ // h3->h4 + VAQ t1, h2, h2 \ // h1->h2 + VAQ t4, h5, h5 \ // h4->h5 + VAQ t2, h0, h0 \ // h2->h0 + VAQ t5, h3, h3 \ // h5->h3 + VREPG $1, t6, t6 \ // 44 and 42 bit masks across both halves + VREPG $1, t7, t7 \ + VSLDB $8, h0, h0, h0 \ // set up [h0/1/2, h3/4/5] + VSLDB $8, h1, h1, h1 \ + VSLDB $8, h2, h2, h2 \ + VO h0, h3, h3 \ + VO h1, h4, h4 \ + VO h2, h5, h5 \ + VESRLG $44, h3, t0 \ // 44 bit shift right + VESRLG $44, h4, t1 \ + VESRLG $42, h5, t2 \ + VN t6, h3, h3 \ // clear carry bits + VN t6, h4, h4 \ + VN t7, h5, h5 \ + VESLG $2, t2, t9 \ // multiply carry by 5 + VAQ t9, t2, t2 \ + VAQ t0, h4, h4 \ + VAQ t1, h5, h5 \ + VAQ t2, h3, h3 \ + +// carry h0->h1->h2->h0 +// input: h0, h1, h2 +// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8 +// output: h0, h1, h2 +#define REDUCE2(h0, h1, h2, t0, t1, t2, t3, t4, t5, t6, t7, t8) \ + VLEIB $7, $0x28, t3 \ // 5 byte shift mask + VREPIB $4, t4 \ // 4 bit shift mask + VREPIB $2, t7 \ // 2 bit shift mask + VGBM $0x003F, t5 \ // mask to clear carry bits + VSRLB t3, h0, t0 \ + VSRLB t3, h1, t1 \ + VSRLB t3, h2, t2 \ + VESRLG $4, t5, t5 \ // 44 bit clear mask + VSRL t4, t0, t0 \ + VSRL t4, t1, t1 \ + VSRL t7, t2, t2 \ + VESRLG $2, t5, t6 \ // 42 bit clear mask + VESLG $2, t2, t8 \ + VAQ t8, t2, t2 \ + VN t5, h0, h0 \ + VN t5, h1, h1 \ + VN t6, h2, h2 \ + VAQ t0, h1, h1 \ + VAQ t1, h2, h2 \ + VAQ t2, h0, h0 \ + VSRLB t3, h0, t0 \ + VSRLB t3, h1, t1 \ + VSRLB t3, h2, t2 \ + VSRL t4, t0, t0 \ + VSRL t4, t1, t1 \ + VSRL t7, t2, t2 \ + VN t5, h0, h0 \ + VN t5, h1, h1 \ + VESLG $2, t2, t8 \ + VN t6, h2, h2 \ + VAQ t0, h1, h1 \ + VAQ t8, t2, t2 \ + VAQ t1, h2, h2 \ + VAQ t2, h0, h0 \ + +// expands two message blocks into the lower halfs of the d registers +// moves the contents of the d registers into upper halfs +// input: in1, in2, d0, d1, d2, d3, d4, d5 +// temp: TEMP0, TEMP1, TEMP2, TEMP3 +// output: d0, d1, d2, d3, d4, d5 +#define EXPACC(in1, in2, d0, d1, d2, d3, d4, d5, TEMP0, TEMP1, TEMP2, TEMP3) \ + VGBM $0xff3f, TEMP0 \ + VGBM $0xff1f, TEMP1 \ + VESLG $4, d1, TEMP2 \ + VESLG $4, d4, TEMP3 \ + VESRLG $4, TEMP0, TEMP0 \ + VPERM in1, d0, EX0, d0 \ + VPERM in2, d3, EX0, d3 \ + VPERM in1, d2, EX2, d2 \ + VPERM in2, d5, EX2, d5 \ + VPERM in1, TEMP2, EX1, d1 \ + VPERM in2, TEMP3, EX1, d4 \ + VN TEMP0, d0, d0 \ + VN TEMP0, d3, d3 \ + VESRLG $4, d1, d1 \ + VESRLG $4, d4, d4 \ + VN TEMP1, d2, d2 \ + VN TEMP1, d5, d5 \ + VN TEMP0, d1, d1 \ + VN TEMP0, d4, d4 \ + +// expands one message block into the lower halfs of the d registers +// moves the contents of the d registers into upper halfs +// input: in, d0, d1, d2 +// temp: TEMP0, TEMP1, TEMP2 +// output: d0, d1, d2 +#define EXPACC2(in, d0, d1, d2, TEMP0, TEMP1, TEMP2) \ + VGBM $0xff3f, TEMP0 \ + VESLG $4, d1, TEMP2 \ + VGBM $0xff1f, TEMP1 \ + VPERM in, d0, EX0, d0 \ + VESRLG $4, TEMP0, TEMP0 \ + VPERM in, d2, EX2, d2 \ + VPERM in, TEMP2, EX1, d1 \ + VN TEMP0, d0, d0 \ + VN TEMP1, d2, d2 \ + VESRLG $4, d1, d1 \ + VN TEMP0, d1, d1 \ + +// pack h2:h0 into h1:h0 (no carry) +// input: h0, h1, h2 +// output: h0, h1, h2 +#define PACK(h0, h1, h2) \ + VMRLG h1, h2, h2 \ // copy h1 to upper half h2 + VESLG $44, h1, h1 \ // shift limb 1 44 bits, leaving 20 + VO h0, h1, h0 \ // combine h0 with 20 bits from limb 1 + VESRLG $20, h2, h1 \ // put top 24 bits of limb 1 into h1 + VLEIG $1, $0, h1 \ // clear h2 stuff from lower half of h1 + VO h0, h1, h0 \ // h0 now has 88 bits (limb 0 and 1) + VLEIG $0, $0, h2 \ // clear upper half of h2 + VESRLG $40, h2, h1 \ // h1 now has upper two bits of result + VLEIB $7, $88, h1 \ // for byte shift (11 bytes) + VSLB h1, h2, h2 \ // shift h2 11 bytes to the left + VO h0, h2, h0 \ // combine h0 with 20 bits from limb 1 + VLEIG $0, $0, h1 \ // clear upper half of h1 + +// if h > 2**130-5 then h -= 2**130-5 +// input: h0, h1 +// temp: t0, t1, t2 +// output: h0 +#define MOD(h0, h1, t0, t1, t2) \ + VZERO t0 \ + VLEIG $1, $5, t0 \ + VACCQ h0, t0, t1 \ + VAQ h0, t0, t0 \ + VONE t2 \ + VLEIG $1, $-4, t2 \ + VAQ t2, t1, t1 \ + VACCQ h1, t1, t1 \ + VONE t2 \ + VAQ t2, t1, t1 \ + VN h0, t1, t2 \ + VNC t0, t1, t1 \ + VO t1, t2, h0 \ + +// func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]key) +TEXT ·poly1305vmsl(SB), $0-32 + // This code processes 6 + up to 4 blocks (32 bytes) per iteration + // using the algorithm described in: + // NEON crypto, Daniel J. Bernstein & Peter Schwabe + // https://cryptojedi.org/papers/neoncrypto-20120320.pdf + // And as moddified for VMSL as described in + // Accelerating Poly1305 Cryptographic Message Authentication on the z14 + // O'Farrell et al, CASCON 2017, p48-55 + // https://ibm.ent.box.com/s/jf9gedj0e9d2vjctfyh186shaztavnht + + LMG out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key + VZERO V0 // c + + // load EX0, EX1 and EX2 + MOVD $·constants<>(SB), R5 + VLM (R5), EX0, EX2 // c + + // setup r + VL (R4), T_0 + MOVD $·keyMask<>(SB), R6 + VL (R6), T_1 + VN T_0, T_1, T_0 + VZERO T_2 // limbs for r + VZERO T_3 + VZERO T_4 + EXPACC2(T_0, T_2, T_3, T_4, T_1, T_5, T_7) + + // T_2, T_3, T_4: [0, r] + + // setup r*20 + VLEIG $0, $0, T_0 + VLEIG $1, $20, T_0 // T_0: [0, 20] + VZERO T_5 + VZERO T_6 + VMSLG T_0, T_3, T_5, T_5 + VMSLG T_0, T_4, T_6, T_6 + + // store r for final block in GR + VLGVG $1, T_2, RSAVE_0 // c + VLGVG $1, T_3, RSAVE_1 // c + VLGVG $1, T_4, RSAVE_2 // c + VLGVG $1, T_5, R5SAVE_1 // c + VLGVG $1, T_6, R5SAVE_2 // c + + // initialize h + VZERO H0_0 + VZERO H1_0 + VZERO H2_0 + VZERO H0_1 + VZERO H1_1 + VZERO H2_1 + + // initialize pointer for reduce constants + MOVD $·reduce<>(SB), R12 + + // calculate r**2 and 20*(r**2) + VZERO R_0 + VZERO R_1 + VZERO R_2 + SQUARE(T_2, T_3, T_4, T_6, R_0, R_1, R_2, T_1, T_5, T_7) + REDUCE2(R_0, R_1, R_2, M0, M1, M2, M3, M4, R5_1, R5_2, M5, T_1) + VZERO R5_1 + VZERO R5_2 + VMSLG T_0, R_1, R5_1, R5_1 + VMSLG T_0, R_2, R5_2, R5_2 + + // skip r**4 calculation if 3 blocks or less + CMPBLE R3, $48, b4 + + // calculate r**4 and 20*(r**4) + VZERO T_8 + VZERO T_9 + VZERO T_10 + SQUARE(R_0, R_1, R_2, R5_2, T_8, T_9, T_10, T_1, T_5, T_7) + REDUCE2(T_8, T_9, T_10, M0, M1, M2, M3, M4, T_2, T_3, M5, T_1) + VZERO T_2 + VZERO T_3 + VMSLG T_0, T_9, T_2, T_2 + VMSLG T_0, T_10, T_3, T_3 + + // put r**2 to the right and r**4 to the left of R_0, R_1, R_2 + VSLDB $8, T_8, T_8, T_8 + VSLDB $8, T_9, T_9, T_9 + VSLDB $8, T_10, T_10, T_10 + VSLDB $8, T_2, T_2, T_2 + VSLDB $8, T_3, T_3, T_3 + + VO T_8, R_0, R_0 + VO T_9, R_1, R_1 + VO T_10, R_2, R_2 + VO T_2, R5_1, R5_1 + VO T_3, R5_2, R5_2 + + CMPBLE R3, $80, load // less than or equal to 5 blocks in message + + // 6(or 5+1) blocks + SUB $81, R3 + VLM (R2), M0, M4 + VLL R3, 80(R2), M5 + ADD $1, R3 + MOVBZ $1, R0 + CMPBGE R3, $16, 2(PC) + VLVGB R3, R0, M5 + MOVD $96(R2), R2 + EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3) + EXPACC(M2, M3, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3) + VLEIB $2, $1, H2_0 + VLEIB $2, $1, H2_1 + VLEIB $10, $1, H2_0 + VLEIB $10, $1, H2_1 + + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO T_4 + VZERO T_10 + EXPACC(M4, M5, M0, M1, M2, M3, T_4, T_10, T_0, T_1, T_2, T_3) + VLR T_4, M4 + VLEIB $10, $1, M2 + CMPBLT R3, $16, 2(PC) + VLEIB $10, $1, T_10 + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9) + VMRHG V0, H0_1, H0_0 + VMRHG V0, H1_1, H1_0 + VMRHG V0, H2_1, H2_0 + VMRLG V0, H0_1, H0_1 + VMRLG V0, H1_1, H1_1 + VMRLG V0, H2_1, H2_1 + + SUB $16, R3 + CMPBLE R3, $0, square + +load: + // load EX0, EX1 and EX2 + MOVD $·c<>(SB), R5 + VLM (R5), EX0, EX2 + +loop: + CMPBLE R3, $64, add // b4 // last 4 or less blocks left + + // next 4 full blocks + VLM (R2), M2, M5 + SUB $64, R3 + MOVD $64(R2), R2 + REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, T_0, T_1, T_3, T_4, T_5, T_2, T_7, T_8, T_9) + + // expacc in-lined to create [m2, m3] limbs + VGBM $0x3f3f, T_0 // 44 bit clear mask + VGBM $0x1f1f, T_1 // 40 bit clear mask + VPERM M2, M3, EX0, T_3 + VESRLG $4, T_0, T_0 // 44 bit clear mask ready + VPERM M2, M3, EX1, T_4 + VPERM M2, M3, EX2, T_5 + VN T_0, T_3, T_3 + VESRLG $4, T_4, T_4 + VN T_1, T_5, T_5 + VN T_0, T_4, T_4 + VMRHG H0_1, T_3, H0_0 + VMRHG H1_1, T_4, H1_0 + VMRHG H2_1, T_5, H2_0 + VMRLG H0_1, T_3, H0_1 + VMRLG H1_1, T_4, H1_1 + VMRLG H2_1, T_5, H2_1 + VLEIB $10, $1, H2_0 + VLEIB $10, $1, H2_1 + VPERM M4, M5, EX0, T_3 + VPERM M4, M5, EX1, T_4 + VPERM M4, M5, EX2, T_5 + VN T_0, T_3, T_3 + VESRLG $4, T_4, T_4 + VN T_1, T_5, T_5 + VN T_0, T_4, T_4 + VMRHG V0, T_3, M0 + VMRHG V0, T_4, M1 + VMRHG V0, T_5, M2 + VMRLG V0, T_3, M3 + VMRLG V0, T_4, M4 + VMRLG V0, T_5, M5 + VLEIB $10, $1, M2 + VLEIB $10, $1, M5 + + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + CMPBNE R3, $0, loop + REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9) + VMRHG V0, H0_1, H0_0 + VMRHG V0, H1_1, H1_0 + VMRHG V0, H2_1, H2_0 + VMRLG V0, H0_1, H0_1 + VMRLG V0, H1_1, H1_1 + VMRLG V0, H2_1, H2_1 + + // load EX0, EX1, EX2 + MOVD $·constants<>(SB), R5 + VLM (R5), EX0, EX2 + + // sum vectors + VAQ H0_0, H0_1, H0_0 + VAQ H1_0, H1_1, H1_0 + VAQ H2_0, H2_1, H2_0 + + // h may be >= 2*(2**130-5) so we need to reduce it again + // M0...M4 are used as temps here + REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5) + +next: // carry h1->h2 + VLEIB $7, $0x28, T_1 + VREPIB $4, T_2 + VGBM $0x003F, T_3 + VESRLG $4, T_3 + + // byte shift + VSRLB T_1, H1_0, T_4 + + // bit shift + VSRL T_2, T_4, T_4 + + // clear h1 carry bits + VN T_3, H1_0, H1_0 + + // add carry + VAQ T_4, H2_0, H2_0 + + // h is now < 2*(2**130-5) + // pack h into h1 (hi) and h0 (lo) + PACK(H0_0, H1_0, H2_0) + + // if h > 2**130-5 then h -= 2**130-5 + MOD(H0_0, H1_0, T_0, T_1, T_2) + + // h += s + MOVD $·bswapMask<>(SB), R5 + VL (R5), T_1 + VL 16(R4), T_0 + VPERM T_0, T_0, T_1, T_0 // reverse bytes (to big) + VAQ T_0, H0_0, H0_0 + VPERM H0_0, H0_0, T_1, H0_0 // reverse bytes (to little) + VST H0_0, (R1) + RET + +add: + // load EX0, EX1, EX2 + MOVD $·constants<>(SB), R5 + VLM (R5), EX0, EX2 + + REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9) + VMRHG V0, H0_1, H0_0 + VMRHG V0, H1_1, H1_0 + VMRHG V0, H2_1, H2_0 + VMRLG V0, H0_1, H0_1 + VMRLG V0, H1_1, H1_1 + VMRLG V0, H2_1, H2_1 + CMPBLE R3, $64, b4 + +b4: + CMPBLE R3, $48, b3 // 3 blocks or less + + // 4(3+1) blocks remaining + SUB $49, R3 + VLM (R2), M0, M2 + VLL R3, 48(R2), M3 + ADD $1, R3 + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, M3 + MOVD $64(R2), R2 + EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3) + VLEIB $10, $1, H2_0 + VLEIB $10, $1, H2_1 + VZERO M0 + VZERO M1 + VZERO M4 + VZERO M5 + VZERO T_4 + VZERO T_10 + EXPACC(M2, M3, M0, M1, M4, M5, T_4, T_10, T_0, T_1, T_2, T_3) + VLR T_4, M2 + VLEIB $10, $1, M4 + CMPBNE R3, $16, 2(PC) + VLEIB $10, $1, T_10 + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M4, M5, M2, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9) + VMRHG V0, H0_1, H0_0 + VMRHG V0, H1_1, H1_0 + VMRHG V0, H2_1, H2_0 + VMRLG V0, H0_1, H0_1 + VMRLG V0, H1_1, H1_1 + VMRLG V0, H2_1, H2_1 + SUB $16, R3 + CMPBLE R3, $0, square // this condition must always hold true! + +b3: + CMPBLE R3, $32, b2 + + // 3 blocks remaining + + // setup [r²,r] + VSLDB $8, R_0, R_0, R_0 + VSLDB $8, R_1, R_1, R_1 + VSLDB $8, R_2, R_2, R_2 + VSLDB $8, R5_1, R5_1, R5_1 + VSLDB $8, R5_2, R5_2, R5_2 + + VLVGG $1, RSAVE_0, R_0 + VLVGG $1, RSAVE_1, R_1 + VLVGG $1, RSAVE_2, R_2 + VLVGG $1, R5SAVE_1, R5_1 + VLVGG $1, R5SAVE_2, R5_2 + + // setup [h0, h1] + VSLDB $8, H0_0, H0_0, H0_0 + VSLDB $8, H1_0, H1_0, H1_0 + VSLDB $8, H2_0, H2_0, H2_0 + VO H0_1, H0_0, H0_0 + VO H1_1, H1_0, H1_0 + VO H2_1, H2_0, H2_0 + VZERO H0_1 + VZERO H1_1 + VZERO H2_1 + + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + + // H*[r**2, r] + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, T_10, M5) + + SUB $33, R3 + VLM (R2), M0, M1 + VLL R3, 32(R2), M2 + ADD $1, R3 + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, M2 + + // H += m0 + VZERO T_1 + VZERO T_2 + VZERO T_3 + EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6) + VLEIB $10, $1, T_3 + VAG H0_0, T_1, H0_0 + VAG H1_0, T_2, H1_0 + VAG H2_0, T_3, H2_0 + + VZERO M0 + VZERO M3 + VZERO M4 + VZERO M5 + VZERO T_10 + + // (H+m0)*r + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M3, M4, M5, V0, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_10, H0_1, H1_1, H2_1, T_9) + + // H += m1 + VZERO V0 + VZERO T_1 + VZERO T_2 + VZERO T_3 + EXPACC2(M1, T_1, T_2, T_3, T_4, T_5, T_6) + VLEIB $10, $1, T_3 + VAQ H0_0, T_1, H0_0 + VAQ H1_0, T_2, H1_0 + VAQ H2_0, T_3, H2_0 + REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10) + + // [H, m2] * [r**2, r] + EXPACC2(M2, H0_0, H1_0, H2_0, T_1, T_2, T_3) + CMPBNE R3, $16, 2(PC) + VLEIB $10, $1, H2_0 + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, M5, T_10) + SUB $16, R3 + CMPBLE R3, $0, next // this condition must always hold true! + +b2: + CMPBLE R3, $16, b1 + + // 2 blocks remaining + + // setup [r²,r] + VSLDB $8, R_0, R_0, R_0 + VSLDB $8, R_1, R_1, R_1 + VSLDB $8, R_2, R_2, R_2 + VSLDB $8, R5_1, R5_1, R5_1 + VSLDB $8, R5_2, R5_2, R5_2 + + VLVGG $1, RSAVE_0, R_0 + VLVGG $1, RSAVE_1, R_1 + VLVGG $1, RSAVE_2, R_2 + VLVGG $1, R5SAVE_1, R5_1 + VLVGG $1, R5SAVE_2, R5_2 + + // setup [h0, h1] + VSLDB $8, H0_0, H0_0, H0_0 + VSLDB $8, H1_0, H1_0, H1_0 + VSLDB $8, H2_0, H2_0, H2_0 + VO H0_1, H0_0, H0_0 + VO H1_1, H1_0, H1_0 + VO H2_1, H2_0, H2_0 + VZERO H0_1 + VZERO H1_1 + VZERO H2_1 + + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + + // H*[r**2, r] + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9) + VMRHG V0, H0_1, H0_0 + VMRHG V0, H1_1, H1_0 + VMRHG V0, H2_1, H2_0 + VMRLG V0, H0_1, H0_1 + VMRLG V0, H1_1, H1_1 + VMRLG V0, H2_1, H2_1 + + // move h to the left and 0s at the right + VSLDB $8, H0_0, H0_0, H0_0 + VSLDB $8, H1_0, H1_0, H1_0 + VSLDB $8, H2_0, H2_0, H2_0 + + // get message blocks and append 1 to start + SUB $17, R3 + VL (R2), M0 + VLL R3, 16(R2), M1 + ADD $1, R3 + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, M1 + VZERO T_6 + VZERO T_7 + VZERO T_8 + EXPACC2(M0, T_6, T_7, T_8, T_1, T_2, T_3) + EXPACC2(M1, T_6, T_7, T_8, T_1, T_2, T_3) + VLEIB $2, $1, T_8 + CMPBNE R3, $16, 2(PC) + VLEIB $10, $1, T_8 + + // add [m0, m1] to h + VAG H0_0, T_6, H0_0 + VAG H1_0, T_7, H1_0 + VAG H2_0, T_8, H2_0 + + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + VZERO T_10 + VZERO M0 + + // at this point R_0 .. R5_2 look like [r**2, r] + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M2, M3, M4, M5, T_10, M0, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M2, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10) + SUB $16, R3, R3 + CMPBLE R3, $0, next + +b1: + CMPBLE R3, $0, next + + // 1 block remaining + + // setup [r²,r] + VSLDB $8, R_0, R_0, R_0 + VSLDB $8, R_1, R_1, R_1 + VSLDB $8, R_2, R_2, R_2 + VSLDB $8, R5_1, R5_1, R5_1 + VSLDB $8, R5_2, R5_2, R5_2 + + VLVGG $1, RSAVE_0, R_0 + VLVGG $1, RSAVE_1, R_1 + VLVGG $1, RSAVE_2, R_2 + VLVGG $1, R5SAVE_1, R5_1 + VLVGG $1, R5SAVE_2, R5_2 + + // setup [h0, h1] + VSLDB $8, H0_0, H0_0, H0_0 + VSLDB $8, H1_0, H1_0, H1_0 + VSLDB $8, H2_0, H2_0, H2_0 + VO H0_1, H0_0, H0_0 + VO H1_1, H1_0, H1_0 + VO H2_1, H2_0, H2_0 + VZERO H0_1 + VZERO H1_1 + VZERO H2_1 + + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + + // H*[r**2, r] + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5) + + // set up [0, m0] limbs + SUB $1, R3 + VLL R3, (R2), M0 + ADD $1, R3 + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, M0 + VZERO T_1 + VZERO T_2 + VZERO T_3 + EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6)// limbs: [0, m] + CMPBNE R3, $16, 2(PC) + VLEIB $10, $1, T_3 + + // h+m0 + VAQ H0_0, T_1, H0_0 + VAQ H1_0, T_2, H1_0 + VAQ H2_0, T_3, H2_0 + + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5) + + BR next + +square: + // setup [r²,r] + VSLDB $8, R_0, R_0, R_0 + VSLDB $8, R_1, R_1, R_1 + VSLDB $8, R_2, R_2, R_2 + VSLDB $8, R5_1, R5_1, R5_1 + VSLDB $8, R5_2, R5_2, R5_2 + + VLVGG $1, RSAVE_0, R_0 + VLVGG $1, RSAVE_1, R_1 + VLVGG $1, RSAVE_2, R_2 + VLVGG $1, R5SAVE_1, R5_1 + VLVGG $1, R5SAVE_2, R5_2 + + // setup [h0, h1] + VSLDB $8, H0_0, H0_0, H0_0 + VSLDB $8, H1_0, H1_0, H1_0 + VSLDB $8, H2_0, H2_0, H2_0 + VO H0_1, H0_0, H0_0 + VO H1_1, H1_0, H1_0 + VO H2_1, H2_0, H2_0 + VZERO H0_1 + VZERO H1_1 + VZERO H2_1 + + VZERO M0 + VZERO M1 + VZERO M2 + VZERO M3 + VZERO M4 + VZERO M5 + + // (h0*r**2) + (h1*r) + MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) + REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5) + BR next + +TEXT ·hasVMSLFacility(SB), NOSPLIT, $24-1 + MOVD $x-24(SP), R1 + XC $24, 0(R1), 0(R1) // clear the storage + MOVD $2, R0 // R0 is the number of double words stored -1 + WORD $0xB2B01000 // STFLE 0(R1) + XOR R0, R0 // reset the value of R0 + MOVBZ z-8(SP), R1 + AND $0x01, R1 + BEQ novmsl + +vectorinstalled: + // check if the vector instruction has been enabled + VLEIB $0, $0xF, V16 + VLGVB $0, V16, R1 + CMPBNE R1, $0xF, novmsl + MOVB $1, ret+0(FP) // have vx + RET + +novmsl: + MOVB $0, ret+0(FP) // no vx + RET diff --git a/vendor/golang.org/x/crypto/ssh/agent/keyring.go b/vendor/golang.org/x/crypto/ssh/agent/keyring.go index a6ba06ab30..1a5163270c 100644 --- a/vendor/golang.org/x/crypto/ssh/agent/keyring.go +++ b/vendor/golang.org/x/crypto/ssh/agent/keyring.go @@ -102,7 +102,7 @@ func (r *keyring) Unlock(passphrase []byte) error { if !r.locked { return errors.New("agent: not locked") } - if len(passphrase) != len(r.passphrase) || 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { + if 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { return fmt.Errorf("agent: incorrect passphrase") } diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go index 30a49fdf27..67b0126105 100644 --- a/vendor/golang.org/x/crypto/ssh/cipher.go +++ b/vendor/golang.org/x/crypto/ssh/cipher.go @@ -16,6 +16,7 @@ import ( "hash" "io" "io/ioutil" + "math/bits" "golang.org/x/crypto/internal/chacha20" "golang.org/x/crypto/poly1305" @@ -641,8 +642,8 @@ const chacha20Poly1305ID = "chacha20-poly1305@openssh.com" // the methods here also implement padding, which RFC4253 Section 6 // also requires of stream ciphers. type chacha20Poly1305Cipher struct { - lengthKey [32]byte - contentKey [32]byte + lengthKey [8]uint32 + contentKey [8]uint32 buf []byte } @@ -655,20 +656,21 @@ func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionA buf: make([]byte, 256), } - copy(c.contentKey[:], key[:32]) - copy(c.lengthKey[:], key[32:]) + for i := range c.contentKey { + c.contentKey[i] = binary.LittleEndian.Uint32(key[i*4 : (i+1)*4]) + } + for i := range c.lengthKey { + c.lengthKey[i] = binary.LittleEndian.Uint32(key[(i+8)*4 : (i+9)*4]) + } return c, nil } -// The Poly1305 key is obtained by encrypting 32 0-bytes. -var chacha20PolyKeyInput [32]byte - func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { - var counter [16]byte - binary.BigEndian.PutUint64(counter[8:], uint64(seqNum)) - + nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)} + s := chacha20.New(c.contentKey, nonce) var polyKey [32]byte - chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey) + s.XORKeyStream(polyKey[:], polyKey[:]) + s.Advance() // skip next 32 bytes encryptedLength := c.buf[:4] if _, err := io.ReadFull(r, encryptedLength); err != nil { @@ -676,7 +678,7 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, } var lenBytes [4]byte - chacha20.XORKeyStream(lenBytes[:], encryptedLength, &counter, &c.lengthKey) + chacha20.New(c.lengthKey, nonce).XORKeyStream(lenBytes[:], encryptedLength) length := binary.BigEndian.Uint32(lenBytes[:]) if length > maxPacket { @@ -702,10 +704,8 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, return nil, errors.New("ssh: MAC failure") } - counter[0] = 1 - plain := c.buf[4:contentEnd] - chacha20.XORKeyStream(plain, plain, &counter, &c.contentKey) + s.XORKeyStream(plain, plain) padding := plain[0] if padding < 4 { @@ -724,11 +724,11 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, } func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error { - var counter [16]byte - binary.BigEndian.PutUint64(counter[8:], uint64(seqNum)) - + nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)} + s := chacha20.New(c.contentKey, nonce) var polyKey [32]byte - chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey) + s.XORKeyStream(polyKey[:], polyKey[:]) + s.Advance() // skip next 32 bytes // There is no blocksize, so fall back to multiple of 8 byte // padding, as described in RFC 4253, Sec 6. @@ -748,7 +748,7 @@ func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io } binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding)) - chacha20.XORKeyStream(c.buf, c.buf[:4], &counter, &c.lengthKey) + chacha20.New(c.lengthKey, nonce).XORKeyStream(c.buf, c.buf[:4]) c.buf[4] = byte(padding) copy(c.buf[5:], payload) packetEnd := 5 + len(payload) + padding @@ -756,8 +756,7 @@ func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io return err } - counter[0] = 1 - chacha20.XORKeyStream(c.buf[4:], c.buf[4:packetEnd], &counter, &c.contentKey) + s.XORKeyStream(c.buf[4:], c.buf[4:packetEnd]) var mac [poly1305.TagSize]byte poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey) diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go index 6fd1994553..ae6ca775ee 100644 --- a/vendor/golang.org/x/crypto/ssh/client.go +++ b/vendor/golang.org/x/crypto/ssh/client.go @@ -19,6 +19,8 @@ import ( type Client struct { Conn + handleForwardsOnce sync.Once // guards calling (*Client).handleForwards + forwards forwardList // forwarded tcpip connections from the remote side mu sync.Mutex channelHandlers map[string]chan NewChannel @@ -60,8 +62,6 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client { conn.Wait() conn.forwards.closeAll() }() - go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip")) - go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com")) return conn } diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go index 73697deda6..2261dc386c 100644 --- a/vendor/golang.org/x/crypto/ssh/keys.go +++ b/vendor/golang.org/x/crypto/ssh/keys.go @@ -803,7 +803,7 @@ func encryptedBlock(block *pem.Block) bool { } // ParseRawPrivateKey returns a private key from a PEM encoded private key. It -// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys. +// supports RSA (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys. func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { block, _ := pem.Decode(pemBytes) if block == nil { @@ -817,6 +817,9 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { switch block.Type { case "RSA PRIVATE KEY": return x509.ParsePKCS1PrivateKey(block.Bytes) + // RFC5208 - https://tools.ietf.org/html/rfc5208 + case "PRIVATE KEY": + return x509.ParsePKCS8PrivateKey(block.Bytes) case "EC PRIVATE KEY": return x509.ParseECPrivateKey(block.Bytes) case "DSA PRIVATE KEY": @@ -900,8 +903,8 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) { // Implemented based on the documentation at // https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) { - magic := append([]byte("openssh-key-v1"), 0) - if !bytes.Equal(magic, key[0:len(magic)]) { + const magic = "openssh-key-v1\x00" + if len(key) < len(magic) || string(key[:len(magic)]) != magic { return nil, errors.New("ssh: invalid openssh private key format") } remaining := key[len(magic):] diff --git a/vendor/golang.org/x/crypto/ssh/streamlocal.go b/vendor/golang.org/x/crypto/ssh/streamlocal.go index a2dccc64c7..b171b330bc 100644 --- a/vendor/golang.org/x/crypto/ssh/streamlocal.go +++ b/vendor/golang.org/x/crypto/ssh/streamlocal.go @@ -32,6 +32,7 @@ type streamLocalChannelForwardMsg struct { // ListenUnix is similar to ListenTCP but uses a Unix domain socket. func (c *Client) ListenUnix(socketPath string) (net.Listener, error) { + c.handleForwardsOnce.Do(c.handleForwards) m := streamLocalChannelForwardMsg{ socketPath, } diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go index acf17175df..80d35f5ec1 100644 --- a/vendor/golang.org/x/crypto/ssh/tcpip.go +++ b/vendor/golang.org/x/crypto/ssh/tcpip.go @@ -90,10 +90,19 @@ type channelForwardMsg struct { rport uint32 } +// handleForwards starts goroutines handling forwarded connections. +// It's called on first use by (*Client).ListenTCP to not launch +// goroutines until needed. +func (c *Client) handleForwards() { + go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-tcpip")) + go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-streamlocal@openssh.com")) +} + // ListenTCP requests the remote peer open a listening socket // on laddr. Incoming connections will be available by calling // Accept on the returned net.Listener. func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { + c.handleForwardsOnce.Do(c.handleForwards) if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) { return c.autoPortListenWorkaround(laddr) } diff --git a/vendor/golang.org/x/oauth2/.travis.yml b/vendor/golang.org/x/oauth2/.travis.yml new file mode 100644 index 0000000000..fa139db225 --- /dev/null +++ b/vendor/golang.org/x/oauth2/.travis.yml @@ -0,0 +1,13 @@ +language: go + +go: + - tip + +install: + - export GOPATH="$HOME/gopath" + - mkdir -p "$GOPATH/src/golang.org/x" + - mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/golang.org/x/oauth2" + - go get -v -t -d golang.org/x/oauth2/... + +script: + - go test -v golang.org/x/oauth2/... diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTING.md b/vendor/golang.org/x/oauth2/CONTRIBUTING.md new file mode 100644 index 0000000000..dfbed62cf5 --- /dev/null +++ b/vendor/golang.org/x/oauth2/CONTRIBUTING.md @@ -0,0 +1,26 @@ +# Contributing to Go + +Go is an open source project. + +It is the work of hundreds of contributors. We appreciate your help! + +## Filing issues + +When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions: + +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. +The gophers there will answer or ask you to file an issue if you've tripped over a bug. + +## Contributing code + +Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) +before sending patches. + +Unless otherwise noted, the Go source files are distributed under +the BSD-style license found in the LICENSE file. diff --git a/vendor/golang.org/x/oauth2/README.md b/vendor/golang.org/x/oauth2/README.md new file mode 100644 index 0000000000..94ffd7326a --- /dev/null +++ b/vendor/golang.org/x/oauth2/README.md @@ -0,0 +1,79 @@ +# OAuth2 for Go + +[![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2) +[![GoDoc](https://godoc.org/golang.org/x/oauth2?status.svg)](https://godoc.org/golang.org/x/oauth2) + +oauth2 package contains a client implementation for OAuth 2.0 spec. + +## Installation + +~~~~ +go get golang.org/x/oauth2 +~~~~ + +Or you can manually git clone the repository to +`$(go env GOPATH)/src/golang.org/x/oauth2`. + +See godoc for further documentation and examples. + +* [godoc.org/golang.org/x/oauth2](http://godoc.org/golang.org/x/oauth2) +* [godoc.org/golang.org/x/oauth2/google](http://godoc.org/golang.org/x/oauth2/google) + + +## App Engine + +In change 96e89be (March 2015), we removed the `oauth2.Context2` type in favor +of the [`context.Context`](https://golang.org/x/net/context#Context) type from +the `golang.org/x/net/context` package. Later replaced by the standard `context` package +of the [`context.Context`](https://golang.org/pkg/context#Context) type. + + +This means it's no longer possible to use the "Classic App Engine" +`appengine.Context` type with the `oauth2` package. (You're using +Classic App Engine if you import the package `"appengine"`.) + +To work around this, you may use the new `"google.golang.org/appengine"` +package. This package has almost the same API as the `"appengine"` package, +but it can be fetched with `go get` and used on "Managed VMs" and well as +Classic App Engine. + +See the [new `appengine` package's readme](https://github.com/golang/appengine#updating-a-go-app-engine-app) +for information on updating your app. + +If you don't want to update your entire app to use the new App Engine packages, +you may use both sets of packages in parallel, using only the new packages +with the `oauth2` package. + +```go +import ( + "context" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" + newappengine "google.golang.org/appengine" + newurlfetch "google.golang.org/appengine/urlfetch" + + "appengine" +) + +func handler(w http.ResponseWriter, r *http.Request) { + var c appengine.Context = appengine.NewContext(r) + c.Infof("Logging a message with the old package") + + var ctx context.Context = newappengine.NewContext(r) + client := &http.Client{ + Transport: &oauth2.Transport{ + Source: google.AppEngineTokenSource(ctx, "scope"), + Base: &newurlfetch.Transport{Context: ctx}, + }, + } + client.Get("...") +} +``` + +## Report Issues / Send Patches + +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://golang.org/doc/contribute.html. + +The main issue tracker for the oauth2 repository is located at +https://github.com/golang/oauth2/issues. diff --git a/vendor/golang.org/x/sys/unix/.gitignore b/vendor/golang.org/x/sys/unix/.gitignore new file mode 100644 index 0000000000..e3e0fc6f89 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/.gitignore @@ -0,0 +1,2 @@ +_obj/ +unix.test diff --git a/vendor/golang.org/x/sys/unix/README.md b/vendor/golang.org/x/sys/unix/README.md new file mode 100644 index 0000000000..bc6f6031f1 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/README.md @@ -0,0 +1,173 @@ +# Building `sys/unix` + +The sys/unix package provides access to the raw system call interface of the +underlying operating system. See: https://godoc.org/golang.org/x/sys/unix + +Porting Go to a new architecture/OS combination or adding syscalls, types, or +constants to an existing architecture/OS pair requires some manual effort; +however, there are tools that automate much of the process. + +## Build Systems + +There are currently two ways we generate the necessary files. We are currently +migrating the build system to use containers so the builds are reproducible. +This is being done on an OS-by-OS basis. Please update this documentation as +components of the build system change. + +### Old Build System (currently for `GOOS != "Linux" || GOARCH == "sparc64"`) + +The old build system generates the Go files based on the C header files +present on your system. This means that files +for a given GOOS/GOARCH pair must be generated on a system with that OS and +architecture. This also means that the generated code can differ from system +to system, based on differences in the header files. + +To avoid this, if you are using the old build system, only generate the Go +files on an installation with unmodified header files. It is also important to +keep track of which version of the OS the files were generated from (ex. +Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes +and have each OS upgrade correspond to a single change. + +To build the files for your current OS and architecture, make sure GOOS and +GOARCH are set correctly and run `mkall.sh`. This will generate the files for +your specific system. Running `mkall.sh -n` shows the commands that will be run. + +Requirements: bash, perl, go + +### New Build System (currently for `GOOS == "Linux" && GOARCH != "sparc64"`) + +The new build system uses a Docker container to generate the go files directly +from source checkouts of the kernel and various system libraries. This means +that on any platform that supports Docker, all the files using the new build +system can be generated at once, and generated files will not change based on +what the person running the scripts has installed on their computer. + +The OS specific files for the new build system are located in the `${GOOS}` +directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When +the kernel or system library updates, modify the Dockerfile at +`${GOOS}/Dockerfile` to checkout the new release of the source. + +To build all the files under the new build system, you must be on an amd64/Linux +system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will +then generate all of the files for all of the GOOS/GOARCH pairs in the new build +system. Running `mkall.sh -n` shows the commands that will be run. + +Requirements: bash, perl, go, docker + +## Component files + +This section describes the various files used in the code generation process. +It also contains instructions on how to modify these files to add a new +architecture/OS or to add additional syscalls, types, or constants. Note that +if you are using the new build system, the scripts cannot be called normally. +They must be called from within the docker container. + +### asm files + +The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system +call dispatch. There are three entry points: +``` + func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) + func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) + func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) +``` +The first and second are the standard ones; they differ only in how many +arguments can be passed to the kernel. The third is for low-level use by the +ForkExec wrapper. Unlike the first two, it does not call into the scheduler to +let it know that a system call is running. + +When porting Go to an new architecture/OS, this file must be implemented for +each GOOS/GOARCH pair. + +### mksysnum + +Mksysnum is a script located at `${GOOS}/mksysnum.pl` (or `mksysnum_${GOOS}.pl` +for the old system). This script takes in a list of header files containing the +syscall number declarations and parses them to produce the corresponding list of +Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated +constants. + +Adding new syscall numbers is mostly done by running the build on a sufficiently +new installation of the target OS (or updating the source checkouts for the +new build system). However, depending on the OS, you make need to update the +parsing in mksysnum. + +### mksyscall.pl + +The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are +hand-written Go files which implement system calls (for unix, the specific OS, +or the specific OS/Architecture pair respectively) that need special handling +and list `//sys` comments giving prototypes for ones that can be generated. + +The mksyscall.pl script takes the `//sys` and `//sysnb` comments and converts +them into syscalls. This requires the name of the prototype in the comment to +match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function +prototype can be exported (capitalized) or not. + +Adding a new syscall often just requires adding a new `//sys` function prototype +with the desired arguments and a capitalized name so it is exported. However, if +you want the interface to the syscall to be different, often one will make an +unexported `//sys` prototype, an then write a custom wrapper in +`syscall_${GOOS}.go`. + +### types files + +For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or +`types_${GOOS}.go` on the old system). This file includes standard C headers and +creates Go type aliases to the corresponding C types. The file is then fed +through godef to get the Go compatible definitions. Finally, the generated code +is fed though mkpost.go to format the code correctly and remove any hidden or +private identifiers. This cleaned-up code is written to +`ztypes_${GOOS}_${GOARCH}.go`. + +The hardest part about preparing this file is figuring out which headers to +include and which symbols need to be `#define`d to get the actual data +structures that pass through to the kernel system calls. Some C libraries +preset alternate versions for binary compatibility and translate them on the +way in and out of system calls, but there is almost always a `#define` that can +get the real ones. +See `types_darwin.go` and `linux/types.go` for examples. + +To add a new type, add in the necessary include statement at the top of the +file (if it is not already there) and add in a type alias line. Note that if +your type is significantly different on different architectures, you may need +some `#if/#elif` macros in your include statements. + +### mkerrors.sh + +This script is used to generate the system's various constants. This doesn't +just include the error numbers and error strings, but also the signal numbers +an a wide variety of miscellaneous constants. The constants come from the list +of include files in the `includes_${uname}` variable. A regex then picks out +the desired `#define` statements, and generates the corresponding Go constants. +The error numbers and strings are generated from `#include `, and the +signal numbers and strings are generated from `#include `. All of +these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program, +`_errors.c`, which prints out all the constants. + +To add a constant, add the header that includes it to the appropriate variable. +Then, edit the regex (if necessary) to match the desired constant. Avoid making +the regex too broad to avoid matching unintended constants. + + +## Generated files + +### `zerror_${GOOS}_${GOARCH}.go` + +A file containing all of the system's generated error numbers, error strings, +signal numbers, and constants. Generated by `mkerrors.sh` (see above). + +### `zsyscall_${GOOS}_${GOARCH}.go` + +A file containing all the generated syscalls for a specific GOOS and GOARCH. +Generated by `mksyscall.pl` (see above). + +### `zsysnum_${GOOS}_${GOARCH}.go` + +A list of numeric constants for all the syscall number of the specific GOOS +and GOARCH. Generated by mksysnum (see above). + +### `ztypes_${GOOS}_${GOARCH}.go` + +A file containing Go types for passing into (or returning from) syscalls. +Generated by godefs and the types file (see above). diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh new file mode 100644 index 0000000000..9b76ad6697 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mkall.sh @@ -0,0 +1,204 @@ +#!/usr/bin/env bash +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# This script runs or (given -n) prints suggested commands to generate files for +# the Architecture/OS specified by the GOARCH and GOOS environment variables. +# See README.md for more information about how the build system works. + +GOOSARCH="${GOOS}_${GOARCH}" + +# defaults +mksyscall="./mksyscall.pl" +mkerrors="./mkerrors.sh" +zerrors="zerrors_$GOOSARCH.go" +mksysctl="" +zsysctl="zsysctl_$GOOSARCH.go" +mksysnum= +mktypes= +run="sh" +cmd="" + +case "$1" in +-syscalls) + for i in zsyscall*go + do + # Run the command line that appears in the first line + # of the generated file to regenerate it. + sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i + rm _$i + done + exit 0 + ;; +-n) + run="cat" + cmd="echo" + shift +esac + +case "$#" in +0) + ;; +*) + echo 'usage: mkall.sh [-n]' 1>&2 + exit 2 +esac + +if [[ "$GOOS" = "linux" ]] && [[ "$GOARCH" != "sparc64" ]]; then + # Use then new build system + # Files generated through docker (use $cmd so you can Ctl-C the build or run) + $cmd docker build --tag generate:$GOOS $GOOS + $cmd docker run --interactive --tty --volume $(dirname "$(readlink -f "$0")"):/build generate:$GOOS + exit +fi + +GOOSARCH_in=syscall_$GOOSARCH.go +case "$GOOSARCH" in +_* | *_ | _) + echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2 + exit 1 + ;; +aix_ppc) + mkerrors="$mkerrors -maix32" + mksyscall="./mksyscall_aix_ppc.pl -aix" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +aix_ppc64) + mkerrors="$mkerrors -maix64" + mksyscall="./mksyscall_aix_ppc64.pl -aix" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +darwin_386) + mkerrors="$mkerrors -m32" + mksyscall="./mksyscall.pl -l32" + mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +darwin_amd64) + mkerrors="$mkerrors -m64" + mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +darwin_arm) + mkerrors="$mkerrors" + mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +darwin_arm64) + mkerrors="$mkerrors -m64" + mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +dragonfly_amd64) + mkerrors="$mkerrors -m64" + mksyscall="./mksyscall.pl -dragonfly" + mksysnum="curl -s 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master' | ./mksysnum_dragonfly.pl" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +freebsd_386) + mkerrors="$mkerrors -m32" + mksyscall="./mksyscall.pl -l32" + mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +freebsd_amd64) + mkerrors="$mkerrors -m64" + mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +freebsd_arm) + mkerrors="$mkerrors" + mksyscall="./mksyscall.pl -l32 -arm" + mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl" + # Let the type of C char be signed for making the bare syscall + # API consistent across platforms. + mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" + ;; +linux_sparc64) + GOOSARCH_in=syscall_linux_sparc64.go + unistd_h=/usr/include/sparc64-linux-gnu/asm/unistd.h + mkerrors="$mkerrors -m64" + mksysnum="./mksysnum_linux.pl $unistd_h" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +netbsd_386) + mkerrors="$mkerrors -m32" + mksyscall="./mksyscall.pl -l32 -netbsd" + mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +netbsd_amd64) + mkerrors="$mkerrors -m64" + mksyscall="./mksyscall.pl -netbsd" + mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +netbsd_arm) + mkerrors="$mkerrors" + mksyscall="./mksyscall.pl -l32 -netbsd -arm" + mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl" + # Let the type of C char be signed for making the bare syscall + # API consistent across platforms. + mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" + ;; +openbsd_386) + mkerrors="$mkerrors -m32" + mksyscall="./mksyscall.pl -l32 -openbsd" + mksysctl="./mksysctl_openbsd.pl" + mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +openbsd_amd64) + mkerrors="$mkerrors -m64" + mksyscall="./mksyscall.pl -openbsd" + mksysctl="./mksysctl_openbsd.pl" + mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl" + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +openbsd_arm) + mkerrors="$mkerrors" + mksyscall="./mksyscall.pl -l32 -openbsd -arm" + mksysctl="./mksysctl_openbsd.pl" + mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl" + # Let the type of C char be signed for making the bare syscall + # API consistent across platforms. + mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" + ;; +solaris_amd64) + mksyscall="./mksyscall_solaris.pl" + mkerrors="$mkerrors -m64" + mksysnum= + mktypes="GOARCH=$GOARCH go tool cgo -godefs" + ;; +*) + echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2 + exit 1 + ;; +esac + +( + if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi + case "$GOOS" in + *) + syscall_goos="syscall_$GOOS.go" + case "$GOOS" in + darwin | dragonfly | freebsd | netbsd | openbsd) + syscall_goos="syscall_bsd.go $syscall_goos" + ;; + esac + if [ -n "$mksyscall" ]; then + if [ "$GOOSARCH" == "aix_ppc64" ]; then + # aix/ppc64 script generates files instead of writing to stdin. + echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ; + else + echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; + fi + fi + esac + if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi + if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi + if [ -n "$mktypes" ]; then + echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go"; + fi +) | $run diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh new file mode 100644 index 0000000000..73e179a89f --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -0,0 +1,656 @@ +#!/usr/bin/env bash +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# Generate Go code listing errors and other #defined constant +# values (ENAMETOOLONG etc.), by asking the preprocessor +# about the definitions. + +unset LANG +export LC_ALL=C +export LC_CTYPE=C + +if test -z "$GOARCH" -o -z "$GOOS"; then + echo 1>&2 "GOARCH or GOOS not defined in environment" + exit 1 +fi + +# Check that we are using the new build system if we should +if [[ "$GOOS" = "linux" ]] && [[ "$GOARCH" != "sparc64" ]]; then + if [[ "$GOLANG_SYS_BUILD" != "docker" ]]; then + echo 1>&2 "In the new build system, mkerrors should not be called directly." + echo 1>&2 "See README.md" + exit 1 + fi +fi + +if [[ "$GOOS" = "aix" ]]; then + CC=${CC:-gcc} +else + CC=${CC:-cc} +fi + +if [[ "$GOOS" = "solaris" ]]; then + # Assumes GNU versions of utilities in PATH. + export PATH=/usr/gnu/bin:$PATH +fi + +uname=$(uname) + +includes_AIX=' +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AF_LOCAL AF_UNIX +' + +includes_Darwin=' +#define _DARWIN_C_SOURCE +#define KERNEL +#define _DARWIN_USE_64_BIT_INODE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +' + +includes_DragonFly=' +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +' + +includes_FreeBSD=' +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __FreeBSD__ >= 10 +#define IFT_CARP 0xf8 // IFT_CARP is deprecated in FreeBSD 10 +#undef SIOCAIFADDR +#define SIOCAIFADDR _IOW(105, 26, struct oifaliasreq) // ifaliasreq contains if_data +#undef SIOCSIFPHYADDR +#define SIOCSIFPHYADDR _IOW(105, 70, struct oifaliasreq) // ifaliasreq contains if_data +#endif +' + +includes_Linux=' +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE +#ifndef __LP64__ +#define _FILE_OFFSET_BITS 64 +#endif +#define _GNU_SOURCE + +// is broken on powerpc64, as it fails to include definitions of +// these structures. We just include them copied from . +#if defined(__powerpc__) +struct sgttyb { + char sg_ispeed; + char sg_ospeed; + char sg_erase; + char sg_kill; + short sg_flags; +}; + +struct tchars { + char t_intrc; + char t_quitc; + char t_startc; + char t_stopc; + char t_eofc; + char t_brkc; +}; + +struct ltchars { + char t_suspc; + char t_dsuspc; + char t_rprntc; + char t_flushc; + char t_werasc; + char t_lnextc; +}; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef MSG_FASTOPEN +#define MSG_FASTOPEN 0x20000000 +#endif + +#ifndef PTRACE_GETREGS +#define PTRACE_GETREGS 0xc +#endif + +#ifndef PTRACE_SETREGS +#define PTRACE_SETREGS 0xd +#endif + +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + +#ifdef SOL_BLUETOOTH +// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h +// but it is already in bluetooth_linux.go +#undef SOL_BLUETOOTH +#endif + +// Certain constants are missing from the fs/crypto UAPI +#define FS_KEY_DESC_PREFIX "fscrypt:" +#define FS_KEY_DESC_PREFIX_SIZE 8 +#define FS_MAX_KEY_SIZE 64 + +// XDP socket constants do not appear to be picked up otherwise. +// Copied from samples/bpf/xdpsock_user.c. +#ifndef SOL_XDP +#define SOL_XDP 283 +#endif + +#ifndef AF_XDP +#define AF_XDP 44 +#endif +' + +includes_NetBSD=' +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Needed since refers to it... +#define schedppq 1 +' + +includes_OpenBSD=' +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// We keep some constants not supported in OpenBSD 5.5 and beyond for +// the promise of compatibility. +#define EMUL_ENABLED 0x1 +#define EMUL_NATIVE 0x2 +#define IPV6_FAITH 0x1d +#define IPV6_OPTIONS 0x1 +#define IPV6_RTHDR_STRICT 0x1 +#define IPV6_SOCKOPT_RESERVED1 0x3 +#define SIOCGIFGENERIC 0xc020693a +#define SIOCSIFGENERIC 0x80206939 +#define WALTSIG 0x4 +' + +includes_SunOS=' +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +' + + +includes=' +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +' +ccflags="$@" + +# Write go tool cgo -godefs input. +( + echo package unix + echo + echo '/*' + indirect="includes_$(uname)" + echo "${!indirect} $includes" + echo '*/' + echo 'import "C"' + echo 'import "syscall"' + echo + echo 'const (' + + # The gcc command line prints all the #defines + # it encounters while processing the input + echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags | + awk ' + $1 != "#define" || $2 ~ /\(/ || $3 == "" {next} + + $2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers + $2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next} + $2 ~ /^(SCM_SRCRT)$/ {next} + $2 ~ /^(MAP_FAILED)$/ {next} + $2 ~ /^ELF_.*$/ {next}# contains ELF_ARCH, etc. + + $2 ~ /^EXTATTR_NAMESPACE_NAMES/ || + $2 ~ /^EXTATTR_NAMESPACE_[A-Z]+_STRING/ {next} + + $2 !~ /^ECCAPBITS/ && + $2 !~ /^ETH_/ && + $2 !~ /^EPROC_/ && + $2 !~ /^EQUIV_/ && + $2 !~ /^EXPR_/ && + $2 ~ /^E[A-Z0-9_]+$/ || + $2 ~ /^B[0-9_]+$/ || + $2 ~ /^(OLD|NEW)DEV$/ || + $2 == "BOTHER" || + $2 ~ /^CI?BAUD(EX)?$/ || + $2 == "IBSHIFT" || + $2 ~ /^V[A-Z0-9]+$/ || + $2 ~ /^CS[A-Z0-9]/ || + $2 ~ /^I(SIG|CANON|CRNL|UCLC|EXTEN|MAXBEL|STRIP|UTF8)$/ || + $2 ~ /^IGN/ || + $2 ~ /^IX(ON|ANY|OFF)$/ || + $2 ~ /^IN(LCR|PCK)$/ || + $2 !~ "X86_CR3_PCID_NOFLUSH" && + $2 ~ /(^FLU?SH)|(FLU?SH$)/ || + $2 ~ /^C(LOCAL|READ|MSPAR|RTSCTS)$/ || + $2 == "BRKINT" || + $2 == "HUPCL" || + $2 == "PENDIN" || + $2 == "TOSTOP" || + $2 == "XCASE" || + $2 == "ALTWERASE" || + $2 == "NOKERNINFO" || + $2 ~ /^PAR/ || + $2 ~ /^SIG[^_]/ || + $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ || + $2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ || + $2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ || + $2 ~ /^O?XTABS$/ || + $2 ~ /^TC[IO](ON|OFF)$/ || + $2 ~ /^IN_/ || + $2 ~ /^LOCK_(SH|EX|NB|UN)$/ || + $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ || + $2 ~ /^TP_STATUS_/ || + $2 ~ /^FALLOC_/ || + $2 == "ICMPV6_FILTER" || + $2 == "SOMAXCONN" || + $2 == "NAME_MAX" || + $2 == "IFNAMSIZ" || + $2 ~ /^CTL_(HW|KERN|MAXNAME|NET|QUERY)$/ || + $2 ~ /^KERN_(HOSTNAME|OS(RELEASE|TYPE)|VERSION)$/ || + $2 ~ /^HW_MACHINE$/ || + $2 ~ /^SYSCTL_VERS/ || + $2 !~ "MNT_BITS" && + $2 ~ /^(MS|MNT|UMOUNT)_/ || + $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || + $2 ~ /^(O|F|E?FD|NAME|S|PTRACE|PT)_/ || + $2 ~ /^KEXEC_/ || + $2 ~ /^LINUX_REBOOT_CMD_/ || + $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || + $2 ~ /^MODULE_INIT_/ || + $2 !~ "NLA_TYPE_MASK" && + $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ || + $2 ~ /^SIOC/ || + $2 ~ /^TIOC/ || + $2 ~ /^TCGET/ || + $2 ~ /^TCSET/ || + $2 ~ /^TC(FLSH|SBRKP?|XONC)$/ || + $2 !~ "RTF_BITS" && + $2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ || + $2 ~ /^BIOC/ || + $2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ || + $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ || + $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ || + $2 ~ /^CLONE_[A-Z_]+/ || + $2 !~ /^(BPF_TIMEVAL)$/ && + $2 ~ /^(BPF|DLT)_/ || + $2 ~ /^CLOCK_/ || + $2 ~ /^CAN_/ || + $2 ~ /^CAP_/ || + $2 ~ /^ALG_/ || + $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ || + $2 ~ /^GRND_/ || + $2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ || + $2 ~ /^KEYCTL_/ || + $2 ~ /^PERF_EVENT_IOC_/ || + $2 ~ /^SECCOMP_MODE_/ || + $2 ~ /^SPLICE_/ || + $2 ~ /^SYNC_FILE_RANGE_/ || + $2 !~ /^AUDIT_RECORD_MAGIC/ && + $2 !~ /IOC_MAGIC/ && + $2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ || + $2 ~ /^(VM|VMADDR)_/ || + $2 ~ /^IOCTL_VM_SOCKETS_/ || + $2 ~ /^(TASKSTATS|TS)_/ || + $2 ~ /^CGROUPSTATS_/ || + $2 ~ /^GENL_/ || + $2 ~ /^STATX_/ || + $2 ~ /^RENAME/ || + $2 ~ /^UBI_IOC[A-Z]/ || + $2 ~ /^UTIME_/ || + $2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ || + $2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ || + $2 ~ /^FSOPT_/ || + $2 ~ /^WDIOC_/ || + $2 ~ /^NFN/ || + $2 ~ /^XDP_/ || + $2 ~ /^(HDIO|WIN|SMART)_/ || + $2 !~ "WMESGLEN" && + $2 ~ /^W[A-Z0-9]+$/ || + $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)} + $2 ~ /^__WCOREFLAG$/ {next} + $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)} + + {next} + ' | sort + + echo ')' +) >_const.go + +# Pull out the error names for later. +errors=$( + echo '#include ' | $CC -x c - -E -dM $ccflags | + awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' | + sort +) + +# Pull out the signal names for later. +signals=$( + echo '#include ' | $CC -x c - -E -dM $ccflags | + awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' | + egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | + sort +) + +# Again, writing regexps to a file. +echo '#include ' | $CC -x c - -E -dM $ccflags | + awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' | + sort >_error.grep +echo '#include ' | $CC -x c - -E -dM $ccflags | + awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' | + egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | + sort >_signal.grep + +echo '// mkerrors.sh' "$@" +echo '// Code generated by the command above; see README.md. DO NOT EDIT.' +echo +echo "// +build ${GOARCH},${GOOS}" +echo +go tool cgo -godefs -- "$@" _const.go >_error.out +cat _error.out | grep -vf _error.grep | grep -vf _signal.grep +echo +echo '// Errors' +echo 'const (' +cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= syscall.Errno(\1)/' +echo ')' + +echo +echo '// Signals' +echo 'const (' +cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= syscall.Signal(\1)/' +echo ')' + +# Run C program to print error and syscall strings. +( + echo -E " +#include +#include +#include +#include +#include +#include + +#define nelem(x) (sizeof(x)/sizeof((x)[0])) + +enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below + +struct tuple { + int num; + const char *name; +}; + +struct tuple errors[] = { +" + for i in $errors + do + echo -E ' {'$i', "'$i'" },' + done + + echo -E " +}; + +struct tuple signals[] = { +" + for i in $signals + do + echo -E ' {'$i', "'$i'" },' + done + + # Use -E because on some systems bash builtin interprets \n itself. + echo -E ' +}; + +static int +tuplecmp(const void *a, const void *b) +{ + return ((struct tuple *)a)->num - ((struct tuple *)b)->num; +} + +int +main(void) +{ + int i, e; + char buf[1024], *p; + + printf("\n\n// Error table\n"); + printf("var errorList = [...]struct {\n"); + printf("\tnum syscall.Errno\n"); + printf("\tname string\n"); + printf("\tdesc string\n"); + printf("} {\n"); + qsort(errors, nelem(errors), sizeof errors[0], tuplecmp); + for(i=0; i 0 && errors[i-1].num == e) + continue; + strcpy(buf, strerror(e)); + // lowercase first letter: Bad -> bad, but STREAM -> STREAM. + if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) + buf[0] += a - A; + printf("\t{ %d, \"%s\", \"%s\" },\n", e, errors[i].name, buf); + } + printf("}\n\n"); + + printf("\n\n// Signal table\n"); + printf("var signalList = [...]struct {\n"); + printf("\tnum syscall.Signal\n"); + printf("\tname string\n"); + printf("\tdesc string\n"); + printf("} {\n"); + qsort(signals, nelem(signals), sizeof signals[0], tuplecmp); + for(i=0; i 0 && signals[i-1].num == e) + continue; + strcpy(buf, strsignal(e)); + // lowercase first letter: Bad -> bad, but STREAM -> STREAM. + if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) + buf[0] += a - A; + // cut trailing : number. + p = strrchr(buf, ":"[0]); + if(p) + *p = '\0'; + printf("\t{ %d, \"%s\", \"%s\" },\n", e, signals[i].name, buf); + } + printf("}\n\n"); + + return 0; +} + +' +) >_errors.c + +$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out diff --git a/vendor/golang.org/x/sys/unix/mksyscall.pl b/vendor/golang.org/x/sys/unix/mksyscall.pl new file mode 100644 index 0000000000..1f6b926f8c --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksyscall.pl @@ -0,0 +1,341 @@ +#!/usr/bin/env perl +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# This program reads a file containing function prototypes +# (like syscall_darwin.go) and generates system call bodies. +# The prototypes are marked by lines beginning with "//sys" +# and read like func declarations if //sys is replaced by func, but: +# * The parameter lists must give a name for each argument. +# This includes return parameters. +# * The parameter lists must give a type for each argument: +# the (x, y, z int) shorthand is not allowed. +# * If the return parameter is an error number, it must be named errno. + +# A line beginning with //sysnb is like //sys, except that the +# goroutine will not be suspended during the execution of the system +# call. This must only be used for system calls which can never +# block, as otherwise the system call could cause all goroutines to +# hang. + +use strict; + +my $cmdline = "mksyscall.pl " . join(' ', @ARGV); +my $errors = 0; +my $_32bit = ""; +my $plan9 = 0; +my $openbsd = 0; +my $netbsd = 0; +my $dragonfly = 0; +my $arm = 0; # 64-bit value should use (even, odd)-pair +my $tags = ""; # build tags + +if($ARGV[0] eq "-b32") { + $_32bit = "big-endian"; + shift; +} elsif($ARGV[0] eq "-l32") { + $_32bit = "little-endian"; + shift; +} +if($ARGV[0] eq "-plan9") { + $plan9 = 1; + shift; +} +if($ARGV[0] eq "-openbsd") { + $openbsd = 1; + shift; +} +if($ARGV[0] eq "-netbsd") { + $netbsd = 1; + shift; +} +if($ARGV[0] eq "-dragonfly") { + $dragonfly = 1; + shift; +} +if($ARGV[0] eq "-arm") { + $arm = 1; + shift; +} +if($ARGV[0] eq "-tags") { + shift; + $tags = $ARGV[0]; + shift; +} + +if($ARGV[0] =~ /^-/) { + print STDERR "usage: mksyscall.pl [-b32 | -l32] [-tags x,y] [file ...]\n"; + exit 1; +} + +# Check that we are using the new build system if we should +if($ENV{'GOOS'} eq "linux" && $ENV{'GOARCH'} ne "sparc64") { + if($ENV{'GOLANG_SYS_BUILD'} ne "docker") { + print STDERR "In the new build system, mksyscall should not be called directly.\n"; + print STDERR "See README.md\n"; + exit 1; + } +} + + +sub parseparamlist($) { + my ($list) = @_; + $list =~ s/^\s*//; + $list =~ s/\s*$//; + if($list eq "") { + return (); + } + return split(/\s*,\s*/, $list); +} + +sub parseparam($) { + my ($p) = @_; + if($p !~ /^(\S*) (\S*)$/) { + print STDERR "$ARGV:$.: malformed parameter: $p\n"; + $errors = 1; + return ("xx", "int"); + } + return ($1, $2); +} + +my $text = ""; +while(<>) { + chomp; + s/\s+/ /g; + s/^\s+//; + s/\s+$//; + my $nonblock = /^\/\/sysnb /; + next if !/^\/\/sys / && !$nonblock; + + # Line must be of the form + # func Open(path string, mode int, perm int) (fd int, errno error) + # Split into name, in params, out params. + if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$/) { + print STDERR "$ARGV:$.: malformed //sys declaration\n"; + $errors = 1; + next; + } + my ($func, $in, $out, $sysname) = ($2, $3, $4, $5); + + # Split argument lists on comma. + my @in = parseparamlist($in); + my @out = parseparamlist($out); + + # Try in vain to keep people from editing this file. + # The theory is that they jump into the middle of the file + # without reading the header. + $text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; + + # Go function header. + my $out_decl = @out ? sprintf(" (%s)", join(', ', @out)) : ""; + $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out_decl; + + # Check if err return available + my $errvar = ""; + foreach my $p (@out) { + my ($name, $type) = parseparam($p); + if($type eq "error") { + $errvar = $name; + last; + } + } + + # Prepare arguments to Syscall. + my @args = (); + my $n = 0; + foreach my $p (@in) { + my ($name, $type) = parseparam($p); + if($type =~ /^\*/) { + push @args, "uintptr(unsafe.Pointer($name))"; + } elsif($type eq "string" && $errvar ne "") { + $text .= "\tvar _p$n *byte\n"; + $text .= "\t_p$n, $errvar = BytePtrFromString($name)\n"; + $text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; + push @args, "uintptr(unsafe.Pointer(_p$n))"; + $n++; + } elsif($type eq "string") { + print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n"; + $text .= "\tvar _p$n *byte\n"; + $text .= "\t_p$n, _ = BytePtrFromString($name)\n"; + push @args, "uintptr(unsafe.Pointer(_p$n))"; + $n++; + } elsif($type =~ /^\[\](.*)/) { + # Convert slice into pointer, length. + # Have to be careful not to take address of &a[0] if len == 0: + # pass dummy pointer in that case. + # Used to pass nil, but some OSes or simulators reject write(fd, nil, 0). + $text .= "\tvar _p$n unsafe.Pointer\n"; + $text .= "\tif len($name) > 0 {\n\t\t_p$n = unsafe.Pointer(\&${name}[0])\n\t}"; + $text .= " else {\n\t\t_p$n = unsafe.Pointer(&_zero)\n\t}"; + $text .= "\n"; + push @args, "uintptr(_p$n)", "uintptr(len($name))"; + $n++; + } elsif($type eq "int64" && ($openbsd || $netbsd)) { + push @args, "0"; + if($_32bit eq "big-endian") { + push @args, "uintptr($name>>32)", "uintptr($name)"; + } elsif($_32bit eq "little-endian") { + push @args, "uintptr($name)", "uintptr($name>>32)"; + } else { + push @args, "uintptr($name)"; + } + } elsif($type eq "int64" && $dragonfly) { + if ($func !~ /^extp(read|write)/i) { + push @args, "0"; + } + if($_32bit eq "big-endian") { + push @args, "uintptr($name>>32)", "uintptr($name)"; + } elsif($_32bit eq "little-endian") { + push @args, "uintptr($name)", "uintptr($name>>32)"; + } else { + push @args, "uintptr($name)"; + } + } elsif($type eq "int64" && $_32bit ne "") { + if(@args % 2 && $arm) { + # arm abi specifies 64-bit argument uses + # (even, odd) pair + push @args, "0" + } + if($_32bit eq "big-endian") { + push @args, "uintptr($name>>32)", "uintptr($name)"; + } else { + push @args, "uintptr($name)", "uintptr($name>>32)"; + } + } else { + push @args, "uintptr($name)"; + } + } + + # Determine which form to use; pad args with zeros. + my $asm = "Syscall"; + if ($nonblock) { + if ($errvar eq "" && $ENV{'GOOS'} eq "linux") { + $asm = "RawSyscallNoError"; + } else { + $asm = "RawSyscall"; + } + } else { + if ($errvar eq "" && $ENV{'GOOS'} eq "linux") { + $asm = "SyscallNoError"; + } + } + if(@args <= 3) { + while(@args < 3) { + push @args, "0"; + } + } elsif(@args <= 6) { + $asm .= "6"; + while(@args < 6) { + push @args, "0"; + } + } elsif(@args <= 9) { + $asm .= "9"; + while(@args < 9) { + push @args, "0"; + } + } else { + print STDERR "$ARGV:$.: too many arguments to system call\n"; + } + + # System call number. + if($sysname eq "") { + $sysname = "SYS_$func"; + $sysname =~ s/([a-z])([A-Z])/${1}_$2/g; # turn FooBar into Foo_Bar + $sysname =~ y/a-z/A-Z/; + } + + # Actual call. + my $args = join(', ', @args); + my $call = "$asm($sysname, $args)"; + + # Assign return values. + my $body = ""; + my @ret = ("_", "_", "_"); + my $do_errno = 0; + for(my $i=0; $i<@out; $i++) { + my $p = $out[$i]; + my ($name, $type) = parseparam($p); + my $reg = ""; + if($name eq "err" && !$plan9) { + $reg = "e1"; + $ret[2] = $reg; + $do_errno = 1; + } elsif($name eq "err" && $plan9) { + $ret[0] = "r0"; + $ret[2] = "e1"; + next; + } else { + $reg = sprintf("r%d", $i); + $ret[$i] = $reg; + } + if($type eq "bool") { + $reg = "$reg != 0"; + } + if($type eq "int64" && $_32bit ne "") { + # 64-bit number in r1:r0 or r0:r1. + if($i+2 > @out) { + print STDERR "$ARGV:$.: not enough registers for int64 return\n"; + } + if($_32bit eq "big-endian") { + $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1); + } else { + $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i); + } + $ret[$i] = sprintf("r%d", $i); + $ret[$i+1] = sprintf("r%d", $i+1); + } + if($reg ne "e1" || $plan9) { + $body .= "\t$name = $type($reg)\n"; + } + } + if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") { + $text .= "\t$call\n"; + } else { + if ($errvar eq "" && $ENV{'GOOS'} eq "linux") { + # raw syscall without error on Linux, see golang.org/issue/22924 + $text .= "\t$ret[0], $ret[1] := $call\n"; + } else { + $text .= "\t$ret[0], $ret[1], $ret[2] := $call\n"; + } + } + $text .= $body; + + if ($plan9 && $ret[2] eq "e1") { + $text .= "\tif int32(r0) == -1 {\n"; + $text .= "\t\terr = e1\n"; + $text .= "\t}\n"; + } elsif ($do_errno) { + $text .= "\tif e1 != 0 {\n"; + $text .= "\t\terr = errnoErr(e1)\n"; + $text .= "\t}\n"; + } + $text .= "\treturn\n"; + $text .= "}\n\n"; +} + +chomp $text; +chomp $text; + +if($errors) { + exit 1; +} + +print <) { + chomp; + s/\s+/ /g; + s/^\s+//; + s/\s+$//; + $package = $1 if !$package && /^package (\S+)$/; + my $nonblock = /^\/\/sysnb /; + next if !/^\/\/sys / && !$nonblock; + + # Line must be of the form + # func Open(path string, mode int, perm int) (fd int, err error) + # Split into name, in params, out params. + if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) { + print STDERR "$ARGV:$.: malformed //sys declaration\n"; + $errors = 1; + next; + } + my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6); + + # Split argument lists on comma. + my @in = parseparamlist($in); + my @out = parseparamlist($out); + + $in = join(', ', @in); + $out = join(', ', @out); + + # Try in vain to keep people from editing this file. + # The theory is that they jump into the middle of the file + # without reading the header. + $text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; + + # Check if value return, err return available + my $errvar = ""; + my $retvar = ""; + my $rettype = ""; + foreach my $p (@out) { + my ($name, $type) = parseparam($p); + if($type eq "error") { + $errvar = $name; + } else { + $retvar = $name; + $rettype = $type; + } + } + + # System call name. + #if($func ne "fcntl") { + + if($sysname eq "") { + $sysname = "$func"; + } + + $sysname =~ s/([a-z])([A-Z])/${1}_$2/g; + $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase. + + my $C_rettype = ""; + if($rettype eq "unsafe.Pointer") { + $C_rettype = "uintptr_t"; + } elsif($rettype eq "uintptr") { + $C_rettype = "uintptr_t"; + } elsif($rettype =~ /^_/) { + $C_rettype = "uintptr_t"; + } elsif($rettype eq "int") { + $C_rettype = "int"; + } elsif($rettype eq "int32") { + $C_rettype = "int"; + } elsif($rettype eq "int64") { + $C_rettype = "long long"; + } elsif($rettype eq "uint32") { + $C_rettype = "unsigned int"; + } elsif($rettype eq "uint64") { + $C_rettype = "unsigned long long"; + } else { + $C_rettype = "int"; + } + if($sysname eq "exit") { + $C_rettype = "void"; + } + + # Change types to c + my @c_in = (); + foreach my $p (@in) { + my ($name, $type) = parseparam($p); + if($type =~ /^\*/) { + push @c_in, "uintptr_t"; + } elsif($type eq "string") { + push @c_in, "uintptr_t"; + } elsif($type =~ /^\[\](.*)/) { + push @c_in, "uintptr_t", "size_t"; + } elsif($type eq "unsafe.Pointer") { + push @c_in, "uintptr_t"; + } elsif($type eq "uintptr") { + push @c_in, "uintptr_t"; + } elsif($type =~ /^_/) { + push @c_in, "uintptr_t"; + } elsif($type eq "int") { + push @c_in, "int"; + } elsif($type eq "int32") { + push @c_in, "int"; + } elsif($type eq "int64") { + push @c_in, "long long"; + } elsif($type eq "uint32") { + push @c_in, "unsigned int"; + } elsif($type eq "uint64") { + push @c_in, "unsigned long long"; + } else { + push @c_in, "int"; + } + } + + if ($func ne "fcntl" && $func ne "FcntlInt" && $func ne "readlen" && $func ne "writelen") { + # Imports of system calls from libc + $c_extern .= "$C_rettype $sysname"; + my $c_in = join(', ', @c_in); + $c_extern .= "($c_in);\n"; + } + + # So file name. + if($aix) { + if($modname eq "") { + $modname = "libc.a/shr_64.o"; + } else { + print STDERR "$func: only syscall using libc are available\n"; + $errors = 1; + next; + } + } + + my $strconvfunc = "C.CString"; + my $strconvtype = "*byte"; + + # Go function header. + if($out ne "") { + $out = " ($out)"; + } + if($text ne "") { + $text .= "\n" + } + + $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out ; + + # Prepare arguments to call. + my @args = (); + my $n = 0; + my $arg_n = 0; + foreach my $p (@in) { + my ($name, $type) = parseparam($p); + if($type =~ /^\*/) { + push @args, "C.uintptr_t(uintptr(unsafe.Pointer($name)))"; + } elsif($type eq "string" && $errvar ne "") { + $text .= "\t_p$n := uintptr(unsafe.Pointer($strconvfunc($name)))\n"; + push @args, "C.uintptr_t(_p$n)"; + $n++; + } elsif($type eq "string") { + print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n"; + $text .= "\t_p$n := uintptr(unsafe.Pointer($strconvfunc($name)))\n"; + push @args, "C.uintptr_t(_p$n)"; + $n++; + } elsif($type =~ /^\[\](.*)/) { + # Convert slice into pointer, length. + # Have to be careful not to take address of &a[0] if len == 0: + # pass nil in that case. + $text .= "\tvar _p$n *$1\n"; + $text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n"; + push @args, "C.uintptr_t(uintptr(unsafe.Pointer(_p$n)))"; + $n++; + $text .= "\tvar _p$n int\n"; + $text .= "\t_p$n = len($name)\n"; + push @args, "C.size_t(_p$n)"; + $n++; + } elsif($type eq "int64" && $_32bit ne "") { + if($_32bit eq "big-endian") { + push @args, "uintptr($name >> 32)", "uintptr($name)"; + } else { + push @args, "uintptr($name)", "uintptr($name >> 32)"; + } + $n++; + } elsif($type eq "bool") { + $text .= "\tvar _p$n uint32\n"; + $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n"; + push @args, "_p$n"; + $n++; + } elsif($type =~ /^_/) { + push @args, "C.uintptr_t(uintptr($name))"; + } elsif($type eq "unsafe.Pointer") { + push @args, "C.uintptr_t(uintptr($name))"; + } elsif($type eq "int") { + if (($arg_n == 2) && (($func eq "readlen") || ($func eq "writelen"))) { + push @args, "C.size_t($name)"; + } elsif ($arg_n == 0 && $func eq "fcntl") { + push @args, "C.uintptr_t($name)"; + } elsif (($arg_n == 2) && (($func eq "fcntl") || ($func eq "FcntlInt"))) { + push @args, "C.uintptr_t($name)"; + } else { + push @args, "C.int($name)"; + } + } elsif($type eq "int32") { + push @args, "C.int($name)"; + } elsif($type eq "int64") { + push @args, "C.longlong($name)"; + } elsif($type eq "uint32") { + push @args, "C.uint($name)"; + } elsif($type eq "uint64") { + push @args, "C.ulonglong($name)"; + } elsif($type eq "uintptr") { + push @args, "C.uintptr_t($name)"; + } else { + push @args, "C.int($name)"; + } + $arg_n++; + } + my $nargs = @args; + + + # Determine which form to use; pad args with zeros. + if ($nonblock) { + } + + my $args = join(', ', @args); + my $call = ""; + if ($sysname eq "exit") { + if ($errvar ne "") { + $call .= "er :="; + } else { + $call .= ""; + } + } elsif ($errvar ne "") { + $call .= "r0,er :="; + } elsif ($retvar ne "") { + $call .= "r0,_ :="; + } else { + $call .= "" + } + $call .= "C.$sysname($args)"; + + # Assign return values. + my $body = ""; + my $failexpr = ""; + + for(my $i=0; $i<@out; $i++) { + my $p = $out[$i]; + my ($name, $type) = parseparam($p); + my $reg = ""; + if($name eq "err") { + $reg = "e1"; + } else { + $reg = "r0"; + } + if($reg ne "e1" ) { + $body .= "\t$name = $type($reg)\n"; + } + } + + # verify return + if ($sysname ne "exit" && $errvar ne "") { + if ($C_rettype =~ /^uintptr/) { + $body .= "\tif \(uintptr\(r0\) ==\^uintptr\(0\) && er != nil\) {\n"; + $body .= "\t\t$errvar = er\n"; + $body .= "\t}\n"; + } else { + $body .= "\tif \(r0 ==-1 && er != nil\) {\n"; + $body .= "\t\t$errvar = er\n"; + $body .= "\t}\n"; + } + } elsif ($errvar ne "") { + $body .= "\tif \(er != nil\) {\n"; + $body .= "\t\t$errvar = er\n"; + $body .= "\t}\n"; + } + + $text .= "\t$call\n"; + $text .= $body; + + $text .= "\treturn\n"; + $text .= "}\n"; +} + +if($errors) { + exit 1; +} + +print <) { + chomp; + s/\s+/ /g; + s/^\s+//; + s/\s+$//; + $package = $1 if !$package && /^package (\S+)$/; + my $nonblock = /^\/\/sysnb /; + next if !/^\/\/sys / && !$nonblock; + + # Line must be of the form + # func Open(path string, mode int, perm int) (fd int, err error) + # Split into name, in params, out params. + if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) { + print STDERR "$ARGV:$.: malformed //sys declaration\n"; + $errors = 1; + next; + } + my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6); + + # Split argument lists on comma. + my @in = parseparamlist($in); + my @out = parseparamlist($out); + + $in = join(', ', @in); + $out = join(', ', @out); + + if($sysname eq "") { + $sysname = "$func"; + } + + my $onlyCommon = 0; + if ($func eq "readlen" || $func eq "writelen" || $func eq "FcntlInt" || $func eq "FcntlFlock") { + # This function call another syscall which is already implemented. + # Therefore, the gc and gccgo part must not be generated. + $onlyCommon = 1 + } + + # Try in vain to keep people from editing this file. + # The theory is that they jump into the middle of the file + # without reading the header. + + $textcommon .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; + if (!$onlyCommon) { + $textgccgo .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; + $textgc .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; + } + + + # Check if value return, err return available + my $errvar = ""; + my $retvar = ""; + my $rettype = ""; + foreach my $p (@out) { + my ($name, $type) = parseparam($p); + if($type eq "error") { + $errvar = $name; + } else { + $retvar = $name; + $rettype = $type; + } + } + + + $sysname =~ s/([a-z])([A-Z])/${1}_$2/g; + $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase. + + # GCCGO Prototype return type + my $C_rettype = ""; + if($rettype eq "unsafe.Pointer") { + $C_rettype = "uintptr_t"; + } elsif($rettype eq "uintptr") { + $C_rettype = "uintptr_t"; + } elsif($rettype =~ /^_/) { + $C_rettype = "uintptr_t"; + } elsif($rettype eq "int") { + $C_rettype = "int"; + } elsif($rettype eq "int32") { + $C_rettype = "int"; + } elsif($rettype eq "int64") { + $C_rettype = "long long"; + } elsif($rettype eq "uint32") { + $C_rettype = "unsigned int"; + } elsif($rettype eq "uint64") { + $C_rettype = "unsigned long long"; + } else { + $C_rettype = "int"; + } + if($sysname eq "exit") { + $C_rettype = "void"; + } + + # GCCGO Prototype arguments type + my @c_in = (); + foreach my $i (0 .. $#in) { + my ($name, $type) = parseparam($in[$i]); + if($type =~ /^\*/) { + push @c_in, "uintptr_t"; + } elsif($type eq "string") { + push @c_in, "uintptr_t"; + } elsif($type =~ /^\[\](.*)/) { + push @c_in, "uintptr_t", "size_t"; + } elsif($type eq "unsafe.Pointer") { + push @c_in, "uintptr_t"; + } elsif($type eq "uintptr") { + push @c_in, "uintptr_t"; + } elsif($type =~ /^_/) { + push @c_in, "uintptr_t"; + } elsif($type eq "int") { + if (($i == 0 || $i == 2) && $func eq "fcntl"){ + # These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock + push @c_in, "uintptr_t"; + } else { + push @c_in, "int"; + } + } elsif($type eq "int32") { + push @c_in, "int"; + } elsif($type eq "int64") { + push @c_in, "long long"; + } elsif($type eq "uint32") { + push @c_in, "unsigned int"; + } elsif($type eq "uint64") { + push @c_in, "unsigned long long"; + } else { + push @c_in, "int"; + } + } + + if (!$onlyCommon){ + # GCCGO Prototype Generation + # Imports of system calls from libc + $c_extern .= "$C_rettype $sysname"; + my $c_in = join(', ', @c_in); + $c_extern .= "($c_in);\n"; + } + + # GC Library name + if($modname eq "") { + $modname = "libc.a/shr_64.o"; + } else { + print STDERR "$func: only syscall using libc are available\n"; + $errors = 1; + next; + } + my $sysvarname = "libc_${sysname}"; + + if (!$onlyCommon){ + # GC Runtime import of function to allow cross-platform builds. + $dynimports .= "//go:cgo_import_dynamic ${sysvarname} ${sysname} \"$modname\"\n"; + # GC Link symbol to proc address variable. + $linknames .= "//go:linkname ${sysvarname} ${sysvarname}\n"; + # GC Library proc address variable. + push @vars, $sysvarname; + } + + my $strconvfunc ="BytePtrFromString"; + my $strconvtype = "*byte"; + + # Go function header. + if($out ne "") { + $out = " ($out)"; + } + if($textcommon ne "") { + $textcommon .= "\n" + } + + $textcommon .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out ; + + # Prepare arguments to call. + my @argscommun = (); # Arguments in the commun part + my @argscall = (); # Arguments for call prototype + my @argsgc = (); # Arguments for gc call (with syscall6) + my @argsgccgo = (); # Arguments for gccgo call (with C.name_of_syscall) + my $n = 0; + my $arg_n = 0; + foreach my $p (@in) { + my ($name, $type) = parseparam($p); + if($type =~ /^\*/) { + push @argscommun, "uintptr(unsafe.Pointer($name))"; + push @argscall, "$name uintptr"; + push @argsgc, "$name"; + push @argsgccgo, "C.uintptr_t($name)"; + } elsif($type eq "string" && $errvar ne "") { + $textcommon .= "\tvar _p$n $strconvtype\n"; + $textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n"; + $textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; + + push @argscommun, "uintptr(unsafe.Pointer(_p$n))"; + push @argscall, "_p$n uintptr "; + push @argsgc, "_p$n"; + push @argsgccgo, "C.uintptr_t(_p$n)"; + $n++; + } elsif($type eq "string") { + print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n"; + $textcommon .= "\tvar _p$n $strconvtype\n"; + $textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n"; + $textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; + + push @argscommun, "uintptr(unsafe.Pointer(_p$n))"; + push @argscall, "_p$n uintptr"; + push @argsgc, "_p$n"; + push @argsgccgo, "C.uintptr_t(_p$n)"; + $n++; + } elsif($type =~ /^\[\](.*)/) { + # Convert slice into pointer, length. + # Have to be careful not to take address of &a[0] if len == 0: + # pass nil in that case. + $textcommon .= "\tvar _p$n *$1\n"; + $textcommon .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n"; + push @argscommun, "uintptr(unsafe.Pointer(_p$n))", "len($name)"; + push @argscall, "_p$n uintptr", "_lenp$n int"; + push @argsgc, "_p$n", "uintptr(_lenp$n)"; + push @argsgccgo, "C.uintptr_t(_p$n)", "C.size_t(_lenp$n)"; + $n++; + } elsif($type eq "int64" && $_32bit ne "") { + print STDERR "$ARGV:$.: $func uses int64 with 32 bits mode. Case not yet implemented\n"; + # if($_32bit eq "big-endian") { + # push @args, "uintptr($name >> 32)", "uintptr($name)"; + # } else { + # push @args, "uintptr($name)", "uintptr($name >> 32)"; + # } + # $n++; + } elsif($type eq "bool") { + print STDERR "$ARGV:$.: $func uses bool. Case not yet implemented\n"; + # $text .= "\tvar _p$n uint32\n"; + # $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n"; + # push @args, "_p$n"; + # $n++; + } elsif($type =~ /^_/ ||$type eq "unsafe.Pointer") { + push @argscommun, "uintptr($name)"; + push @argscall, "$name uintptr"; + push @argsgc, "$name"; + push @argsgccgo, "C.uintptr_t($name)"; + } elsif($type eq "int") { + if (($arg_n == 0 || $arg_n == 2) && ($func eq "fcntl" || $func eq "FcntlInt" || $func eq "FcntlFlock")) { + # These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock + push @argscommun, "uintptr($name)"; + push @argscall, "$name uintptr"; + push @argsgc, "$name"; + push @argsgccgo, "C.uintptr_t($name)"; + } else { + push @argscommun, "$name"; + push @argscall, "$name int"; + push @argsgc, "uintptr($name)"; + push @argsgccgo, "C.int($name)"; + } + } elsif($type eq "int32") { + push @argscommun, "$name"; + push @argscall, "$name int32"; + push @argsgc, "uintptr($name)"; + push @argsgccgo, "C.int($name)"; + } elsif($type eq "int64") { + push @argscommun, "$name"; + push @argscall, "$name int64"; + push @argsgc, "uintptr($name)"; + push @argsgccgo, "C.longlong($name)"; + } elsif($type eq "uint32") { + push @argscommun, "$name"; + push @argscall, "$name uint32"; + push @argsgc, "uintptr($name)"; + push @argsgccgo, "C.uint($name)"; + } elsif($type eq "uint64") { + push @argscommun, "$name"; + push @argscall, "$name uint64"; + push @argsgc, "uintptr($name)"; + push @argsgccgo, "C.ulonglong($name)"; + } elsif($type eq "uintptr") { + push @argscommun, "$name"; + push @argscall, "$name uintptr"; + push @argsgc, "$name"; + push @argsgccgo, "C.uintptr_t($name)"; + } else { + push @argscommun, "int($name)"; + push @argscall, "$name int"; + push @argsgc, "uintptr($name)"; + push @argsgccgo, "C.int($name)"; + } + $arg_n++; + } + my $nargs = @argsgc; + + # COMMUN function generation + my $argscommun = join(', ', @argscommun); + my $callcommun = "call$sysname($argscommun)"; + my @ret = ("_", "_"); + my $body = ""; + my $do_errno = 0; + for(my $i=0; $i<@out; $i++) { + my $p = $out[$i]; + my ($name, $type) = parseparam($p); + my $reg = ""; + if($name eq "err") { + $reg = "e1"; + $ret[1] = $reg; + $do_errno = 1; + } else { + $reg = "r0"; + $ret[0] = $reg; + } + if($type eq "bool") { + $reg = "$reg != 0"; + } + if($reg ne "e1") { + $body .= "\t$name = $type($reg)\n"; + } + } + if ($ret[0] eq "_" && $ret[1] eq "_") { + $textcommon .= "\t$callcommun\n"; + } else { + $textcommon .= "\t$ret[0], $ret[1] := $callcommun\n"; + } + $textcommon .= $body; + + if ($do_errno) { + $textcommon .= "\tif e1 != 0 {\n"; + $textcommon .= "\t\terr = errnoErr(e1)\n"; + $textcommon .= "\t}\n"; + } + $textcommon .= "\treturn\n"; + $textcommon .= "}\n"; + + if ($onlyCommon){ + next + } + # CALL Prototype + my $callProto = sprintf "func call%s(%s) (r1 uintptr, e1 Errno) {\n", $sysname, join(', ', @argscall); + + # GC function generation + my $asm = "syscall6"; + if ($nonblock) { + $asm = "rawSyscall6"; + } + + if(@argsgc <= 6) { + while(@argsgc < 6) { + push @argsgc, "0"; + } + } else { + print STDERR "$ARGV:$.: too many arguments to system call\n"; + } + my $argsgc = join(', ', @argsgc); + my $callgc = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $argsgc)"; + + $textgc .= $callProto; + $textgc .= "\tr1, _, e1 = $callgc\n"; + $textgc .= "\treturn\n}\n"; + + # GCCGO function generation + my $argsgccgo = join(', ', @argsgccgo); + my $callgccgo = "C.$sysname($argsgccgo)"; + $textgccgo .= $callProto; + $textgccgo .= "\tr1 = uintptr($callgccgo)\n"; + $textgccgo .= "\te1 = syscall.GetErrno()\n"; + $textgccgo .= "\treturn\n}\n"; +} + +if($errors) { + exit 1; +} + +# Print zsyscall_aix_ppc64.go +open(my $fcommun, '>', 'zsyscall_aix_ppc64.go'); +my $tofcommun = <', 'zsyscall_aix_ppc64_gc.go'); +my $tofgc = <', 'zsyscall_aix_ppc64_gccgo.go'); +my $tofgccgo = <) { + chomp; + s/\s+/ /g; + s/^\s+//; + s/\s+$//; + $package = $1 if !$package && /^package (\S+)$/; + my $nonblock = /^\/\/sysnb /; + next if !/^\/\/sys / && !$nonblock; + + # Line must be of the form + # func Open(path string, mode int, perm int) (fd int, err error) + # Split into name, in params, out params. + if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) { + print STDERR "$ARGV:$.: malformed //sys declaration\n"; + $errors = 1; + next; + } + my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6); + + # Split argument lists on comma. + my @in = parseparamlist($in); + my @out = parseparamlist($out); + + # Try in vain to keep people from editing this file. + # The theory is that they jump into the middle of the file + # without reading the header. + $text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; + + # So file name. + if($modname eq "") { + $modname = "libc"; + } + + # System call name. + if($sysname eq "") { + $sysname = "$func"; + } + + # System call pointer variable name. + my $sysvarname = "proc$sysname"; + + my $strconvfunc = "BytePtrFromString"; + my $strconvtype = "*byte"; + + $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase. + + # Runtime import of function to allow cross-platform builds. + $dynimports .= "//go:cgo_import_dynamic libc_${sysname} ${sysname} \"$modname.so\"\n"; + # Link symbol to proc address variable. + $linknames .= "//go:linkname ${sysvarname} libc_${sysname}\n"; + # Library proc address variable. + push @vars, $sysvarname; + + # Go function header. + $out = join(', ', @out); + if($out ne "") { + $out = " ($out)"; + } + if($text ne "") { + $text .= "\n" + } + $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out; + + # Check if err return available + my $errvar = ""; + foreach my $p (@out) { + my ($name, $type) = parseparam($p); + if($type eq "error") { + $errvar = $name; + last; + } + } + + # Prepare arguments to Syscall. + my @args = (); + my $n = 0; + foreach my $p (@in) { + my ($name, $type) = parseparam($p); + if($type =~ /^\*/) { + push @args, "uintptr(unsafe.Pointer($name))"; + } elsif($type eq "string" && $errvar ne "") { + $text .= "\tvar _p$n $strconvtype\n"; + $text .= "\t_p$n, $errvar = $strconvfunc($name)\n"; + $text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; + push @args, "uintptr(unsafe.Pointer(_p$n))"; + $n++; + } elsif($type eq "string") { + print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n"; + $text .= "\tvar _p$n $strconvtype\n"; + $text .= "\t_p$n, _ = $strconvfunc($name)\n"; + push @args, "uintptr(unsafe.Pointer(_p$n))"; + $n++; + } elsif($type =~ /^\[\](.*)/) { + # Convert slice into pointer, length. + # Have to be careful not to take address of &a[0] if len == 0: + # pass nil in that case. + $text .= "\tvar _p$n *$1\n"; + $text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n"; + push @args, "uintptr(unsafe.Pointer(_p$n))", "uintptr(len($name))"; + $n++; + } elsif($type eq "int64" && $_32bit ne "") { + if($_32bit eq "big-endian") { + push @args, "uintptr($name >> 32)", "uintptr($name)"; + } else { + push @args, "uintptr($name)", "uintptr($name >> 32)"; + } + } elsif($type eq "bool") { + $text .= "\tvar _p$n uint32\n"; + $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n"; + push @args, "uintptr(_p$n)"; + $n++; + } else { + push @args, "uintptr($name)"; + } + } + my $nargs = @args; + + # Determine which form to use; pad args with zeros. + my $asm = "sysvicall6"; + if ($nonblock) { + $asm = "rawSysvicall6"; + } + if(@args <= 6) { + while(@args < 6) { + push @args, "0"; + } + } else { + print STDERR "$ARGV:$.: too many arguments to system call\n"; + } + + # Actual call. + my $args = join(', ', @args); + my $call = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $args)"; + + # Assign return values. + my $body = ""; + my $failexpr = ""; + my @ret = ("_", "_", "_"); + my @pout= (); + my $do_errno = 0; + for(my $i=0; $i<@out; $i++) { + my $p = $out[$i]; + my ($name, $type) = parseparam($p); + my $reg = ""; + if($name eq "err") { + $reg = "e1"; + $ret[2] = $reg; + $do_errno = 1; + } else { + $reg = sprintf("r%d", $i); + $ret[$i] = $reg; + } + if($type eq "bool") { + $reg = "$reg != 0"; + } + if($type eq "int64" && $_32bit ne "") { + # 64-bit number in r1:r0 or r0:r1. + if($i+2 > @out) { + print STDERR "$ARGV:$.: not enough registers for int64 return\n"; + } + if($_32bit eq "big-endian") { + $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1); + } else { + $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i); + } + $ret[$i] = sprintf("r%d", $i); + $ret[$i+1] = sprintf("r%d", $i+1); + } + if($reg ne "e1") { + $body .= "\t$name = $type($reg)\n"; + } + } + if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") { + $text .= "\t$call\n"; + } else { + $text .= "\t$ret[0], $ret[1], $ret[2] := $call\n"; + } + $text .= $body; + + if ($do_errno) { + $text .= "\tif e1 != 0 {\n"; + $text .= "\t\terr = e1\n"; + $text .= "\t}\n"; + } + $text .= "\treturn\n"; + $text .= "}\n"; +} + +if($errors) { + exit 1; +} + +print < "net.inet", + "net.inet.ipproto" => "net.inet", + "net.inet6.ipv6proto" => "net.inet6", + "net.inet6.ipv6" => "net.inet6.ip6", + "net.inet.icmpv6" => "net.inet6.icmp6", + "net.inet6.divert6" => "net.inet6.divert", + "net.inet6.tcp6" => "net.inet.tcp", + "net.inet6.udp6" => "net.inet.udp", + "mpls" => "net.mpls", + "swpenc" => "vm.swapencrypt" +); + +# Node mappings +my %node_map = ( + "net.inet.ip.ifq" => "net.ifq", + "net.inet.pfsync" => "net.pfsync", + "net.mpls.ifq" => "net.ifq" +); + +my $ctlname; +my %mib = (); +my %sysctl = (); +my $node; + +sub debug() { + print STDERR "$_[0]\n" if $debug; +} + +# Walk the MIB and build a sysctl name to OID mapping. +sub build_sysctl() { + my ($node, $name, $oid) = @_; + my %node = %{$node}; + my @oid = @{$oid}; + + foreach my $key (sort keys %node) { + my @node = @{$node{$key}}; + my $nodename = $name.($name ne '' ? '.' : '').$key; + my @nodeoid = (@oid, $node[0]); + if ($node[1] eq 'CTLTYPE_NODE') { + if (exists $node_map{$nodename}) { + $node = \%mib; + $ctlname = $node_map{$nodename}; + foreach my $part (split /\./, $ctlname) { + $node = \%{@{$$node{$part}}[2]}; + } + } else { + $node = $node[2]; + } + &build_sysctl($node, $nodename, \@nodeoid); + } elsif ($node[1] ne '') { + $sysctl{$nodename} = \@nodeoid; + } + } +} + +foreach my $ctl (@ctls) { + $ctls{$ctl} = $ctl; +} + +# Build MIB +foreach my $header (@headers) { + &debug("Processing $header..."); + open HEADER, "/usr/include/$header" || + print STDERR "Failed to open $header\n"; + while (
) { + if ($_ =~ /^#define\s+(CTL_NAMES)\s+{/ || + $_ =~ /^#define\s+(CTL_(.*)_NAMES)\s+{/ || + $_ =~ /^#define\s+((.*)CTL_NAMES)\s+{/) { + if ($1 eq 'CTL_NAMES') { + # Top level. + $node = \%mib; + } else { + # Node. + my $nodename = lc($2); + if ($header =~ /^netinet\//) { + $ctlname = "net.inet.$nodename"; + } elsif ($header =~ /^netinet6\//) { + $ctlname = "net.inet6.$nodename"; + } elsif ($header =~ /^net\//) { + $ctlname = "net.$nodename"; + } else { + $ctlname = "$nodename"; + $ctlname =~ s/^(fs|net|kern)_/$1\./; + } + if (exists $ctl_map{$ctlname}) { + $ctlname = $ctl_map{$ctlname}; + } + if (not exists $ctls{$ctlname}) { + &debug("Ignoring $ctlname..."); + next; + } + + # Walk down from the top of the MIB. + $node = \%mib; + foreach my $part (split /\./, $ctlname) { + if (not exists $$node{$part}) { + &debug("Missing node $part"); + $$node{$part} = [ 0, '', {} ]; + } + $node = \%{@{$$node{$part}}[2]}; + } + } + + # Populate current node with entries. + my $i = -1; + while (defined($_) && $_ !~ /^}/) { + $_ =
; + $i++ if $_ =~ /{.*}/; + next if $_ !~ /{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}/; + $$node{$1} = [ $i, $2, {} ]; + } + } + } + close HEADER; +} + +&build_sysctl(\%mib, "", []); + +print <){ + if(/^#define\s+SYS_(\w+)\s+([0-9]+)/){ + my $name = $1; + my $num = $2; + $name =~ y/a-z/A-Z/; + print " SYS_$name = $num;" + } +} + +print <){ + if(/^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$/){ + my $num = $1; + my $proto = $2; + my $name = "SYS_$3"; + $name =~ y/a-z/A-Z/; + + # There are multiple entries for enosys and nosys, so comment them out. + if($name =~ /^SYS_E?NOSYS$/){ + $name = "// $name"; + } + if($name eq 'SYS_SYS_EXIT'){ + $name = 'SYS_EXIT'; + } + + print " $name = $num; // $proto\n"; + } +} + +print <){ + if(/^([0-9]+)\s+\S+\s+(?:NO)?STD\s+({ \S+\s+(\w+).*)$/){ + my $num = $1; + my $proto = $2; + my $name = "SYS_$3"; + $name =~ y/a-z/A-Z/; + + # There are multiple entries for enosys and nosys, so comment them out. + if($name =~ /^SYS_E?NOSYS$/){ + $name = "// $name"; + } + if($name eq 'SYS_SYS_EXIT'){ + $name = 'SYS_EXIT'; + } + + print " $name = $num; // $proto\n"; + } +} + +print <){ + if($line =~ /^(.*)\\$/) { + # Handle continuation + $line = $1; + $_ =~ s/^\s+//; + $line .= $_; + } else { + # New line + $line = $_; + } + next if $line =~ /\\$/; + if($line =~ /^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$/) { + my $num = $1; + my $proto = $6; + my $compat = $8; + my $name = "$7_$9"; + + $name = "$7_$11" if $11 ne ''; + $name =~ y/a-z/A-Z/; + + if($compat eq '' || $compat eq '13' || $compat eq '30' || $compat eq '50') { + print " $name = $num; // $proto\n"; + } + } +} + +print <){ + if(/^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$/){ + my $num = $1; + my $proto = $3; + my $name = $4; + $name =~ y/a-z/A-Z/; + + # There are multiple entries for enosys and nosys, so comment them out. + if($name =~ /^SYS_E?NOSYS$/){ + $name = "// $name"; + } + if($name eq 'SYS_SYS_EXIT'){ + $name = 'SYS_EXIT'; + } + + print " $name = $num; // $proto\n"; + } +} + +print < 0 && (s[0] == '\t' || s[0] == ' '); s = s[1:] { - sep += s[:1] - } - - strings.NewReplacer(sep, "\n// ", "\n", "\n// ").WriteString(w, s) - - w.printf("\n") -} - -func (w *CodeWriter) writeSizeInfo(size int) { - w.printf("// Size: %d bytes\n", size) -} - -// WriteConst writes a constant of the given name and value. -func (w *CodeWriter) WriteConst(name string, x interface{}) { - w.insertSep() - v := reflect.ValueOf(x) - - switch v.Type().Kind() { - case reflect.String: - w.printf("const %s %s = ", name, typeName(x)) - w.WriteString(v.String()) - w.printf("\n") - default: - w.printf("const %s = %#v\n", name, x) - } -} - -// WriteVar writes a variable of the given name and value. -func (w *CodeWriter) WriteVar(name string, x interface{}) { - w.insertSep() - v := reflect.ValueOf(x) - oldSize := w.Size - sz := int(v.Type().Size()) - w.Size += sz - - switch v.Type().Kind() { - case reflect.String: - w.printf("var %s %s = ", name, typeName(x)) - w.WriteString(v.String()) - case reflect.Struct: - w.gob.Encode(x) - fallthrough - case reflect.Slice, reflect.Array: - w.printf("var %s = ", name) - w.writeValue(v) - w.writeSizeInfo(w.Size - oldSize) - default: - w.printf("var %s %s = ", name, typeName(x)) - w.gob.Encode(x) - w.writeValue(v) - w.writeSizeInfo(w.Size - oldSize) - } - w.printf("\n") -} - -func (w *CodeWriter) writeValue(v reflect.Value) { - x := v.Interface() - switch v.Kind() { - case reflect.String: - w.WriteString(v.String()) - case reflect.Array: - // Don't double count: callers of WriteArray count on the size being - // added, so we need to discount it here. - w.Size -= int(v.Type().Size()) - w.writeSlice(x, true) - case reflect.Slice: - w.writeSlice(x, false) - case reflect.Struct: - w.printf("%s{\n", typeName(v.Interface())) - t := v.Type() - for i := 0; i < v.NumField(); i++ { - w.printf("%s: ", t.Field(i).Name) - w.writeValue(v.Field(i)) - w.printf(",\n") - } - w.printf("}") - default: - w.printf("%#v", x) - } -} - -// WriteString writes a string literal. -func (w *CodeWriter) WriteString(s string) { - s = strings.Replace(s, `\`, `\\`, -1) - io.WriteString(w.Hash, s) // content hash - w.Size += len(s) - - const maxInline = 40 - if len(s) <= maxInline { - w.printf("%q", s) - return - } - - // We will render the string as a multi-line string. - const maxWidth = 80 - 4 - len(`"`) - len(`" +`) - - // When starting on its own line, go fmt indents line 2+ an extra level. - n, max := maxWidth, maxWidth-4 - - // As per https://golang.org/issue/18078, the compiler has trouble - // compiling the concatenation of many strings, s0 + s1 + s2 + ... + sN, - // for large N. We insert redundant, explicit parentheses to work around - // that, lowering the N at any given step: (s0 + s1 + ... + s63) + (s64 + - // ... + s127) + etc + (etc + ... + sN). - explicitParens, extraComment := len(s) > 128*1024, "" - if explicitParens { - w.printf(`(`) - extraComment = "; the redundant, explicit parens are for https://golang.org/issue/18078" - } - - // Print "" +\n, if a string does not start on its own line. - b := w.buf.Bytes() - if p := len(bytes.TrimRight(b, " \t")); p > 0 && b[p-1] != '\n' { - w.printf("\"\" + // Size: %d bytes%s\n", len(s), extraComment) - n, max = maxWidth, maxWidth - } - - w.printf(`"`) - - for sz, p, nLines := 0, 0, 0; p < len(s); { - var r rune - r, sz = utf8.DecodeRuneInString(s[p:]) - out := s[p : p+sz] - chars := 1 - if !unicode.IsPrint(r) || r == utf8.RuneError || r == '"' { - switch sz { - case 1: - out = fmt.Sprintf("\\x%02x", s[p]) - case 2, 3: - out = fmt.Sprintf("\\u%04x", r) - case 4: - out = fmt.Sprintf("\\U%08x", r) - } - chars = len(out) - } - if n -= chars; n < 0 { - nLines++ - if explicitParens && nLines&63 == 63 { - w.printf("\") + (\"") - } - w.printf("\" +\n\"") - n = max - len(out) - } - w.printf("%s", out) - p += sz - } - w.printf(`"`) - if explicitParens { - w.printf(`)`) - } -} - -// WriteSlice writes a slice value. -func (w *CodeWriter) WriteSlice(x interface{}) { - w.writeSlice(x, false) -} - -// WriteArray writes an array value. -func (w *CodeWriter) WriteArray(x interface{}) { - w.writeSlice(x, true) -} - -func (w *CodeWriter) writeSlice(x interface{}, isArray bool) { - v := reflect.ValueOf(x) - w.gob.Encode(v.Len()) - w.Size += v.Len() * int(v.Type().Elem().Size()) - name := typeName(x) - if isArray { - name = fmt.Sprintf("[%d]%s", v.Len(), name[strings.Index(name, "]")+1:]) - } - if isArray { - w.printf("%s{\n", name) - } else { - w.printf("%s{ // %d elements\n", name, v.Len()) - } - - switch kind := v.Type().Elem().Kind(); kind { - case reflect.String: - for _, s := range x.([]string) { - w.WriteString(s) - w.printf(",\n") - } - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - // nLine and nBlock are the number of elements per line and block. - nLine, nBlock, format := 8, 64, "%d," - switch kind { - case reflect.Uint8: - format = "%#02x," - case reflect.Uint16: - format = "%#04x," - case reflect.Uint32: - nLine, nBlock, format = 4, 32, "%#08x," - case reflect.Uint, reflect.Uint64: - nLine, nBlock, format = 4, 32, "%#016x," - case reflect.Int8: - nLine = 16 - } - n := nLine - for i := 0; i < v.Len(); i++ { - if i%nBlock == 0 && v.Len() > nBlock { - w.printf("// Entry %X - %X\n", i, i+nBlock-1) - } - x := v.Index(i).Interface() - w.gob.Encode(x) - w.printf(format, x) - if n--; n == 0 { - n = nLine - w.printf("\n") - } - } - w.printf("\n") - case reflect.Struct: - zero := reflect.Zero(v.Type().Elem()).Interface() - for i := 0; i < v.Len(); i++ { - x := v.Index(i).Interface() - w.gob.EncodeValue(v) - if !reflect.DeepEqual(zero, x) { - line := fmt.Sprintf("%#v,\n", x) - line = line[strings.IndexByte(line, '{'):] - w.printf("%d: ", i) - w.printf(line) - } - } - case reflect.Array: - for i := 0; i < v.Len(); i++ { - w.printf("%d: %#v,\n", i, v.Index(i).Interface()) - } - default: - panic("gen: slice elem type not supported") - } - w.printf("}") -} - -// WriteType writes a definition of the type of the given value and returns the -// type name. -func (w *CodeWriter) WriteType(x interface{}) string { - t := reflect.TypeOf(x) - w.printf("type %s struct {\n", t.Name()) - for i := 0; i < t.NumField(); i++ { - w.printf("\t%s %s\n", t.Field(i).Name, t.Field(i).Type) - } - w.printf("}\n") - return t.Name() -} - -// typeName returns the name of the go type of x. -func typeName(x interface{}) string { - t := reflect.ValueOf(x).Type() - return strings.Replace(fmt.Sprint(t), "main.", "", 1) -} diff --git a/vendor/golang.org/x/text/internal/gen/gen.go b/vendor/golang.org/x/text/internal/gen/gen.go deleted file mode 100644 index 2acb0355a2..0000000000 --- a/vendor/golang.org/x/text/internal/gen/gen.go +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package gen contains common code for the various code generation tools in the -// text repository. Its usage ensures consistency between tools. -// -// This package defines command line flags that are common to most generation -// tools. The flags allow for specifying specific Unicode and CLDR versions -// in the public Unicode data repository (http://www.unicode.org/Public). -// -// A local Unicode data mirror can be set through the flag -local or the -// environment variable UNICODE_DIR. The former takes precedence. The local -// directory should follow the same structure as the public repository. -// -// IANA data can also optionally be mirrored by putting it in the iana directory -// rooted at the top of the local mirror. Beware, though, that IANA data is not -// versioned. So it is up to the developer to use the right version. -package gen // import "golang.org/x/text/internal/gen" - -import ( - "bytes" - "flag" - "fmt" - "go/build" - "go/format" - "io" - "io/ioutil" - "log" - "net/http" - "os" - "path" - "path/filepath" - "sync" - "unicode" - - "golang.org/x/text/unicode/cldr" -) - -var ( - url = flag.String("url", - "http://www.unicode.org/Public", - "URL of Unicode database directory") - iana = flag.String("iana", - "http://www.iana.org", - "URL of the IANA repository") - unicodeVersion = flag.String("unicode", - getEnv("UNICODE_VERSION", unicode.Version), - "unicode version to use") - cldrVersion = flag.String("cldr", - getEnv("CLDR_VERSION", cldr.Version), - "cldr version to use") -) - -func getEnv(name, def string) string { - if v := os.Getenv(name); v != "" { - return v - } - return def -} - -// Init performs common initialization for a gen command. It parses the flags -// and sets up the standard logging parameters. -func Init() { - log.SetPrefix("") - log.SetFlags(log.Lshortfile) - flag.Parse() -} - -const header = `// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -package %s - -` - -// UnicodeVersion reports the requested Unicode version. -func UnicodeVersion() string { - return *unicodeVersion -} - -// UnicodeVersion reports the requested CLDR version. -func CLDRVersion() string { - return *cldrVersion -} - -// IsLocal reports whether data files are available locally. -func IsLocal() bool { - dir, err := localReadmeFile() - if err != nil { - return false - } - if _, err = os.Stat(dir); err != nil { - return false - } - return true -} - -// OpenUCDFile opens the requested UCD file. The file is specified relative to -// the public Unicode root directory. It will call log.Fatal if there are any -// errors. -func OpenUCDFile(file string) io.ReadCloser { - return openUnicode(path.Join(*unicodeVersion, "ucd", file)) -} - -// OpenCLDRCoreZip opens the CLDR core zip file. It will call log.Fatal if there -// are any errors. -func OpenCLDRCoreZip() io.ReadCloser { - return OpenUnicodeFile("cldr", *cldrVersion, "core.zip") -} - -// OpenUnicodeFile opens the requested file of the requested category from the -// root of the Unicode data archive. The file is specified relative to the -// public Unicode root directory. If version is "", it will use the default -// Unicode version. It will call log.Fatal if there are any errors. -func OpenUnicodeFile(category, version, file string) io.ReadCloser { - if version == "" { - version = UnicodeVersion() - } - return openUnicode(path.Join(category, version, file)) -} - -// OpenIANAFile opens the requested IANA file. The file is specified relative -// to the IANA root, which is typically either http://www.iana.org or the -// iana directory in the local mirror. It will call log.Fatal if there are any -// errors. -func OpenIANAFile(path string) io.ReadCloser { - return Open(*iana, "iana", path) -} - -var ( - dirMutex sync.Mutex - localDir string -) - -const permissions = 0755 - -func localReadmeFile() (string, error) { - p, err := build.Import("golang.org/x/text", "", build.FindOnly) - if err != nil { - return "", fmt.Errorf("Could not locate package: %v", err) - } - return filepath.Join(p.Dir, "DATA", "README"), nil -} - -func getLocalDir() string { - dirMutex.Lock() - defer dirMutex.Unlock() - - readme, err := localReadmeFile() - if err != nil { - log.Fatal(err) - } - dir := filepath.Dir(readme) - if _, err := os.Stat(readme); err != nil { - if err := os.MkdirAll(dir, permissions); err != nil { - log.Fatalf("Could not create directory: %v", err) - } - ioutil.WriteFile(readme, []byte(readmeTxt), permissions) - } - return dir -} - -const readmeTxt = `Generated by golang.org/x/text/internal/gen. DO NOT EDIT. - -This directory contains downloaded files used to generate the various tables -in the golang.org/x/text subrepo. - -Note that the language subtag repo (iana/assignments/language-subtag-registry) -and all other times in the iana subdirectory are not versioned and will need -to be periodically manually updated. The easiest way to do this is to remove -the entire iana directory. This is mostly of concern when updating the language -package. -` - -// Open opens subdir/path if a local directory is specified and the file exists, -// where subdir is a directory relative to the local root, or fetches it from -// urlRoot/path otherwise. It will call log.Fatal if there are any errors. -func Open(urlRoot, subdir, path string) io.ReadCloser { - file := filepath.Join(getLocalDir(), subdir, filepath.FromSlash(path)) - return open(file, urlRoot, path) -} - -func openUnicode(path string) io.ReadCloser { - file := filepath.Join(getLocalDir(), filepath.FromSlash(path)) - return open(file, *url, path) -} - -// TODO: automatically periodically update non-versioned files. - -func open(file, urlRoot, path string) io.ReadCloser { - if f, err := os.Open(file); err == nil { - return f - } - r := get(urlRoot, path) - defer r.Close() - b, err := ioutil.ReadAll(r) - if err != nil { - log.Fatalf("Could not download file: %v", err) - } - os.MkdirAll(filepath.Dir(file), permissions) - if err := ioutil.WriteFile(file, b, permissions); err != nil { - log.Fatalf("Could not create file: %v", err) - } - return ioutil.NopCloser(bytes.NewReader(b)) -} - -func get(root, path string) io.ReadCloser { - url := root + "/" + path - fmt.Printf("Fetching %s...", url) - defer fmt.Println(" done.") - resp, err := http.Get(url) - if err != nil { - log.Fatalf("HTTP GET: %v", err) - } - if resp.StatusCode != 200 { - log.Fatalf("Bad GET status for %q: %q", url, resp.Status) - } - return resp.Body -} - -// TODO: use Write*Version in all applicable packages. - -// WriteUnicodeVersion writes a constant for the Unicode version from which the -// tables are generated. -func WriteUnicodeVersion(w io.Writer) { - fmt.Fprintf(w, "// UnicodeVersion is the Unicode version from which the tables in this package are derived.\n") - fmt.Fprintf(w, "const UnicodeVersion = %q\n\n", UnicodeVersion()) -} - -// WriteCLDRVersion writes a constant for the CLDR version from which the -// tables are generated. -func WriteCLDRVersion(w io.Writer) { - fmt.Fprintf(w, "// CLDRVersion is the CLDR version from which the tables in this package are derived.\n") - fmt.Fprintf(w, "const CLDRVersion = %q\n\n", CLDRVersion()) -} - -// WriteGoFile prepends a standard file comment and package statement to the -// given bytes, applies gofmt, and writes them to a file with the given name. -// It will call log.Fatal if there are any errors. -func WriteGoFile(filename, pkg string, b []byte) { - w, err := os.Create(filename) - if err != nil { - log.Fatalf("Could not create file %s: %v", filename, err) - } - defer w.Close() - if _, err = WriteGo(w, pkg, b); err != nil { - log.Fatalf("Error writing file %s: %v", filename, err) - } -} - -// WriteGo prepends a standard file comment and package statement to the given -// bytes, applies gofmt, and writes them to w. -func WriteGo(w io.Writer, pkg string, b []byte) (n int, err error) { - src := []byte(fmt.Sprintf(header, pkg)) - src = append(src, b...) - formatted, err := format.Source(src) - if err != nil { - // Print the generated code even in case of an error so that the - // returned error can be meaningfully interpreted. - n, _ = w.Write(src) - return n, err - } - return w.Write(formatted) -} - -// Repackage rewrites a Go file from belonging to package main to belonging to -// the given package. -func Repackage(inFile, outFile, pkg string) { - src, err := ioutil.ReadFile(inFile) - if err != nil { - log.Fatalf("reading %s: %v", inFile, err) - } - const toDelete = "package main\n\n" - i := bytes.Index(src, []byte(toDelete)) - if i < 0 { - log.Fatalf("Could not find %q in %s.", toDelete, inFile) - } - w := &bytes.Buffer{} - w.Write(src[i+len(toDelete):]) - WriteGoFile(outFile, pkg, w.Bytes()) -} diff --git a/vendor/golang.org/x/text/internal/triegen/compact.go b/vendor/golang.org/x/text/internal/triegen/compact.go deleted file mode 100644 index 397b975c1b..0000000000 --- a/vendor/golang.org/x/text/internal/triegen/compact.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package triegen - -// This file defines Compacter and its implementations. - -import "io" - -// A Compacter generates an alternative, more space-efficient way to store a -// trie value block. A trie value block holds all possible values for the last -// byte of a UTF-8 encoded rune. Excluding ASCII characters, a trie value block -// always has 64 values, as a UTF-8 encoding ends with a byte in [0x80, 0xC0). -type Compacter interface { - // Size returns whether the Compacter could encode the given block as well - // as its size in case it can. len(v) is always 64. - Size(v []uint64) (sz int, ok bool) - - // Store stores the block using the Compacter's compression method. - // It returns a handle with which the block can be retrieved. - // len(v) is always 64. - Store(v []uint64) uint32 - - // Print writes the data structures associated to the given store to w. - Print(w io.Writer) error - - // Handler returns the name of a function that gets called during trie - // lookup for blocks generated by the Compacter. The function should be of - // the form func (n uint32, b byte) uint64, where n is the index returned by - // the Compacter's Store method and b is the last byte of the UTF-8 - // encoding, where 0x80 <= b < 0xC0, for which to do the lookup in the - // block. - Handler() string -} - -// simpleCompacter is the default Compacter used by builder. It implements a -// normal trie block. -type simpleCompacter builder - -func (b *simpleCompacter) Size([]uint64) (sz int, ok bool) { - return blockSize * b.ValueSize, true -} - -func (b *simpleCompacter) Store(v []uint64) uint32 { - h := uint32(len(b.ValueBlocks) - blockOffset) - b.ValueBlocks = append(b.ValueBlocks, v) - return h -} - -func (b *simpleCompacter) Print(io.Writer) error { - // Structures are printed in print.go. - return nil -} - -func (b *simpleCompacter) Handler() string { - panic("Handler should be special-cased for this Compacter") -} diff --git a/vendor/golang.org/x/text/internal/triegen/print.go b/vendor/golang.org/x/text/internal/triegen/print.go deleted file mode 100644 index 8d9f120bcd..0000000000 --- a/vendor/golang.org/x/text/internal/triegen/print.go +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package triegen - -import ( - "bytes" - "fmt" - "io" - "strings" - "text/template" -) - -// print writes all the data structures as well as the code necessary to use the -// trie to w. -func (b *builder) print(w io.Writer) error { - b.Stats.NValueEntries = len(b.ValueBlocks) * blockSize - b.Stats.NValueBytes = len(b.ValueBlocks) * blockSize * b.ValueSize - b.Stats.NIndexEntries = len(b.IndexBlocks) * blockSize - b.Stats.NIndexBytes = len(b.IndexBlocks) * blockSize * b.IndexSize - b.Stats.NHandleBytes = len(b.Trie) * 2 * b.IndexSize - - // If we only have one root trie, all starter blocks are at position 0 and - // we can access the arrays directly. - if len(b.Trie) == 1 { - // At this point we cannot refer to the generated tables directly. - b.ASCIIBlock = b.Name + "Values" - b.StarterBlock = b.Name + "Index" - } else { - // Otherwise we need to have explicit starter indexes in the trie - // structure. - b.ASCIIBlock = "t.ascii" - b.StarterBlock = "t.utf8Start" - } - - b.SourceType = "[]byte" - if err := lookupGen.Execute(w, b); err != nil { - return err - } - - b.SourceType = "string" - if err := lookupGen.Execute(w, b); err != nil { - return err - } - - if err := trieGen.Execute(w, b); err != nil { - return err - } - - for _, c := range b.Compactions { - if err := c.c.Print(w); err != nil { - return err - } - } - - return nil -} - -func printValues(n int, values []uint64) string { - w := &bytes.Buffer{} - boff := n * blockSize - fmt.Fprintf(w, "\t// Block %#x, offset %#x", n, boff) - var newline bool - for i, v := range values { - if i%6 == 0 { - newline = true - } - if v != 0 { - if newline { - fmt.Fprintf(w, "\n") - newline = false - } - fmt.Fprintf(w, "\t%#02x:%#04x, ", boff+i, v) - } - } - return w.String() -} - -func printIndex(b *builder, nr int, n *node) string { - w := &bytes.Buffer{} - boff := nr * blockSize - fmt.Fprintf(w, "\t// Block %#x, offset %#x", nr, boff) - var newline bool - for i, c := range n.children { - if i%8 == 0 { - newline = true - } - if c != nil { - v := b.Compactions[c.index.compaction].Offset + uint32(c.index.index) - if v != 0 { - if newline { - fmt.Fprintf(w, "\n") - newline = false - } - fmt.Fprintf(w, "\t%#02x:%#02x, ", boff+i, v) - } - } - } - return w.String() -} - -var ( - trieGen = template.Must(template.New("trie").Funcs(template.FuncMap{ - "printValues": printValues, - "printIndex": printIndex, - "title": strings.Title, - "dec": func(x int) int { return x - 1 }, - "psize": func(n int) string { - return fmt.Sprintf("%d bytes (%.2f KiB)", n, float64(n)/1024) - }, - }).Parse(trieTemplate)) - lookupGen = template.Must(template.New("lookup").Parse(lookupTemplate)) -) - -// TODO: consider the return type of lookup. It could be uint64, even if the -// internal value type is smaller. We will have to verify this with the -// performance of unicode/norm, which is very sensitive to such changes. -const trieTemplate = `{{$b := .}}{{$multi := gt (len .Trie) 1}} -// {{.Name}}Trie. Total size: {{psize .Size}}. Checksum: {{printf "%08x" .Checksum}}. -type {{.Name}}Trie struct { {{if $multi}} - ascii []{{.ValueType}} // index for ASCII bytes - utf8Start []{{.IndexType}} // index for UTF-8 bytes >= 0xC0 -{{end}}} - -func new{{title .Name}}Trie(i int) *{{.Name}}Trie { {{if $multi}} - h := {{.Name}}TrieHandles[i] - return &{{.Name}}Trie{ {{.Name}}Values[uint32(h.ascii)<<6:], {{.Name}}Index[uint32(h.multi)<<6:] } -} - -type {{.Name}}TrieHandle struct { - ascii, multi {{.IndexType}} -} - -// {{.Name}}TrieHandles: {{len .Trie}} handles, {{.Stats.NHandleBytes}} bytes -var {{.Name}}TrieHandles = [{{len .Trie}}]{{.Name}}TrieHandle{ -{{range .Trie}} { {{.ASCIIIndex}}, {{.StarterIndex}} }, // {{printf "%08x" .Checksum}}: {{.Name}} -{{end}}}{{else}} - return &{{.Name}}Trie{} -} -{{end}} -// lookupValue determines the type of block n and looks up the value for b. -func (t *{{.Name}}Trie) lookupValue(n uint32, b byte) {{.ValueType}}{{$last := dec (len .Compactions)}} { - switch { {{range $i, $c := .Compactions}} - {{if eq $i $last}}default{{else}}case n < {{$c.Cutoff}}{{end}}:{{if ne $i 0}} - n -= {{$c.Offset}}{{end}} - return {{print $b.ValueType}}({{$c.Handler}}){{end}} - } -} - -// {{.Name}}Values: {{len .ValueBlocks}} blocks, {{.Stats.NValueEntries}} entries, {{.Stats.NValueBytes}} bytes -// The third block is the zero block. -var {{.Name}}Values = [{{.Stats.NValueEntries}}]{{.ValueType}} { -{{range $i, $v := .ValueBlocks}}{{printValues $i $v}} -{{end}}} - -// {{.Name}}Index: {{len .IndexBlocks}} blocks, {{.Stats.NIndexEntries}} entries, {{.Stats.NIndexBytes}} bytes -// Block 0 is the zero block. -var {{.Name}}Index = [{{.Stats.NIndexEntries}}]{{.IndexType}} { -{{range $i, $v := .IndexBlocks}}{{printIndex $b $i $v}} -{{end}}} -` - -// TODO: consider allowing zero-length strings after evaluating performance with -// unicode/norm. -const lookupTemplate = ` -// lookup{{if eq .SourceType "string"}}String{{end}} returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *{{.Name}}Trie) lookup{{if eq .SourceType "string"}}String{{end}}(s {{.SourceType}}) (v {{.ValueType}}, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return {{.ASCIIBlock}}[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := {{.StarterBlock}}[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := {{.StarterBlock}}[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = {{.Name}}Index[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := {{.StarterBlock}}[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = {{.Name}}Index[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = {{.Name}}Index[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookup{{if eq .SourceType "string"}}String{{end}}Unsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *{{.Name}}Trie) lookup{{if eq .SourceType "string"}}String{{end}}Unsafe(s {{.SourceType}}) {{.ValueType}} { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return {{.ASCIIBlock}}[c0] - } - i := {{.StarterBlock}}[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = {{.Name}}Index[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = {{.Name}}Index[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} -` diff --git a/vendor/golang.org/x/text/internal/triegen/triegen.go b/vendor/golang.org/x/text/internal/triegen/triegen.go deleted file mode 100644 index adb0108124..0000000000 --- a/vendor/golang.org/x/text/internal/triegen/triegen.go +++ /dev/null @@ -1,494 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package triegen implements a code generator for a trie for associating -// unsigned integer values with UTF-8 encoded runes. -// -// Many of the go.text packages use tries for storing per-rune information. A -// trie is especially useful if many of the runes have the same value. If this -// is the case, many blocks can be expected to be shared allowing for -// information on many runes to be stored in little space. -// -// As most of the lookups are done directly on []byte slices, the tries use the -// UTF-8 bytes directly for the lookup. This saves a conversion from UTF-8 to -// runes and contributes a little bit to better performance. It also naturally -// provides a fast path for ASCII. -// -// Space is also an issue. There are many code points defined in Unicode and as -// a result tables can get quite large. So every byte counts. The triegen -// package automatically chooses the smallest integer values to represent the -// tables. Compacters allow further compression of the trie by allowing for -// alternative representations of individual trie blocks. -// -// triegen allows generating multiple tries as a single structure. This is -// useful when, for example, one wants to generate tries for several languages -// that have a lot of values in common. Some existing libraries for -// internationalization store all per-language data as a dynamically loadable -// chunk. The go.text packages are designed with the assumption that the user -// typically wants to compile in support for all supported languages, in line -// with the approach common to Go to create a single standalone binary. The -// multi-root trie approach can give significant storage savings in this -// scenario. -// -// triegen generates both tables and code. The code is optimized to use the -// automatically chosen data types. The following code is generated for a Trie -// or multiple Tries named "foo": -// - type fooTrie -// The trie type. -// -// - func newFooTrie(x int) *fooTrie -// Trie constructor, where x is the index of the trie passed to Gen. -// -// - func (t *fooTrie) lookup(s []byte) (v uintX, sz int) -// The lookup method, where uintX is automatically chosen. -// -// - func lookupString, lookupUnsafe and lookupStringUnsafe -// Variants of the above. -// -// - var fooValues and fooIndex and any tables generated by Compacters. -// The core trie data. -// -// - var fooTrieHandles -// Indexes of starter blocks in case of multiple trie roots. -// -// It is recommended that users test the generated trie by checking the returned -// value for every rune. Such exhaustive tests are possible as the the number of -// runes in Unicode is limited. -package triegen // import "golang.org/x/text/internal/triegen" - -// TODO: Arguably, the internally optimized data types would not have to be -// exposed in the generated API. We could also investigate not generating the -// code, but using it through a package. We would have to investigate the impact -// on performance of making such change, though. For packages like unicode/norm, -// small changes like this could tank performance. - -import ( - "encoding/binary" - "fmt" - "hash/crc64" - "io" - "log" - "unicode/utf8" -) - -// builder builds a set of tries for associating values with runes. The set of -// tries can share common index and value blocks. -type builder struct { - Name string - - // ValueType is the type of the trie values looked up. - ValueType string - - // ValueSize is the byte size of the ValueType. - ValueSize int - - // IndexType is the type of trie index values used for all UTF-8 bytes of - // a rune except the last one. - IndexType string - - // IndexSize is the byte size of the IndexType. - IndexSize int - - // SourceType is used when generating the lookup functions. If the user - // requests StringSupport, all lookup functions will be generated for - // string input as well. - SourceType string - - Trie []*Trie - - IndexBlocks []*node - ValueBlocks [][]uint64 - Compactions []compaction - Checksum uint64 - - ASCIIBlock string - StarterBlock string - - indexBlockIdx map[uint64]int - valueBlockIdx map[uint64]nodeIndex - asciiBlockIdx map[uint64]int - - // Stats are used to fill out the template. - Stats struct { - NValueEntries int - NValueBytes int - NIndexEntries int - NIndexBytes int - NHandleBytes int - } - - err error -} - -// A nodeIndex encodes the index of a node, which is defined by the compaction -// which stores it and an index within the compaction. For internal nodes, the -// compaction is always 0. -type nodeIndex struct { - compaction int - index int -} - -// compaction keeps track of stats used for the compaction. -type compaction struct { - c Compacter - blocks []*node - maxHandle uint32 - totalSize int - - // Used by template-based generator and thus exported. - Cutoff uint32 - Offset uint32 - Handler string -} - -func (b *builder) setError(err error) { - if b.err == nil { - b.err = err - } -} - -// An Option can be passed to Gen. -type Option func(b *builder) error - -// Compact configures the trie generator to use the given Compacter. -func Compact(c Compacter) Option { - return func(b *builder) error { - b.Compactions = append(b.Compactions, compaction{ - c: c, - Handler: c.Handler() + "(n, b)"}) - return nil - } -} - -// Gen writes Go code for a shared trie lookup structure to w for the given -// Tries. The generated trie type will be called nameTrie. newNameTrie(x) will -// return the *nameTrie for tries[x]. A value can be looked up by using one of -// the various lookup methods defined on nameTrie. It returns the table size of -// the generated trie. -func Gen(w io.Writer, name string, tries []*Trie, opts ...Option) (sz int, err error) { - // The index contains two dummy blocks, followed by the zero block. The zero - // block is at offset 0x80, so that the offset for the zero block for - // continuation bytes is 0. - b := &builder{ - Name: name, - Trie: tries, - IndexBlocks: []*node{{}, {}, {}}, - Compactions: []compaction{{ - Handler: name + "Values[n<<6+uint32(b)]", - }}, - // The 0 key in indexBlockIdx and valueBlockIdx is the hash of the zero - // block. - indexBlockIdx: map[uint64]int{0: 0}, - valueBlockIdx: map[uint64]nodeIndex{0: {}}, - asciiBlockIdx: map[uint64]int{}, - } - b.Compactions[0].c = (*simpleCompacter)(b) - - for _, f := range opts { - if err := f(b); err != nil { - return 0, err - } - } - b.build() - if b.err != nil { - return 0, b.err - } - if err = b.print(w); err != nil { - return 0, err - } - return b.Size(), nil -} - -// A Trie represents a single root node of a trie. A builder may build several -// overlapping tries at once. -type Trie struct { - root *node - - hiddenTrie -} - -// hiddenTrie contains values we want to be visible to the template generator, -// but hidden from the API documentation. -type hiddenTrie struct { - Name string - Checksum uint64 - ASCIIIndex int - StarterIndex int -} - -// NewTrie returns a new trie root. -func NewTrie(name string) *Trie { - return &Trie{ - &node{ - children: make([]*node, blockSize), - values: make([]uint64, utf8.RuneSelf), - }, - hiddenTrie{Name: name}, - } -} - -// Gen is a convenience wrapper around the Gen func passing t as the only trie -// and uses the name passed to NewTrie. It returns the size of the generated -// tables. -func (t *Trie) Gen(w io.Writer, opts ...Option) (sz int, err error) { - return Gen(w, t.Name, []*Trie{t}, opts...) -} - -// node is a node of the intermediate trie structure. -type node struct { - // children holds this node's children. It is always of length 64. - // A child node may be nil. - children []*node - - // values contains the values of this node. If it is non-nil, this node is - // either a root or leaf node: - // For root nodes, len(values) == 128 and it maps the bytes in [0x00, 0x7F]. - // For leaf nodes, len(values) == 64 and it maps the bytes in [0x80, 0xBF]. - values []uint64 - - index nodeIndex -} - -// Insert associates value with the given rune. Insert will panic if a non-zero -// value is passed for an invalid rune. -func (t *Trie) Insert(r rune, value uint64) { - if value == 0 { - return - } - s := string(r) - if []rune(s)[0] != r && value != 0 { - // Note: The UCD tables will always assign what amounts to a zero value - // to a surrogate. Allowing a zero value for an illegal rune allows - // users to iterate over [0..MaxRune] without having to explicitly - // exclude surrogates, which would be tedious. - panic(fmt.Sprintf("triegen: non-zero value for invalid rune %U", r)) - } - if len(s) == 1 { - // It is a root node value (ASCII). - t.root.values[s[0]] = value - return - } - - n := t.root - for ; len(s) > 1; s = s[1:] { - if n.children == nil { - n.children = make([]*node, blockSize) - } - p := s[0] % blockSize - c := n.children[p] - if c == nil { - c = &node{} - n.children[p] = c - } - if len(s) > 2 && c.values != nil { - log.Fatalf("triegen: insert(%U): found internal node with values", r) - } - n = c - } - if n.values == nil { - n.values = make([]uint64, blockSize) - } - if n.children != nil { - log.Fatalf("triegen: insert(%U): found leaf node that also has child nodes", r) - } - n.values[s[0]-0x80] = value -} - -// Size returns the number of bytes the generated trie will take to store. It -// needs to be exported as it is used in the templates. -func (b *builder) Size() int { - // Index blocks. - sz := len(b.IndexBlocks) * blockSize * b.IndexSize - - // Skip the first compaction, which represents the normal value blocks, as - // its totalSize does not account for the ASCII blocks, which are managed - // separately. - sz += len(b.ValueBlocks) * blockSize * b.ValueSize - for _, c := range b.Compactions[1:] { - sz += c.totalSize - } - - // TODO: this computation does not account for the fixed overhead of a using - // a compaction, either code or data. As for data, though, the typical - // overhead of data is in the order of bytes (2 bytes for cases). Further, - // the savings of using a compaction should anyway be substantial for it to - // be worth it. - - // For multi-root tries, we also need to account for the handles. - if len(b.Trie) > 1 { - sz += 2 * b.IndexSize * len(b.Trie) - } - return sz -} - -func (b *builder) build() { - // Compute the sizes of the values. - var vmax uint64 - for _, t := range b.Trie { - vmax = maxValue(t.root, vmax) - } - b.ValueType, b.ValueSize = getIntType(vmax) - - // Compute all block allocations. - // TODO: first compute the ASCII blocks for all tries and then the other - // nodes. ASCII blocks are more restricted in placement, as they require two - // blocks to be placed consecutively. Processing them first may improve - // sharing (at least one zero block can be expected to be saved.) - for _, t := range b.Trie { - b.Checksum += b.buildTrie(t) - } - - // Compute the offsets for all the Compacters. - offset := uint32(0) - for i := range b.Compactions { - c := &b.Compactions[i] - c.Offset = offset - offset += c.maxHandle + 1 - c.Cutoff = offset - } - - // Compute the sizes of indexes. - // TODO: different byte positions could have different sizes. So far we have - // not found a case where this is beneficial. - imax := uint64(b.Compactions[len(b.Compactions)-1].Cutoff) - for _, ib := range b.IndexBlocks { - if x := uint64(ib.index.index); x > imax { - imax = x - } - } - b.IndexType, b.IndexSize = getIntType(imax) -} - -func maxValue(n *node, max uint64) uint64 { - if n == nil { - return max - } - for _, c := range n.children { - max = maxValue(c, max) - } - for _, v := range n.values { - if max < v { - max = v - } - } - return max -} - -func getIntType(v uint64) (string, int) { - switch { - case v < 1<<8: - return "uint8", 1 - case v < 1<<16: - return "uint16", 2 - case v < 1<<32: - return "uint32", 4 - } - return "uint64", 8 -} - -const ( - blockSize = 64 - - // Subtract two blocks to offset 0x80, the first continuation byte. - blockOffset = 2 - - // Subtract three blocks to offset 0xC0, the first non-ASCII starter. - rootBlockOffset = 3 -) - -var crcTable = crc64.MakeTable(crc64.ISO) - -func (b *builder) buildTrie(t *Trie) uint64 { - n := t.root - - // Get the ASCII offset. For the first trie, the ASCII block will be at - // position 0. - hasher := crc64.New(crcTable) - binary.Write(hasher, binary.BigEndian, n.values) - hash := hasher.Sum64() - - v, ok := b.asciiBlockIdx[hash] - if !ok { - v = len(b.ValueBlocks) - b.asciiBlockIdx[hash] = v - - b.ValueBlocks = append(b.ValueBlocks, n.values[:blockSize], n.values[blockSize:]) - if v == 0 { - // Add the zero block at position 2 so that it will be assigned a - // zero reference in the lookup blocks. - // TODO: always do this? This would allow us to remove a check from - // the trie lookup, but at the expense of extra space. Analyze - // performance for unicode/norm. - b.ValueBlocks = append(b.ValueBlocks, make([]uint64, blockSize)) - } - } - t.ASCIIIndex = v - - // Compute remaining offsets. - t.Checksum = b.computeOffsets(n, true) - // We already subtracted the normal blockOffset from the index. Subtract the - // difference for starter bytes. - t.StarterIndex = n.index.index - (rootBlockOffset - blockOffset) - return t.Checksum -} - -func (b *builder) computeOffsets(n *node, root bool) uint64 { - // For the first trie, the root lookup block will be at position 3, which is - // the offset for UTF-8 non-ASCII starter bytes. - first := len(b.IndexBlocks) == rootBlockOffset - if first { - b.IndexBlocks = append(b.IndexBlocks, n) - } - - // We special-case the cases where all values recursively are 0. This allows - // for the use of a zero block to which all such values can be directed. - hash := uint64(0) - if n.children != nil || n.values != nil { - hasher := crc64.New(crcTable) - for _, c := range n.children { - var v uint64 - if c != nil { - v = b.computeOffsets(c, false) - } - binary.Write(hasher, binary.BigEndian, v) - } - binary.Write(hasher, binary.BigEndian, n.values) - hash = hasher.Sum64() - } - - if first { - b.indexBlockIdx[hash] = rootBlockOffset - blockOffset - } - - // Compacters don't apply to internal nodes. - if n.children != nil { - v, ok := b.indexBlockIdx[hash] - if !ok { - v = len(b.IndexBlocks) - blockOffset - b.IndexBlocks = append(b.IndexBlocks, n) - b.indexBlockIdx[hash] = v - } - n.index = nodeIndex{0, v} - } else { - h, ok := b.valueBlockIdx[hash] - if !ok { - bestI, bestSize := 0, blockSize*b.ValueSize - for i, c := range b.Compactions[1:] { - if sz, ok := c.c.Size(n.values); ok && bestSize > sz { - bestI, bestSize = i+1, sz - } - } - c := &b.Compactions[bestI] - c.totalSize += bestSize - v := c.c.Store(n.values) - if c.maxHandle < v { - c.maxHandle = v - } - h = nodeIndex{bestI, int(v)} - b.valueBlockIdx[hash] = h - } - n.index = h - } - return hash -} diff --git a/vendor/golang.org/x/text/internal/ucd/ucd.go b/vendor/golang.org/x/text/internal/ucd/ucd.go deleted file mode 100644 index 309e8d8b16..0000000000 --- a/vendor/golang.org/x/text/internal/ucd/ucd.go +++ /dev/null @@ -1,376 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package ucd provides a parser for Unicode Character Database files, the -// format of which is defined in http://www.unicode.org/reports/tr44/. See -// http://www.unicode.org/Public/UCD/latest/ucd/ for example files. -// -// It currently does not support substitutions of missing fields. -package ucd // import "golang.org/x/text/internal/ucd" - -import ( - "bufio" - "bytes" - "errors" - "io" - "log" - "regexp" - "strconv" - "strings" -) - -// UnicodeData.txt fields. -const ( - CodePoint = iota - Name - GeneralCategory - CanonicalCombiningClass - BidiClass - DecompMapping - DecimalValue - DigitValue - NumericValue - BidiMirrored - Unicode1Name - ISOComment - SimpleUppercaseMapping - SimpleLowercaseMapping - SimpleTitlecaseMapping -) - -// Parse calls f for each entry in the given reader of a UCD file. It will close -// the reader upon return. It will call log.Fatal if any error occurred. -// -// This implements the most common usage pattern of using Parser. -func Parse(r io.ReadCloser, f func(p *Parser)) { - defer r.Close() - - p := New(r) - for p.Next() { - f(p) - } - if err := p.Err(); err != nil { - r.Close() // os.Exit will cause defers not to be called. - log.Fatal(err) - } -} - -// An Option is used to configure a Parser. -type Option func(p *Parser) - -func keepRanges(p *Parser) { - p.keepRanges = true -} - -var ( - // KeepRanges prevents the expansion of ranges. The raw ranges can be - // obtained by calling Range(0) on the parser. - KeepRanges Option = keepRanges -) - -// The Part option register a handler for lines starting with a '@'. The text -// after a '@' is available as the first field. Comments are handled as usual. -func Part(f func(p *Parser)) Option { - return func(p *Parser) { - p.partHandler = f - } -} - -// The CommentHandler option passes comments that are on a line by itself to -// a given handler. -func CommentHandler(f func(s string)) Option { - return func(p *Parser) { - p.commentHandler = f - } -} - -// A Parser parses Unicode Character Database (UCD) files. -type Parser struct { - scanner *bufio.Scanner - - keepRanges bool // Don't expand rune ranges in field 0. - - err error - comment []byte - field [][]byte - // parsedRange is needed in case Range(0) is called more than once for one - // field. In some cases this requires scanning ahead. - parsedRange bool - rangeStart, rangeEnd rune - - partHandler func(p *Parser) - commentHandler func(s string) -} - -func (p *Parser) setError(err error) { - if p.err == nil { - p.err = err - } -} - -func (p *Parser) getField(i int) []byte { - if i >= len(p.field) { - return nil - } - return p.field[i] -} - -// Err returns a non-nil error if any error occurred during parsing. -func (p *Parser) Err() error { - return p.err -} - -// New returns a Parser for the given Reader. -func New(r io.Reader, o ...Option) *Parser { - p := &Parser{ - scanner: bufio.NewScanner(r), - } - for _, f := range o { - f(p) - } - return p -} - -// Next parses the next line in the file. It returns true if a line was parsed -// and false if it reached the end of the file. -func (p *Parser) Next() bool { - if !p.keepRanges && p.rangeStart < p.rangeEnd { - p.rangeStart++ - return true - } - p.comment = nil - p.field = p.field[:0] - p.parsedRange = false - - for p.scanner.Scan() { - b := p.scanner.Bytes() - if len(b) == 0 { - continue - } - if b[0] == '#' { - if p.commentHandler != nil { - p.commentHandler(strings.TrimSpace(string(b[1:]))) - } - continue - } - - // Parse line - if i := bytes.IndexByte(b, '#'); i != -1 { - p.comment = bytes.TrimSpace(b[i+1:]) - b = b[:i] - } - if b[0] == '@' { - if p.partHandler != nil { - p.field = append(p.field, bytes.TrimSpace(b[1:])) - p.partHandler(p) - p.field = p.field[:0] - } - p.comment = nil - continue - } - for { - i := bytes.IndexByte(b, ';') - if i == -1 { - p.field = append(p.field, bytes.TrimSpace(b)) - break - } - p.field = append(p.field, bytes.TrimSpace(b[:i])) - b = b[i+1:] - } - if !p.keepRanges { - p.rangeStart, p.rangeEnd = p.getRange(0) - } - return true - } - p.setError(p.scanner.Err()) - return false -} - -func parseRune(b []byte) (rune, error) { - if len(b) > 2 && b[0] == 'U' && b[1] == '+' { - b = b[2:] - } - x, err := strconv.ParseUint(string(b), 16, 32) - return rune(x), err -} - -func (p *Parser) parseRune(b []byte) rune { - x, err := parseRune(b) - p.setError(err) - return x -} - -// Rune parses and returns field i as a rune. -func (p *Parser) Rune(i int) rune { - if i > 0 || p.keepRanges { - return p.parseRune(p.getField(i)) - } - return p.rangeStart -} - -// Runes interprets and returns field i as a sequence of runes. -func (p *Parser) Runes(i int) (runes []rune) { - add := func(b []byte) { - if b = bytes.TrimSpace(b); len(b) > 0 { - runes = append(runes, p.parseRune(b)) - } - } - for b := p.getField(i); ; { - i := bytes.IndexByte(b, ' ') - if i == -1 { - add(b) - break - } - add(b[:i]) - b = b[i+1:] - } - return -} - -var ( - errIncorrectLegacyRange = errors.New("ucd: unmatched <* First>") - - // reRange matches one line of a legacy rune range. - reRange = regexp.MustCompile("^([0-9A-F]*);<([^,]*), ([^>]*)>(.*)$") -) - -// Range parses and returns field i as a rune range. A range is inclusive at -// both ends. If the field only has one rune, first and last will be identical. -// It supports the legacy format for ranges used in UnicodeData.txt. -func (p *Parser) Range(i int) (first, last rune) { - if !p.keepRanges { - return p.rangeStart, p.rangeStart - } - return p.getRange(i) -} - -func (p *Parser) getRange(i int) (first, last rune) { - b := p.getField(i) - if k := bytes.Index(b, []byte("..")); k != -1 { - return p.parseRune(b[:k]), p.parseRune(b[k+2:]) - } - // The first field may not be a rune, in which case we may ignore any error - // and set the range as 0..0. - x, err := parseRune(b) - if err != nil { - // Disable range parsing henceforth. This ensures that an error will be - // returned if the user subsequently will try to parse this field as - // a Rune. - p.keepRanges = true - } - // Special case for UnicodeData that was retained for backwards compatibility. - if i == 0 && len(p.field) > 1 && bytes.HasSuffix(p.field[1], []byte("First>")) { - if p.parsedRange { - return p.rangeStart, p.rangeEnd - } - mf := reRange.FindStringSubmatch(p.scanner.Text()) - if mf == nil || !p.scanner.Scan() { - p.setError(errIncorrectLegacyRange) - return x, x - } - // Using Bytes would be more efficient here, but Text is a lot easier - // and this is not a frequent case. - ml := reRange.FindStringSubmatch(p.scanner.Text()) - if ml == nil || mf[2] != ml[2] || ml[3] != "Last" || mf[4] != ml[4] { - p.setError(errIncorrectLegacyRange) - return x, x - } - p.rangeStart, p.rangeEnd = x, p.parseRune(p.scanner.Bytes()[:len(ml[1])]) - p.parsedRange = true - return p.rangeStart, p.rangeEnd - } - return x, x -} - -// bools recognizes all valid UCD boolean values. -var bools = map[string]bool{ - "": false, - "N": false, - "No": false, - "F": false, - "False": false, - "Y": true, - "Yes": true, - "T": true, - "True": true, -} - -// Bool parses and returns field i as a boolean value. -func (p *Parser) Bool(i int) bool { - b := p.getField(i) - for s, v := range bools { - if bstrEq(b, s) { - return v - } - } - p.setError(strconv.ErrSyntax) - return false -} - -// Int parses and returns field i as an integer value. -func (p *Parser) Int(i int) int { - x, err := strconv.ParseInt(string(p.getField(i)), 10, 64) - p.setError(err) - return int(x) -} - -// Uint parses and returns field i as an unsigned integer value. -func (p *Parser) Uint(i int) uint { - x, err := strconv.ParseUint(string(p.getField(i)), 10, 64) - p.setError(err) - return uint(x) -} - -// Float parses and returns field i as a decimal value. -func (p *Parser) Float(i int) float64 { - x, err := strconv.ParseFloat(string(p.getField(i)), 64) - p.setError(err) - return x -} - -// String parses and returns field i as a string value. -func (p *Parser) String(i int) string { - return string(p.getField(i)) -} - -// Strings parses and returns field i as a space-separated list of strings. -func (p *Parser) Strings(i int) []string { - ss := strings.Split(string(p.getField(i)), " ") - for i, s := range ss { - ss[i] = strings.TrimSpace(s) - } - return ss -} - -// Comment returns the comments for the current line. -func (p *Parser) Comment() string { - return string(p.comment) -} - -var errUndefinedEnum = errors.New("ucd: undefined enum value") - -// Enum interprets and returns field i as a value that must be one of the values -// in enum. -func (p *Parser) Enum(i int, enum ...string) string { - b := p.getField(i) - for _, s := range enum { - if bstrEq(b, s) { - return s - } - } - p.setError(errUndefinedEnum) - return "" -} - -func bstrEq(b []byte, s string) bool { - if len(b) != len(s) { - return false - } - for i, c := range b { - if c != s[i] { - return false - } - } - return true -} diff --git a/vendor/golang.org/x/text/language/Makefile b/vendor/golang.org/x/text/language/Makefile new file mode 100644 index 0000000000..79f005784f --- /dev/null +++ b/vendor/golang.org/x/text/language/Makefile @@ -0,0 +1,16 @@ +# Copyright 2013 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +CLEANFILES+=maketables + +maketables: maketables.go + go build $^ + +tables: maketables + ./maketables > tables.go + gofmt -w -s tables.go + +# Build (but do not run) maketables during testing, +# just to make sure it still compiles. +testshort: maketables diff --git a/vendor/golang.org/x/text/language/doc.go b/vendor/golang.org/x/text/language/doc.go new file mode 100644 index 0000000000..8afecd50e1 --- /dev/null +++ b/vendor/golang.org/x/text/language/doc.go @@ -0,0 +1,102 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package language implements BCP 47 language tags and related functionality. +// +// The most important function of package language is to match a list of +// user-preferred languages to a list of supported languages. +// It alleviates the developer of dealing with the complexity of this process +// and provides the user with the best experience +// (see https://blog.golang.org/matchlang). +// +// +// Matching preferred against supported languages +// +// A Matcher for an application that supports English, Australian English, +// Danish, and standard Mandarin can be created as follows: +// +// var matcher = language.NewMatcher([]language.Tag{ +// language.English, // The first language is used as fallback. +// language.MustParse("en-AU"), +// language.Danish, +// language.Chinese, +// }) +// +// This list of supported languages is typically implied by the languages for +// which there exists translations of the user interface. +// +// User-preferred languages usually come as a comma-separated list of BCP 47 +// language tags. +// The MatchString finds best matches for such strings: +// +// handler(w http.ResponseWriter, r *http.Request) { +// lang, _ := r.Cookie("lang") +// accept := r.Header.Get("Accept-Language") +// tag, _ := language.MatchStrings(matcher, lang.String(), accept) +// +// // tag should now be used for the initialization of any +// // locale-specific service. +// } +// +// The Matcher's Match method can be used to match Tags directly. +// +// Matchers are aware of the intricacies of equivalence between languages, such +// as deprecated subtags, legacy tags, macro languages, mutual +// intelligibility between scripts and languages, and transparently passing +// BCP 47 user configuration. +// For instance, it will know that a reader of Bokmål Danish can read Norwegian +// and will know that Cantonese ("yue") is a good match for "zh-HK". +// +// +// Using match results +// +// To guarantee a consistent user experience to the user it is important to +// use the same language tag for the selection of any locale-specific services. +// For example, it is utterly confusing to substitute spelled-out numbers +// or dates in one language in text of another language. +// More subtly confusing is using the wrong sorting order or casing +// algorithm for a certain language. +// +// All the packages in x/text that provide locale-specific services +// (e.g. collate, cases) should be initialized with the tag that was +// obtained at the start of an interaction with the user. +// +// Note that Tag that is returned by Match and MatchString may differ from any +// of the supported languages, as it may contain carried over settings from +// the user tags. +// This may be inconvenient when your application has some additional +// locale-specific data for your supported languages. +// Match and MatchString both return the index of the matched supported tag +// to simplify associating such data with the matched tag. +// +// +// Canonicalization +// +// If one uses the Matcher to compare languages one does not need to +// worry about canonicalization. +// +// The meaning of a Tag varies per application. The language package +// therefore delays canonicalization and preserves information as much +// as possible. The Matcher, however, will always take into account that +// two different tags may represent the same language. +// +// By default, only legacy and deprecated tags are converted into their +// canonical equivalent. All other information is preserved. This approach makes +// the confidence scores more accurate and allows matchers to distinguish +// between variants that are otherwise lost. +// +// As a consequence, two tags that should be treated as identical according to +// BCP 47 or CLDR, like "en-Latn" and "en", will be represented differently. The +// Matcher handles such distinctions, though, and is aware of the +// equivalence relations. The CanonType type can be used to alter the +// canonicalization form. +// +// References +// +// BCP 47 - Tags for Identifying Languages http://tools.ietf.org/html/bcp47 +// +package language // import "golang.org/x/text/language" + +// TODO: explanation on how to match languages for your own locale-specific +// service. diff --git a/vendor/golang.org/x/text/language/maketables.go b/vendor/golang.org/x/text/language/gen.go similarity index 97% rename from vendor/golang.org/x/text/language/maketables.go rename to vendor/golang.org/x/text/language/gen.go index 153269bc10..302f1940aa 100644 --- a/vendor/golang.org/x/text/language/maketables.go +++ b/vendor/golang.org/x/text/language/gen.go @@ -698,8 +698,8 @@ func (b *builder) computeRegionGroups() { b.groups[group] = index(len(b.groups)) } } - if len(b.groups) > 32 { - log.Fatalf("only 32 groups supported, found %d", len(b.groups)) + if len(b.groups) > 64 { + log.Fatalf("only 64 groups supported, found %d", len(b.groups)) } b.writeConst("nRegionGroups", len(b.groups)) } @@ -1417,20 +1417,27 @@ func (b *builder) writeMatchData() { } b.writeSlice("regionToGroups", regionToGroups) + // maps language id to in- and out-of-group region. + paradigmLocales := [][3]uint16{} + locales := strings.Split(lm[0].ParadigmLocales[0].Locales, " ") + for i := 0; i < len(locales); i += 2 { + x := [3]uint16{} + for j := 0; j < 2; j++ { + pc := strings.SplitN(locales[i+j], "-", 2) + x[0] = b.langIndex(pc[0]) + if len(pc) == 2 { + x[1+j] = uint16(b.region.index(pc[1])) + } + } + paradigmLocales = append(paradigmLocales, x) + } + b.writeSlice("paradigmLocales", paradigmLocales) + b.writeType(mutualIntelligibility{}) b.writeType(scriptIntelligibility{}) b.writeType(regionIntelligibility{}) - matchLang := []mutualIntelligibility{{ - // TODO: remove once CLDR is fixed. - want: uint16(b.langIndex("sr")), - have: uint16(b.langIndex("hr")), - distance: uint8(5), - }, { - want: uint16(b.langIndex("sr")), - have: uint16(b.langIndex("bs")), - distance: uint8(5), - }} + matchLang := []mutualIntelligibility{} matchScript := []scriptIntelligibility{} matchRegion := []regionIntelligibility{} // Convert the languageMatch entries in lists keyed by desired language. @@ -1490,8 +1497,14 @@ func (b *builder) writeMatchData() { if desired == supported && desired == "*_*_*" { continue } - if desired != supported { // (Weird but correct.) - log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) + if desired != supported { + // This is now supported by CLDR, but only one case, which + // should already be covered by paradigm locales. For instance, + // test case "und, en, en-GU, en-IN, en-GB ; en-ZA ; en-GB" in + // testdata/CLDRLocaleMatcherTest.txt tests this. + if supported != "en_*_GB" { + log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) + } continue } ri := regionIntelligibility{ @@ -1559,7 +1572,7 @@ func (b *builder) writeRegionInclusionData() { } } - regionContainment := make([]uint32, len(b.groups)) + regionContainment := make([]uint64, len(b.groups)) for _, g := range b.groups { l := containment[g] @@ -1577,10 +1590,10 @@ func (b *builder) writeRegionInclusionData() { b.writeSlice("regionContainment", regionContainment) regionInclusion := make([]uint8, len(b.region.s)) - bvs := make(map[uint32]index) + bvs := make(map[uint64]index) // Make the first bitvector positions correspond with the groups. for r, i := range b.groups { - bv := uint32(1 << i) + bv := uint64(1 << i) for _, g := range mm[r] { bv |= 1 << g } @@ -1589,7 +1602,7 @@ func (b *builder) writeRegionInclusionData() { } for r := 1; r < len(b.region.s); r++ { if _, ok := b.groups[r]; !ok { - bv := uint32(0) + bv := uint64(0) for _, g := range mm[r] { bv |= 1 << g } @@ -1604,9 +1617,9 @@ func (b *builder) writeRegionInclusionData() { } } b.writeSlice("regionInclusion", regionInclusion) - regionInclusionBits := make([]uint32, len(bvs)) + regionInclusionBits := make([]uint64, len(bvs)) for k, v := range bvs { - regionInclusionBits[v] = uint32(k) + regionInclusionBits[v] = uint64(k) } // Add bit vectors for increasingly large distances until a fixed point is reached. regionInclusionNext := []uint8{} diff --git a/vendor/golang.org/x/text/language/gen_index.go b/vendor/golang.org/x/text/language/gen_index.go index eef555cd3a..5ca9bccac5 100644 --- a/vendor/golang.org/x/text/language/gen_index.go +++ b/vendor/golang.org/x/text/language/gen_index.go @@ -49,7 +49,7 @@ func main() { defer func() { buf := &bytes.Buffer{} - if _, err = w.WriteGo(buf, "language"); err != nil { + if _, err = w.WriteGo(buf, "language", ""); err != nil { log.Fatalf("Error formatting file index.go: %v", err) } diff --git a/vendor/golang.org/x/text/language/index.go b/vendor/golang.org/x/text/language/index.go index 973db9fd54..5311e5cbe4 100644 --- a/vendor/golang.org/x/text/language/index.go +++ b/vendor/golang.org/x/text/language/index.go @@ -4,766 +4,780 @@ package language // NumCompactTags is the number of common tags. The maximum tag is // NumCompactTags-1. -const NumCompactTags = 754 +const NumCompactTags = 768 var specialTags = []Tag{ // 2 elements - 0: {lang: 0xd7, region: 0x6d, script: 0x0, pVariant: 0x5, pExt: 0xe, str: "ca-ES-valencia"}, - 1: {lang: 0x138, region: 0x134, script: 0x0, pVariant: 0x5, pExt: 0x5, str: "en-US-u-va-posix"}, + 0: {lang: 0xd7, region: 0x6e, script: 0x0, pVariant: 0x5, pExt: 0xe, str: "ca-ES-valencia"}, + 1: {lang: 0x139, region: 0x135, script: 0x0, pVariant: 0x5, pExt: 0x5, str: "en-US-u-va-posix"}, } // Size: 72 bytes var coreTags = map[uint32]uint16{ 0x0: 0, // und 0x01600000: 3, // af - 0x016000d1: 4, // af-NA - 0x01600160: 5, // af-ZA + 0x016000d2: 4, // af-NA + 0x01600161: 5, // af-ZA 0x01c00000: 6, // agq - 0x01c00051: 7, // agq-CM + 0x01c00052: 7, // agq-CM 0x02100000: 8, // ak - 0x0210007f: 9, // ak-GH + 0x02100080: 9, // ak-GH 0x02700000: 10, // am - 0x0270006e: 11, // am-ET + 0x0270006f: 11, // am-ET 0x03a00000: 12, // ar 0x03a00001: 13, // ar-001 - 0x03a00022: 14, // ar-AE - 0x03a00038: 15, // ar-BH - 0x03a00061: 16, // ar-DJ - 0x03a00066: 17, // ar-DZ - 0x03a0006a: 18, // ar-EG - 0x03a0006b: 19, // ar-EH - 0x03a0006c: 20, // ar-ER - 0x03a00096: 21, // ar-IL - 0x03a0009a: 22, // ar-IQ - 0x03a000a0: 23, // ar-JO - 0x03a000a7: 24, // ar-KM - 0x03a000ab: 25, // ar-KW - 0x03a000af: 26, // ar-LB - 0x03a000b8: 27, // ar-LY - 0x03a000b9: 28, // ar-MA - 0x03a000c8: 29, // ar-MR - 0x03a000e0: 30, // ar-OM - 0x03a000ec: 31, // ar-PS - 0x03a000f2: 32, // ar-QA - 0x03a00107: 33, // ar-SA - 0x03a0010a: 34, // ar-SD - 0x03a00114: 35, // ar-SO - 0x03a00116: 36, // ar-SS - 0x03a0011b: 37, // ar-SY - 0x03a0011f: 38, // ar-TD - 0x03a00127: 39, // ar-TN - 0x03a0015d: 40, // ar-YE + 0x03a00023: 14, // ar-AE + 0x03a00039: 15, // ar-BH + 0x03a00062: 16, // ar-DJ + 0x03a00067: 17, // ar-DZ + 0x03a0006b: 18, // ar-EG + 0x03a0006c: 19, // ar-EH + 0x03a0006d: 20, // ar-ER + 0x03a00097: 21, // ar-IL + 0x03a0009b: 22, // ar-IQ + 0x03a000a1: 23, // ar-JO + 0x03a000a8: 24, // ar-KM + 0x03a000ac: 25, // ar-KW + 0x03a000b0: 26, // ar-LB + 0x03a000b9: 27, // ar-LY + 0x03a000ba: 28, // ar-MA + 0x03a000c9: 29, // ar-MR + 0x03a000e1: 30, // ar-OM + 0x03a000ed: 31, // ar-PS + 0x03a000f3: 32, // ar-QA + 0x03a00108: 33, // ar-SA + 0x03a0010b: 34, // ar-SD + 0x03a00115: 35, // ar-SO + 0x03a00117: 36, // ar-SS + 0x03a0011c: 37, // ar-SY + 0x03a00120: 38, // ar-TD + 0x03a00128: 39, // ar-TN + 0x03a0015e: 40, // ar-YE 0x04000000: 41, // ars 0x04300000: 42, // as - 0x04300098: 43, // as-IN + 0x04300099: 43, // as-IN 0x04400000: 44, // asa - 0x0440012e: 45, // asa-TZ + 0x0440012f: 45, // asa-TZ 0x04800000: 46, // ast - 0x0480006d: 47, // ast-ES + 0x0480006e: 47, // ast-ES 0x05800000: 48, // az - 0x0581e000: 49, // az-Cyrl - 0x0581e031: 50, // az-Cyrl-AZ - 0x05852000: 51, // az-Latn - 0x05852031: 52, // az-Latn-AZ + 0x0581f000: 49, // az-Cyrl + 0x0581f032: 50, // az-Cyrl-AZ + 0x05857000: 51, // az-Latn + 0x05857032: 52, // az-Latn-AZ 0x05e00000: 53, // bas - 0x05e00051: 54, // bas-CM + 0x05e00052: 54, // bas-CM 0x07100000: 55, // be - 0x07100046: 56, // be-BY + 0x07100047: 56, // be-BY 0x07500000: 57, // bem - 0x07500161: 58, // bem-ZM + 0x07500162: 58, // bem-ZM 0x07900000: 59, // bez - 0x0790012e: 60, // bez-TZ + 0x0790012f: 60, // bez-TZ 0x07e00000: 61, // bg - 0x07e00037: 62, // bg-BG + 0x07e00038: 62, // bg-BG 0x08200000: 63, // bh 0x0a000000: 64, // bm - 0x0a0000c2: 65, // bm-ML + 0x0a0000c3: 65, // bm-ML 0x0a500000: 66, // bn - 0x0a500034: 67, // bn-BD - 0x0a500098: 68, // bn-IN + 0x0a500035: 67, // bn-BD + 0x0a500099: 68, // bn-IN 0x0a900000: 69, // bo - 0x0a900052: 70, // bo-CN - 0x0a900098: 71, // bo-IN + 0x0a900053: 70, // bo-CN + 0x0a900099: 71, // bo-IN 0x0b200000: 72, // br - 0x0b200077: 73, // br-FR + 0x0b200078: 73, // br-FR 0x0b500000: 74, // brx - 0x0b500098: 75, // brx-IN + 0x0b500099: 75, // brx-IN 0x0b700000: 76, // bs - 0x0b71e000: 77, // bs-Cyrl - 0x0b71e032: 78, // bs-Cyrl-BA - 0x0b752000: 79, // bs-Latn - 0x0b752032: 80, // bs-Latn-BA + 0x0b71f000: 77, // bs-Cyrl + 0x0b71f033: 78, // bs-Cyrl-BA + 0x0b757000: 79, // bs-Latn + 0x0b757033: 80, // bs-Latn-BA 0x0d700000: 81, // ca - 0x0d700021: 82, // ca-AD - 0x0d70006d: 83, // ca-ES - 0x0d700077: 84, // ca-FR - 0x0d70009d: 85, // ca-IT - 0x0dc00000: 86, // ce - 0x0dc00105: 87, // ce-RU - 0x0df00000: 88, // cgg - 0x0df00130: 89, // cgg-UG - 0x0e500000: 90, // chr - 0x0e500134: 91, // chr-US - 0x0e900000: 92, // ckb - 0x0e90009a: 93, // ckb-IQ - 0x0e90009b: 94, // ckb-IR - 0x0f900000: 95, // cs - 0x0f90005d: 96, // cs-CZ - 0x0fd00000: 97, // cu - 0x0fd00105: 98, // cu-RU - 0x0ff00000: 99, // cy - 0x0ff0007a: 100, // cy-GB - 0x10000000: 101, // da - 0x10000062: 102, // da-DK - 0x10000081: 103, // da-GL - 0x10700000: 104, // dav - 0x107000a3: 105, // dav-KE - 0x10c00000: 106, // de - 0x10c0002d: 107, // de-AT - 0x10c00035: 108, // de-BE - 0x10c0004d: 109, // de-CH - 0x10c0005f: 110, // de-DE - 0x10c0009d: 111, // de-IT - 0x10c000b1: 112, // de-LI - 0x10c000b6: 113, // de-LU - 0x11600000: 114, // dje - 0x116000d3: 115, // dje-NE - 0x11e00000: 116, // dsb - 0x11e0005f: 117, // dsb-DE - 0x12300000: 118, // dua - 0x12300051: 119, // dua-CM - 0x12700000: 120, // dv - 0x12a00000: 121, // dyo - 0x12a00113: 122, // dyo-SN - 0x12c00000: 123, // dz - 0x12c00042: 124, // dz-BT - 0x12e00000: 125, // ebu - 0x12e000a3: 126, // ebu-KE - 0x12f00000: 127, // ee - 0x12f0007f: 128, // ee-GH - 0x12f00121: 129, // ee-TG - 0x13500000: 130, // el - 0x1350005c: 131, // el-CY - 0x13500086: 132, // el-GR - 0x13800000: 133, // en - 0x13800001: 134, // en-001 - 0x1380001a: 135, // en-150 - 0x13800024: 136, // en-AG - 0x13800025: 137, // en-AI - 0x1380002c: 138, // en-AS - 0x1380002d: 139, // en-AT - 0x1380002e: 140, // en-AU - 0x13800033: 141, // en-BB - 0x13800035: 142, // en-BE - 0x13800039: 143, // en-BI - 0x1380003c: 144, // en-BM - 0x13800041: 145, // en-BS - 0x13800045: 146, // en-BW - 0x13800047: 147, // en-BZ - 0x13800048: 148, // en-CA - 0x13800049: 149, // en-CC - 0x1380004d: 150, // en-CH - 0x1380004f: 151, // en-CK - 0x13800051: 152, // en-CM - 0x1380005b: 153, // en-CX - 0x1380005c: 154, // en-CY - 0x1380005f: 155, // en-DE - 0x13800060: 156, // en-DG - 0x13800062: 157, // en-DK - 0x13800063: 158, // en-DM - 0x1380006c: 159, // en-ER - 0x13800071: 160, // en-FI - 0x13800072: 161, // en-FJ - 0x13800073: 162, // en-FK - 0x13800074: 163, // en-FM - 0x1380007a: 164, // en-GB - 0x1380007b: 165, // en-GD - 0x1380007e: 166, // en-GG - 0x1380007f: 167, // en-GH - 0x13800080: 168, // en-GI - 0x13800082: 169, // en-GM - 0x13800089: 170, // en-GU - 0x1380008b: 171, // en-GY - 0x1380008c: 172, // en-HK - 0x13800095: 173, // en-IE - 0x13800096: 174, // en-IL - 0x13800097: 175, // en-IM - 0x13800098: 176, // en-IN - 0x13800099: 177, // en-IO - 0x1380009e: 178, // en-JE - 0x1380009f: 179, // en-JM - 0x138000a3: 180, // en-KE - 0x138000a6: 181, // en-KI - 0x138000a8: 182, // en-KN - 0x138000ac: 183, // en-KY - 0x138000b0: 184, // en-LC - 0x138000b3: 185, // en-LR - 0x138000b4: 186, // en-LS - 0x138000be: 187, // en-MG - 0x138000bf: 188, // en-MH - 0x138000c5: 189, // en-MO - 0x138000c6: 190, // en-MP - 0x138000c9: 191, // en-MS - 0x138000ca: 192, // en-MT - 0x138000cb: 193, // en-MU - 0x138000cd: 194, // en-MW - 0x138000cf: 195, // en-MY - 0x138000d1: 196, // en-NA - 0x138000d4: 197, // en-NF - 0x138000d5: 198, // en-NG - 0x138000d8: 199, // en-NL - 0x138000dc: 200, // en-NR - 0x138000de: 201, // en-NU - 0x138000df: 202, // en-NZ - 0x138000e5: 203, // en-PG - 0x138000e6: 204, // en-PH - 0x138000e7: 205, // en-PK - 0x138000ea: 206, // en-PN - 0x138000eb: 207, // en-PR - 0x138000ef: 208, // en-PW - 0x13800106: 209, // en-RW - 0x13800108: 210, // en-SB - 0x13800109: 211, // en-SC - 0x1380010a: 212, // en-SD - 0x1380010b: 213, // en-SE - 0x1380010c: 214, // en-SG - 0x1380010d: 215, // en-SH - 0x1380010e: 216, // en-SI - 0x13800111: 217, // en-SL - 0x13800116: 218, // en-SS - 0x1380011a: 219, // en-SX - 0x1380011c: 220, // en-SZ - 0x1380011e: 221, // en-TC - 0x13800124: 222, // en-TK - 0x13800128: 223, // en-TO - 0x1380012b: 224, // en-TT - 0x1380012c: 225, // en-TV - 0x1380012e: 226, // en-TZ - 0x13800130: 227, // en-UG - 0x13800132: 228, // en-UM - 0x13800134: 229, // en-US - 0x13800138: 230, // en-VC - 0x1380013b: 231, // en-VG - 0x1380013c: 232, // en-VI - 0x1380013e: 233, // en-VU - 0x13800141: 234, // en-WS - 0x13800160: 235, // en-ZA - 0x13800161: 236, // en-ZM - 0x13800163: 237, // en-ZW - 0x13b00000: 238, // eo - 0x13b00001: 239, // eo-001 - 0x13d00000: 240, // es - 0x13d0001e: 241, // es-419 - 0x13d0002b: 242, // es-AR - 0x13d0003e: 243, // es-BO - 0x13d00040: 244, // es-BR - 0x13d00047: 245, // es-BZ - 0x13d00050: 246, // es-CL - 0x13d00053: 247, // es-CO - 0x13d00055: 248, // es-CR - 0x13d00058: 249, // es-CU - 0x13d00064: 250, // es-DO - 0x13d00067: 251, // es-EA - 0x13d00068: 252, // es-EC - 0x13d0006d: 253, // es-ES - 0x13d00085: 254, // es-GQ - 0x13d00088: 255, // es-GT - 0x13d0008e: 256, // es-HN - 0x13d00093: 257, // es-IC - 0x13d000ce: 258, // es-MX - 0x13d000d7: 259, // es-NI - 0x13d000e1: 260, // es-PA - 0x13d000e3: 261, // es-PE - 0x13d000e6: 262, // es-PH - 0x13d000eb: 263, // es-PR - 0x13d000f0: 264, // es-PY - 0x13d00119: 265, // es-SV - 0x13d00134: 266, // es-US - 0x13d00135: 267, // es-UY - 0x13d0013a: 268, // es-VE - 0x13f00000: 269, // et - 0x13f00069: 270, // et-EE - 0x14400000: 271, // eu - 0x1440006d: 272, // eu-ES - 0x14500000: 273, // ewo - 0x14500051: 274, // ewo-CM - 0x14700000: 275, // fa - 0x14700023: 276, // fa-AF - 0x1470009b: 277, // fa-IR - 0x14d00000: 278, // ff - 0x14d00051: 279, // ff-CM - 0x14d00083: 280, // ff-GN - 0x14d000c8: 281, // ff-MR - 0x14d00113: 282, // ff-SN - 0x15000000: 283, // fi - 0x15000071: 284, // fi-FI - 0x15200000: 285, // fil - 0x152000e6: 286, // fil-PH - 0x15700000: 287, // fo - 0x15700062: 288, // fo-DK - 0x15700075: 289, // fo-FO - 0x15d00000: 290, // fr - 0x15d00035: 291, // fr-BE - 0x15d00036: 292, // fr-BF - 0x15d00039: 293, // fr-BI - 0x15d0003a: 294, // fr-BJ - 0x15d0003b: 295, // fr-BL - 0x15d00048: 296, // fr-CA - 0x15d0004a: 297, // fr-CD - 0x15d0004b: 298, // fr-CF - 0x15d0004c: 299, // fr-CG - 0x15d0004d: 300, // fr-CH - 0x15d0004e: 301, // fr-CI - 0x15d00051: 302, // fr-CM - 0x15d00061: 303, // fr-DJ - 0x15d00066: 304, // fr-DZ - 0x15d00077: 305, // fr-FR - 0x15d00079: 306, // fr-GA - 0x15d0007d: 307, // fr-GF - 0x15d00083: 308, // fr-GN - 0x15d00084: 309, // fr-GP - 0x15d00085: 310, // fr-GQ - 0x15d00090: 311, // fr-HT - 0x15d000a7: 312, // fr-KM - 0x15d000b6: 313, // fr-LU - 0x15d000b9: 314, // fr-MA - 0x15d000ba: 315, // fr-MC - 0x15d000bd: 316, // fr-MF - 0x15d000be: 317, // fr-MG - 0x15d000c2: 318, // fr-ML - 0x15d000c7: 319, // fr-MQ - 0x15d000c8: 320, // fr-MR - 0x15d000cb: 321, // fr-MU - 0x15d000d2: 322, // fr-NC - 0x15d000d3: 323, // fr-NE - 0x15d000e4: 324, // fr-PF - 0x15d000e9: 325, // fr-PM - 0x15d00101: 326, // fr-RE - 0x15d00106: 327, // fr-RW - 0x15d00109: 328, // fr-SC - 0x15d00113: 329, // fr-SN - 0x15d0011b: 330, // fr-SY - 0x15d0011f: 331, // fr-TD - 0x15d00121: 332, // fr-TG - 0x15d00127: 333, // fr-TN - 0x15d0013e: 334, // fr-VU - 0x15d0013f: 335, // fr-WF - 0x15d0015e: 336, // fr-YT - 0x16800000: 337, // fur - 0x1680009d: 338, // fur-IT - 0x16c00000: 339, // fy - 0x16c000d8: 340, // fy-NL - 0x16d00000: 341, // ga - 0x16d00095: 342, // ga-IE - 0x17c00000: 343, // gd - 0x17c0007a: 344, // gd-GB - 0x18e00000: 345, // gl - 0x18e0006d: 346, // gl-ES - 0x1a100000: 347, // gsw - 0x1a10004d: 348, // gsw-CH - 0x1a100077: 349, // gsw-FR - 0x1a1000b1: 350, // gsw-LI - 0x1a200000: 351, // gu - 0x1a200098: 352, // gu-IN - 0x1a700000: 353, // guw - 0x1a900000: 354, // guz - 0x1a9000a3: 355, // guz-KE - 0x1aa00000: 356, // gv - 0x1aa00097: 357, // gv-IM - 0x1b200000: 358, // ha - 0x1b20007f: 359, // ha-GH - 0x1b2000d3: 360, // ha-NE - 0x1b2000d5: 361, // ha-NG - 0x1b600000: 362, // haw - 0x1b600134: 363, // haw-US - 0x1ba00000: 364, // he - 0x1ba00096: 365, // he-IL - 0x1bc00000: 366, // hi - 0x1bc00098: 367, // hi-IN - 0x1cf00000: 368, // hr - 0x1cf00032: 369, // hr-BA - 0x1cf0008f: 370, // hr-HR - 0x1d000000: 371, // hsb - 0x1d00005f: 372, // hsb-DE - 0x1d300000: 373, // hu - 0x1d300091: 374, // hu-HU - 0x1d500000: 375, // hy - 0x1d500027: 376, // hy-AM - 0x1df00000: 377, // id - 0x1df00094: 378, // id-ID - 0x1e500000: 379, // ig - 0x1e5000d5: 380, // ig-NG - 0x1e800000: 381, // ii - 0x1e800052: 382, // ii-CN - 0x1f600000: 383, // is - 0x1f60009c: 384, // is-IS - 0x1f700000: 385, // it - 0x1f70004d: 386, // it-CH - 0x1f70009d: 387, // it-IT - 0x1f700112: 388, // it-SM - 0x1f700137: 389, // it-VA - 0x1f800000: 390, // iu - 0x1fe00000: 391, // ja - 0x1fe000a1: 392, // ja-JP - 0x20100000: 393, // jbo - 0x20500000: 394, // jgo - 0x20500051: 395, // jgo-CM - 0x20800000: 396, // jmc - 0x2080012e: 397, // jmc-TZ - 0x20c00000: 398, // jv - 0x20e00000: 399, // ka - 0x20e0007c: 400, // ka-GE - 0x21000000: 401, // kab - 0x21000066: 402, // kab-DZ - 0x21400000: 403, // kaj - 0x21500000: 404, // kam - 0x215000a3: 405, // kam-KE - 0x21d00000: 406, // kcg - 0x22100000: 407, // kde - 0x2210012e: 408, // kde-TZ - 0x22500000: 409, // kea - 0x22500059: 410, // kea-CV - 0x23200000: 411, // khq - 0x232000c2: 412, // khq-ML - 0x23700000: 413, // ki - 0x237000a3: 414, // ki-KE - 0x24000000: 415, // kk - 0x240000ad: 416, // kk-KZ - 0x24200000: 417, // kkj - 0x24200051: 418, // kkj-CM - 0x24300000: 419, // kl - 0x24300081: 420, // kl-GL - 0x24400000: 421, // kln - 0x244000a3: 422, // kln-KE - 0x24800000: 423, // km - 0x248000a5: 424, // km-KH - 0x24f00000: 425, // kn - 0x24f00098: 426, // kn-IN - 0x25200000: 427, // ko - 0x252000a9: 428, // ko-KP - 0x252000aa: 429, // ko-KR - 0x25400000: 430, // kok - 0x25400098: 431, // kok-IN - 0x26800000: 432, // ks - 0x26800098: 433, // ks-IN - 0x26900000: 434, // ksb - 0x2690012e: 435, // ksb-TZ - 0x26b00000: 436, // ksf - 0x26b00051: 437, // ksf-CM - 0x26c00000: 438, // ksh - 0x26c0005f: 439, // ksh-DE - 0x27200000: 440, // ku - 0x27f00000: 441, // kw - 0x27f0007a: 442, // kw-GB - 0x28800000: 443, // ky - 0x288000a4: 444, // ky-KG - 0x28f00000: 445, // lag - 0x28f0012e: 446, // lag-TZ - 0x29300000: 447, // lb - 0x293000b6: 448, // lb-LU - 0x2a100000: 449, // lg - 0x2a100130: 450, // lg-UG - 0x2ad00000: 451, // lkt - 0x2ad00134: 452, // lkt-US - 0x2b300000: 453, // ln - 0x2b300029: 454, // ln-AO - 0x2b30004a: 455, // ln-CD - 0x2b30004b: 456, // ln-CF - 0x2b30004c: 457, // ln-CG - 0x2b600000: 458, // lo - 0x2b6000ae: 459, // lo-LA - 0x2bd00000: 460, // lrc - 0x2bd0009a: 461, // lrc-IQ - 0x2bd0009b: 462, // lrc-IR - 0x2be00000: 463, // lt - 0x2be000b5: 464, // lt-LT - 0x2c000000: 465, // lu - 0x2c00004a: 466, // lu-CD - 0x2c200000: 467, // luo - 0x2c2000a3: 468, // luo-KE - 0x2c300000: 469, // luy - 0x2c3000a3: 470, // luy-KE - 0x2c500000: 471, // lv - 0x2c5000b7: 472, // lv-LV - 0x2cf00000: 473, // mas - 0x2cf000a3: 474, // mas-KE - 0x2cf0012e: 475, // mas-TZ - 0x2e700000: 476, // mer - 0x2e7000a3: 477, // mer-KE - 0x2eb00000: 478, // mfe - 0x2eb000cb: 479, // mfe-MU - 0x2ef00000: 480, // mg - 0x2ef000be: 481, // mg-MG - 0x2f000000: 482, // mgh - 0x2f0000d0: 483, // mgh-MZ - 0x2f200000: 484, // mgo - 0x2f200051: 485, // mgo-CM - 0x2fd00000: 486, // mk - 0x2fd000c1: 487, // mk-MK - 0x30200000: 488, // ml - 0x30200098: 489, // ml-IN - 0x30900000: 490, // mn - 0x309000c4: 491, // mn-MN - 0x31900000: 492, // mr - 0x31900098: 493, // mr-IN - 0x31d00000: 494, // ms - 0x31d0003d: 495, // ms-BN - 0x31d000cf: 496, // ms-MY - 0x31d0010c: 497, // ms-SG - 0x31e00000: 498, // mt - 0x31e000ca: 499, // mt-MT - 0x32300000: 500, // mua - 0x32300051: 501, // mua-CM - 0x32f00000: 502, // my - 0x32f000c3: 503, // my-MM - 0x33800000: 504, // mzn - 0x3380009b: 505, // mzn-IR - 0x33f00000: 506, // nah - 0x34300000: 507, // naq - 0x343000d1: 508, // naq-NA - 0x34500000: 509, // nb - 0x345000d9: 510, // nb-NO - 0x3450010f: 511, // nb-SJ - 0x34c00000: 512, // nd - 0x34c00163: 513, // nd-ZW - 0x34e00000: 514, // nds - 0x34e0005f: 515, // nds-DE - 0x34e000d8: 516, // nds-NL - 0x34f00000: 517, // ne - 0x34f00098: 518, // ne-IN - 0x34f000da: 519, // ne-NP - 0x36500000: 520, // nl - 0x3650002f: 521, // nl-AW - 0x36500035: 522, // nl-BE - 0x3650003f: 523, // nl-BQ - 0x3650005a: 524, // nl-CW - 0x365000d8: 525, // nl-NL - 0x36500115: 526, // nl-SR - 0x3650011a: 527, // nl-SX - 0x36600000: 528, // nmg - 0x36600051: 529, // nmg-CM - 0x36800000: 530, // nn - 0x368000d9: 531, // nn-NO - 0x36a00000: 532, // nnh - 0x36a00051: 533, // nnh-CM - 0x36d00000: 534, // no - 0x37300000: 535, // nqo - 0x37400000: 536, // nr - 0x37800000: 537, // nso - 0x37e00000: 538, // nus - 0x37e00116: 539, // nus-SS - 0x38500000: 540, // ny - 0x38700000: 541, // nyn - 0x38700130: 542, // nyn-UG - 0x38e00000: 543, // om - 0x38e0006e: 544, // om-ET - 0x38e000a3: 545, // om-KE - 0x39300000: 546, // or - 0x39300098: 547, // or-IN - 0x39600000: 548, // os - 0x3960007c: 549, // os-GE - 0x39600105: 550, // os-RU - 0x39b00000: 551, // pa - 0x39b05000: 552, // pa-Arab - 0x39b050e7: 553, // pa-Arab-PK - 0x39b2f000: 554, // pa-Guru - 0x39b2f098: 555, // pa-Guru-IN - 0x39f00000: 556, // pap - 0x3b100000: 557, // pl - 0x3b1000e8: 558, // pl-PL - 0x3bb00000: 559, // prg - 0x3bb00001: 560, // prg-001 - 0x3bc00000: 561, // ps - 0x3bc00023: 562, // ps-AF - 0x3be00000: 563, // pt - 0x3be00029: 564, // pt-AO - 0x3be00040: 565, // pt-BR - 0x3be0004d: 566, // pt-CH - 0x3be00059: 567, // pt-CV - 0x3be00085: 568, // pt-GQ - 0x3be0008a: 569, // pt-GW - 0x3be000b6: 570, // pt-LU - 0x3be000c5: 571, // pt-MO - 0x3be000d0: 572, // pt-MZ - 0x3be000ed: 573, // pt-PT - 0x3be00117: 574, // pt-ST - 0x3be00125: 575, // pt-TL - 0x3c200000: 576, // qu - 0x3c20003e: 577, // qu-BO - 0x3c200068: 578, // qu-EC - 0x3c2000e3: 579, // qu-PE - 0x3d200000: 580, // rm - 0x3d20004d: 581, // rm-CH - 0x3d700000: 582, // rn - 0x3d700039: 583, // rn-BI - 0x3da00000: 584, // ro - 0x3da000bb: 585, // ro-MD - 0x3da00103: 586, // ro-RO - 0x3dc00000: 587, // rof - 0x3dc0012e: 588, // rof-TZ - 0x3e000000: 589, // ru - 0x3e000046: 590, // ru-BY - 0x3e0000a4: 591, // ru-KG - 0x3e0000ad: 592, // ru-KZ - 0x3e0000bb: 593, // ru-MD - 0x3e000105: 594, // ru-RU - 0x3e00012f: 595, // ru-UA - 0x3e300000: 596, // rw - 0x3e300106: 597, // rw-RW - 0x3e400000: 598, // rwk - 0x3e40012e: 599, // rwk-TZ - 0x3e900000: 600, // sah - 0x3e900105: 601, // sah-RU - 0x3ea00000: 602, // saq - 0x3ea000a3: 603, // saq-KE - 0x3f100000: 604, // sbp - 0x3f10012e: 605, // sbp-TZ - 0x3fa00000: 606, // sdh - 0x3fb00000: 607, // se - 0x3fb00071: 608, // se-FI - 0x3fb000d9: 609, // se-NO - 0x3fb0010b: 610, // se-SE - 0x3fd00000: 611, // seh - 0x3fd000d0: 612, // seh-MZ - 0x3ff00000: 613, // ses - 0x3ff000c2: 614, // ses-ML - 0x40000000: 615, // sg - 0x4000004b: 616, // sg-CF - 0x40600000: 617, // shi - 0x40652000: 618, // shi-Latn - 0x406520b9: 619, // shi-Latn-MA - 0x406d2000: 620, // shi-Tfng - 0x406d20b9: 621, // shi-Tfng-MA - 0x40a00000: 622, // si - 0x40a000b2: 623, // si-LK - 0x41000000: 624, // sk - 0x41000110: 625, // sk-SK - 0x41400000: 626, // sl - 0x4140010e: 627, // sl-SI - 0x41a00000: 628, // sma - 0x41b00000: 629, // smi - 0x41c00000: 630, // smj - 0x41d00000: 631, // smn - 0x41d00071: 632, // smn-FI - 0x42000000: 633, // sms - 0x42100000: 634, // sn - 0x42100163: 635, // sn-ZW - 0x42700000: 636, // so - 0x42700061: 637, // so-DJ - 0x4270006e: 638, // so-ET - 0x427000a3: 639, // so-KE - 0x42700114: 640, // so-SO - 0x42f00000: 641, // sq - 0x42f00026: 642, // sq-AL - 0x42f000c1: 643, // sq-MK - 0x42f0014c: 644, // sq-XK - 0x43000000: 645, // sr - 0x4301e000: 646, // sr-Cyrl - 0x4301e032: 647, // sr-Cyrl-BA - 0x4301e0bc: 648, // sr-Cyrl-ME - 0x4301e104: 649, // sr-Cyrl-RS - 0x4301e14c: 650, // sr-Cyrl-XK - 0x43052000: 651, // sr-Latn - 0x43052032: 652, // sr-Latn-BA - 0x430520bc: 653, // sr-Latn-ME - 0x43052104: 654, // sr-Latn-RS - 0x4305214c: 655, // sr-Latn-XK - 0x43500000: 656, // ss - 0x43800000: 657, // ssy - 0x43900000: 658, // st - 0x44200000: 659, // sv - 0x44200030: 660, // sv-AX - 0x44200071: 661, // sv-FI - 0x4420010b: 662, // sv-SE - 0x44300000: 663, // sw - 0x4430004a: 664, // sw-CD - 0x443000a3: 665, // sw-KE - 0x4430012e: 666, // sw-TZ - 0x44300130: 667, // sw-UG - 0x44c00000: 668, // syr - 0x44e00000: 669, // ta - 0x44e00098: 670, // ta-IN - 0x44e000b2: 671, // ta-LK - 0x44e000cf: 672, // ta-MY - 0x44e0010c: 673, // ta-SG - 0x45f00000: 674, // te - 0x45f00098: 675, // te-IN - 0x46200000: 676, // teo - 0x462000a3: 677, // teo-KE - 0x46200130: 678, // teo-UG - 0x46900000: 679, // th - 0x46900122: 680, // th-TH - 0x46d00000: 681, // ti - 0x46d0006c: 682, // ti-ER - 0x46d0006e: 683, // ti-ET - 0x46f00000: 684, // tig - 0x47400000: 685, // tk - 0x47400126: 686, // tk-TM - 0x47e00000: 687, // tn - 0x48000000: 688, // to - 0x48000128: 689, // to-TO - 0x48800000: 690, // tr - 0x4880005c: 691, // tr-CY - 0x4880012a: 692, // tr-TR - 0x48c00000: 693, // ts - 0x4a200000: 694, // twq - 0x4a2000d3: 695, // twq-NE - 0x4a700000: 696, // tzm - 0x4a7000b9: 697, // tzm-MA - 0x4aa00000: 698, // ug - 0x4aa00052: 699, // ug-CN - 0x4ac00000: 700, // uk - 0x4ac0012f: 701, // uk-UA - 0x4b200000: 702, // ur - 0x4b200098: 703, // ur-IN - 0x4b2000e7: 704, // ur-PK - 0x4ba00000: 705, // uz - 0x4ba05000: 706, // uz-Arab - 0x4ba05023: 707, // uz-Arab-AF - 0x4ba1e000: 708, // uz-Cyrl - 0x4ba1e136: 709, // uz-Cyrl-UZ - 0x4ba52000: 710, // uz-Latn - 0x4ba52136: 711, // uz-Latn-UZ - 0x4bc00000: 712, // vai - 0x4bc52000: 713, // vai-Latn - 0x4bc520b3: 714, // vai-Latn-LR - 0x4bcd9000: 715, // vai-Vaii - 0x4bcd90b3: 716, // vai-Vaii-LR - 0x4be00000: 717, // ve - 0x4c100000: 718, // vi - 0x4c10013d: 719, // vi-VN - 0x4c700000: 720, // vo - 0x4c700001: 721, // vo-001 - 0x4ca00000: 722, // vun - 0x4ca0012e: 723, // vun-TZ - 0x4cc00000: 724, // wa - 0x4cd00000: 725, // wae - 0x4cd0004d: 726, // wae-CH - 0x4e300000: 727, // wo - 0x4f000000: 728, // xh - 0x4f900000: 729, // xog - 0x4f900130: 730, // xog-UG - 0x50700000: 731, // yav - 0x50700051: 732, // yav-CM - 0x51000000: 733, // yi - 0x51000001: 734, // yi-001 - 0x51600000: 735, // yo - 0x5160003a: 736, // yo-BJ - 0x516000d5: 737, // yo-NG - 0x51d00000: 738, // yue - 0x51d0008c: 739, // yue-HK - 0x52600000: 740, // zgh - 0x526000b9: 741, // zgh-MA - 0x52700000: 742, // zh - 0x52734000: 743, // zh-Hans - 0x52734052: 744, // zh-Hans-CN - 0x5273408c: 745, // zh-Hans-HK - 0x527340c5: 746, // zh-Hans-MO - 0x5273410c: 747, // zh-Hans-SG - 0x52735000: 748, // zh-Hant - 0x5273508c: 749, // zh-Hant-HK - 0x527350c5: 750, // zh-Hant-MO - 0x5273512d: 751, // zh-Hant-TW - 0x52c00000: 752, // zu - 0x52c00160: 753, // zu-ZA + 0x0d700022: 82, // ca-AD + 0x0d70006e: 83, // ca-ES + 0x0d700078: 84, // ca-FR + 0x0d70009e: 85, // ca-IT + 0x0db00000: 86, // ccp + 0x0db00035: 87, // ccp-BD + 0x0db00099: 88, // ccp-IN + 0x0dc00000: 89, // ce + 0x0dc00106: 90, // ce-RU + 0x0df00000: 91, // cgg + 0x0df00131: 92, // cgg-UG + 0x0e500000: 93, // chr + 0x0e500135: 94, // chr-US + 0x0e900000: 95, // ckb + 0x0e90009b: 96, // ckb-IQ + 0x0e90009c: 97, // ckb-IR + 0x0fa00000: 98, // cs + 0x0fa0005e: 99, // cs-CZ + 0x0fe00000: 100, // cu + 0x0fe00106: 101, // cu-RU + 0x10000000: 102, // cy + 0x1000007b: 103, // cy-GB + 0x10100000: 104, // da + 0x10100063: 105, // da-DK + 0x10100082: 106, // da-GL + 0x10800000: 107, // dav + 0x108000a4: 108, // dav-KE + 0x10d00000: 109, // de + 0x10d0002e: 110, // de-AT + 0x10d00036: 111, // de-BE + 0x10d0004e: 112, // de-CH + 0x10d00060: 113, // de-DE + 0x10d0009e: 114, // de-IT + 0x10d000b2: 115, // de-LI + 0x10d000b7: 116, // de-LU + 0x11700000: 117, // dje + 0x117000d4: 118, // dje-NE + 0x11f00000: 119, // dsb + 0x11f00060: 120, // dsb-DE + 0x12400000: 121, // dua + 0x12400052: 122, // dua-CM + 0x12800000: 123, // dv + 0x12b00000: 124, // dyo + 0x12b00114: 125, // dyo-SN + 0x12d00000: 126, // dz + 0x12d00043: 127, // dz-BT + 0x12f00000: 128, // ebu + 0x12f000a4: 129, // ebu-KE + 0x13000000: 130, // ee + 0x13000080: 131, // ee-GH + 0x13000122: 132, // ee-TG + 0x13600000: 133, // el + 0x1360005d: 134, // el-CY + 0x13600087: 135, // el-GR + 0x13900000: 136, // en + 0x13900001: 137, // en-001 + 0x1390001a: 138, // en-150 + 0x13900025: 139, // en-AG + 0x13900026: 140, // en-AI + 0x1390002d: 141, // en-AS + 0x1390002e: 142, // en-AT + 0x1390002f: 143, // en-AU + 0x13900034: 144, // en-BB + 0x13900036: 145, // en-BE + 0x1390003a: 146, // en-BI + 0x1390003d: 147, // en-BM + 0x13900042: 148, // en-BS + 0x13900046: 149, // en-BW + 0x13900048: 150, // en-BZ + 0x13900049: 151, // en-CA + 0x1390004a: 152, // en-CC + 0x1390004e: 153, // en-CH + 0x13900050: 154, // en-CK + 0x13900052: 155, // en-CM + 0x1390005c: 156, // en-CX + 0x1390005d: 157, // en-CY + 0x13900060: 158, // en-DE + 0x13900061: 159, // en-DG + 0x13900063: 160, // en-DK + 0x13900064: 161, // en-DM + 0x1390006d: 162, // en-ER + 0x13900072: 163, // en-FI + 0x13900073: 164, // en-FJ + 0x13900074: 165, // en-FK + 0x13900075: 166, // en-FM + 0x1390007b: 167, // en-GB + 0x1390007c: 168, // en-GD + 0x1390007f: 169, // en-GG + 0x13900080: 170, // en-GH + 0x13900081: 171, // en-GI + 0x13900083: 172, // en-GM + 0x1390008a: 173, // en-GU + 0x1390008c: 174, // en-GY + 0x1390008d: 175, // en-HK + 0x13900096: 176, // en-IE + 0x13900097: 177, // en-IL + 0x13900098: 178, // en-IM + 0x13900099: 179, // en-IN + 0x1390009a: 180, // en-IO + 0x1390009f: 181, // en-JE + 0x139000a0: 182, // en-JM + 0x139000a4: 183, // en-KE + 0x139000a7: 184, // en-KI + 0x139000a9: 185, // en-KN + 0x139000ad: 186, // en-KY + 0x139000b1: 187, // en-LC + 0x139000b4: 188, // en-LR + 0x139000b5: 189, // en-LS + 0x139000bf: 190, // en-MG + 0x139000c0: 191, // en-MH + 0x139000c6: 192, // en-MO + 0x139000c7: 193, // en-MP + 0x139000ca: 194, // en-MS + 0x139000cb: 195, // en-MT + 0x139000cc: 196, // en-MU + 0x139000ce: 197, // en-MW + 0x139000d0: 198, // en-MY + 0x139000d2: 199, // en-NA + 0x139000d5: 200, // en-NF + 0x139000d6: 201, // en-NG + 0x139000d9: 202, // en-NL + 0x139000dd: 203, // en-NR + 0x139000df: 204, // en-NU + 0x139000e0: 205, // en-NZ + 0x139000e6: 206, // en-PG + 0x139000e7: 207, // en-PH + 0x139000e8: 208, // en-PK + 0x139000eb: 209, // en-PN + 0x139000ec: 210, // en-PR + 0x139000f0: 211, // en-PW + 0x13900107: 212, // en-RW + 0x13900109: 213, // en-SB + 0x1390010a: 214, // en-SC + 0x1390010b: 215, // en-SD + 0x1390010c: 216, // en-SE + 0x1390010d: 217, // en-SG + 0x1390010e: 218, // en-SH + 0x1390010f: 219, // en-SI + 0x13900112: 220, // en-SL + 0x13900117: 221, // en-SS + 0x1390011b: 222, // en-SX + 0x1390011d: 223, // en-SZ + 0x1390011f: 224, // en-TC + 0x13900125: 225, // en-TK + 0x13900129: 226, // en-TO + 0x1390012c: 227, // en-TT + 0x1390012d: 228, // en-TV + 0x1390012f: 229, // en-TZ + 0x13900131: 230, // en-UG + 0x13900133: 231, // en-UM + 0x13900135: 232, // en-US + 0x13900139: 233, // en-VC + 0x1390013c: 234, // en-VG + 0x1390013d: 235, // en-VI + 0x1390013f: 236, // en-VU + 0x13900142: 237, // en-WS + 0x13900161: 238, // en-ZA + 0x13900162: 239, // en-ZM + 0x13900164: 240, // en-ZW + 0x13c00000: 241, // eo + 0x13c00001: 242, // eo-001 + 0x13e00000: 243, // es + 0x13e0001f: 244, // es-419 + 0x13e0002c: 245, // es-AR + 0x13e0003f: 246, // es-BO + 0x13e00041: 247, // es-BR + 0x13e00048: 248, // es-BZ + 0x13e00051: 249, // es-CL + 0x13e00054: 250, // es-CO + 0x13e00056: 251, // es-CR + 0x13e00059: 252, // es-CU + 0x13e00065: 253, // es-DO + 0x13e00068: 254, // es-EA + 0x13e00069: 255, // es-EC + 0x13e0006e: 256, // es-ES + 0x13e00086: 257, // es-GQ + 0x13e00089: 258, // es-GT + 0x13e0008f: 259, // es-HN + 0x13e00094: 260, // es-IC + 0x13e000cf: 261, // es-MX + 0x13e000d8: 262, // es-NI + 0x13e000e2: 263, // es-PA + 0x13e000e4: 264, // es-PE + 0x13e000e7: 265, // es-PH + 0x13e000ec: 266, // es-PR + 0x13e000f1: 267, // es-PY + 0x13e0011a: 268, // es-SV + 0x13e00135: 269, // es-US + 0x13e00136: 270, // es-UY + 0x13e0013b: 271, // es-VE + 0x14000000: 272, // et + 0x1400006a: 273, // et-EE + 0x14500000: 274, // eu + 0x1450006e: 275, // eu-ES + 0x14600000: 276, // ewo + 0x14600052: 277, // ewo-CM + 0x14800000: 278, // fa + 0x14800024: 279, // fa-AF + 0x1480009c: 280, // fa-IR + 0x14e00000: 281, // ff + 0x14e00052: 282, // ff-CM + 0x14e00084: 283, // ff-GN + 0x14e000c9: 284, // ff-MR + 0x14e00114: 285, // ff-SN + 0x15100000: 286, // fi + 0x15100072: 287, // fi-FI + 0x15300000: 288, // fil + 0x153000e7: 289, // fil-PH + 0x15800000: 290, // fo + 0x15800063: 291, // fo-DK + 0x15800076: 292, // fo-FO + 0x15e00000: 293, // fr + 0x15e00036: 294, // fr-BE + 0x15e00037: 295, // fr-BF + 0x15e0003a: 296, // fr-BI + 0x15e0003b: 297, // fr-BJ + 0x15e0003c: 298, // fr-BL + 0x15e00049: 299, // fr-CA + 0x15e0004b: 300, // fr-CD + 0x15e0004c: 301, // fr-CF + 0x15e0004d: 302, // fr-CG + 0x15e0004e: 303, // fr-CH + 0x15e0004f: 304, // fr-CI + 0x15e00052: 305, // fr-CM + 0x15e00062: 306, // fr-DJ + 0x15e00067: 307, // fr-DZ + 0x15e00078: 308, // fr-FR + 0x15e0007a: 309, // fr-GA + 0x15e0007e: 310, // fr-GF + 0x15e00084: 311, // fr-GN + 0x15e00085: 312, // fr-GP + 0x15e00086: 313, // fr-GQ + 0x15e00091: 314, // fr-HT + 0x15e000a8: 315, // fr-KM + 0x15e000b7: 316, // fr-LU + 0x15e000ba: 317, // fr-MA + 0x15e000bb: 318, // fr-MC + 0x15e000be: 319, // fr-MF + 0x15e000bf: 320, // fr-MG + 0x15e000c3: 321, // fr-ML + 0x15e000c8: 322, // fr-MQ + 0x15e000c9: 323, // fr-MR + 0x15e000cc: 324, // fr-MU + 0x15e000d3: 325, // fr-NC + 0x15e000d4: 326, // fr-NE + 0x15e000e5: 327, // fr-PF + 0x15e000ea: 328, // fr-PM + 0x15e00102: 329, // fr-RE + 0x15e00107: 330, // fr-RW + 0x15e0010a: 331, // fr-SC + 0x15e00114: 332, // fr-SN + 0x15e0011c: 333, // fr-SY + 0x15e00120: 334, // fr-TD + 0x15e00122: 335, // fr-TG + 0x15e00128: 336, // fr-TN + 0x15e0013f: 337, // fr-VU + 0x15e00140: 338, // fr-WF + 0x15e0015f: 339, // fr-YT + 0x16900000: 340, // fur + 0x1690009e: 341, // fur-IT + 0x16d00000: 342, // fy + 0x16d000d9: 343, // fy-NL + 0x16e00000: 344, // ga + 0x16e00096: 345, // ga-IE + 0x17e00000: 346, // gd + 0x17e0007b: 347, // gd-GB + 0x19000000: 348, // gl + 0x1900006e: 349, // gl-ES + 0x1a300000: 350, // gsw + 0x1a30004e: 351, // gsw-CH + 0x1a300078: 352, // gsw-FR + 0x1a3000b2: 353, // gsw-LI + 0x1a400000: 354, // gu + 0x1a400099: 355, // gu-IN + 0x1a900000: 356, // guw + 0x1ab00000: 357, // guz + 0x1ab000a4: 358, // guz-KE + 0x1ac00000: 359, // gv + 0x1ac00098: 360, // gv-IM + 0x1b400000: 361, // ha + 0x1b400080: 362, // ha-GH + 0x1b4000d4: 363, // ha-NE + 0x1b4000d6: 364, // ha-NG + 0x1b800000: 365, // haw + 0x1b800135: 366, // haw-US + 0x1bc00000: 367, // he + 0x1bc00097: 368, // he-IL + 0x1be00000: 369, // hi + 0x1be00099: 370, // hi-IN + 0x1d100000: 371, // hr + 0x1d100033: 372, // hr-BA + 0x1d100090: 373, // hr-HR + 0x1d200000: 374, // hsb + 0x1d200060: 375, // hsb-DE + 0x1d500000: 376, // hu + 0x1d500092: 377, // hu-HU + 0x1d700000: 378, // hy + 0x1d700028: 379, // hy-AM + 0x1e100000: 380, // id + 0x1e100095: 381, // id-ID + 0x1e700000: 382, // ig + 0x1e7000d6: 383, // ig-NG + 0x1ea00000: 384, // ii + 0x1ea00053: 385, // ii-CN + 0x1f500000: 386, // io + 0x1f800000: 387, // is + 0x1f80009d: 388, // is-IS + 0x1f900000: 389, // it + 0x1f90004e: 390, // it-CH + 0x1f90009e: 391, // it-IT + 0x1f900113: 392, // it-SM + 0x1f900138: 393, // it-VA + 0x1fa00000: 394, // iu + 0x20000000: 395, // ja + 0x200000a2: 396, // ja-JP + 0x20300000: 397, // jbo + 0x20700000: 398, // jgo + 0x20700052: 399, // jgo-CM + 0x20a00000: 400, // jmc + 0x20a0012f: 401, // jmc-TZ + 0x20e00000: 402, // jv + 0x21000000: 403, // ka + 0x2100007d: 404, // ka-GE + 0x21200000: 405, // kab + 0x21200067: 406, // kab-DZ + 0x21600000: 407, // kaj + 0x21700000: 408, // kam + 0x217000a4: 409, // kam-KE + 0x21f00000: 410, // kcg + 0x22300000: 411, // kde + 0x2230012f: 412, // kde-TZ + 0x22700000: 413, // kea + 0x2270005a: 414, // kea-CV + 0x23400000: 415, // khq + 0x234000c3: 416, // khq-ML + 0x23900000: 417, // ki + 0x239000a4: 418, // ki-KE + 0x24200000: 419, // kk + 0x242000ae: 420, // kk-KZ + 0x24400000: 421, // kkj + 0x24400052: 422, // kkj-CM + 0x24500000: 423, // kl + 0x24500082: 424, // kl-GL + 0x24600000: 425, // kln + 0x246000a4: 426, // kln-KE + 0x24a00000: 427, // km + 0x24a000a6: 428, // km-KH + 0x25100000: 429, // kn + 0x25100099: 430, // kn-IN + 0x25400000: 431, // ko + 0x254000aa: 432, // ko-KP + 0x254000ab: 433, // ko-KR + 0x25600000: 434, // kok + 0x25600099: 435, // kok-IN + 0x26a00000: 436, // ks + 0x26a00099: 437, // ks-IN + 0x26b00000: 438, // ksb + 0x26b0012f: 439, // ksb-TZ + 0x26d00000: 440, // ksf + 0x26d00052: 441, // ksf-CM + 0x26e00000: 442, // ksh + 0x26e00060: 443, // ksh-DE + 0x27400000: 444, // ku + 0x28100000: 445, // kw + 0x2810007b: 446, // kw-GB + 0x28a00000: 447, // ky + 0x28a000a5: 448, // ky-KG + 0x29100000: 449, // lag + 0x2910012f: 450, // lag-TZ + 0x29500000: 451, // lb + 0x295000b7: 452, // lb-LU + 0x2a300000: 453, // lg + 0x2a300131: 454, // lg-UG + 0x2af00000: 455, // lkt + 0x2af00135: 456, // lkt-US + 0x2b500000: 457, // ln + 0x2b50002a: 458, // ln-AO + 0x2b50004b: 459, // ln-CD + 0x2b50004c: 460, // ln-CF + 0x2b50004d: 461, // ln-CG + 0x2b800000: 462, // lo + 0x2b8000af: 463, // lo-LA + 0x2bf00000: 464, // lrc + 0x2bf0009b: 465, // lrc-IQ + 0x2bf0009c: 466, // lrc-IR + 0x2c000000: 467, // lt + 0x2c0000b6: 468, // lt-LT + 0x2c200000: 469, // lu + 0x2c20004b: 470, // lu-CD + 0x2c400000: 471, // luo + 0x2c4000a4: 472, // luo-KE + 0x2c500000: 473, // luy + 0x2c5000a4: 474, // luy-KE + 0x2c700000: 475, // lv + 0x2c7000b8: 476, // lv-LV + 0x2d100000: 477, // mas + 0x2d1000a4: 478, // mas-KE + 0x2d10012f: 479, // mas-TZ + 0x2e900000: 480, // mer + 0x2e9000a4: 481, // mer-KE + 0x2ed00000: 482, // mfe + 0x2ed000cc: 483, // mfe-MU + 0x2f100000: 484, // mg + 0x2f1000bf: 485, // mg-MG + 0x2f200000: 486, // mgh + 0x2f2000d1: 487, // mgh-MZ + 0x2f400000: 488, // mgo + 0x2f400052: 489, // mgo-CM + 0x2ff00000: 490, // mk + 0x2ff000c2: 491, // mk-MK + 0x30400000: 492, // ml + 0x30400099: 493, // ml-IN + 0x30b00000: 494, // mn + 0x30b000c5: 495, // mn-MN + 0x31b00000: 496, // mr + 0x31b00099: 497, // mr-IN + 0x31f00000: 498, // ms + 0x31f0003e: 499, // ms-BN + 0x31f000d0: 500, // ms-MY + 0x31f0010d: 501, // ms-SG + 0x32000000: 502, // mt + 0x320000cb: 503, // mt-MT + 0x32500000: 504, // mua + 0x32500052: 505, // mua-CM + 0x33100000: 506, // my + 0x331000c4: 507, // my-MM + 0x33a00000: 508, // mzn + 0x33a0009c: 509, // mzn-IR + 0x34100000: 510, // nah + 0x34500000: 511, // naq + 0x345000d2: 512, // naq-NA + 0x34700000: 513, // nb + 0x347000da: 514, // nb-NO + 0x34700110: 515, // nb-SJ + 0x34e00000: 516, // nd + 0x34e00164: 517, // nd-ZW + 0x35000000: 518, // nds + 0x35000060: 519, // nds-DE + 0x350000d9: 520, // nds-NL + 0x35100000: 521, // ne + 0x35100099: 522, // ne-IN + 0x351000db: 523, // ne-NP + 0x36700000: 524, // nl + 0x36700030: 525, // nl-AW + 0x36700036: 526, // nl-BE + 0x36700040: 527, // nl-BQ + 0x3670005b: 528, // nl-CW + 0x367000d9: 529, // nl-NL + 0x36700116: 530, // nl-SR + 0x3670011b: 531, // nl-SX + 0x36800000: 532, // nmg + 0x36800052: 533, // nmg-CM + 0x36a00000: 534, // nn + 0x36a000da: 535, // nn-NO + 0x36c00000: 536, // nnh + 0x36c00052: 537, // nnh-CM + 0x36f00000: 538, // no + 0x37500000: 539, // nqo + 0x37600000: 540, // nr + 0x37a00000: 541, // nso + 0x38000000: 542, // nus + 0x38000117: 543, // nus-SS + 0x38700000: 544, // ny + 0x38900000: 545, // nyn + 0x38900131: 546, // nyn-UG + 0x39000000: 547, // om + 0x3900006f: 548, // om-ET + 0x390000a4: 549, // om-KE + 0x39500000: 550, // or + 0x39500099: 551, // or-IN + 0x39800000: 552, // os + 0x3980007d: 553, // os-GE + 0x39800106: 554, // os-RU + 0x39d00000: 555, // pa + 0x39d05000: 556, // pa-Arab + 0x39d050e8: 557, // pa-Arab-PK + 0x39d33000: 558, // pa-Guru + 0x39d33099: 559, // pa-Guru-IN + 0x3a100000: 560, // pap + 0x3b300000: 561, // pl + 0x3b3000e9: 562, // pl-PL + 0x3bd00000: 563, // prg + 0x3bd00001: 564, // prg-001 + 0x3be00000: 565, // ps + 0x3be00024: 566, // ps-AF + 0x3c000000: 567, // pt + 0x3c00002a: 568, // pt-AO + 0x3c000041: 569, // pt-BR + 0x3c00004e: 570, // pt-CH + 0x3c00005a: 571, // pt-CV + 0x3c000086: 572, // pt-GQ + 0x3c00008b: 573, // pt-GW + 0x3c0000b7: 574, // pt-LU + 0x3c0000c6: 575, // pt-MO + 0x3c0000d1: 576, // pt-MZ + 0x3c0000ee: 577, // pt-PT + 0x3c000118: 578, // pt-ST + 0x3c000126: 579, // pt-TL + 0x3c400000: 580, // qu + 0x3c40003f: 581, // qu-BO + 0x3c400069: 582, // qu-EC + 0x3c4000e4: 583, // qu-PE + 0x3d400000: 584, // rm + 0x3d40004e: 585, // rm-CH + 0x3d900000: 586, // rn + 0x3d90003a: 587, // rn-BI + 0x3dc00000: 588, // ro + 0x3dc000bc: 589, // ro-MD + 0x3dc00104: 590, // ro-RO + 0x3de00000: 591, // rof + 0x3de0012f: 592, // rof-TZ + 0x3e200000: 593, // ru + 0x3e200047: 594, // ru-BY + 0x3e2000a5: 595, // ru-KG + 0x3e2000ae: 596, // ru-KZ + 0x3e2000bc: 597, // ru-MD + 0x3e200106: 598, // ru-RU + 0x3e200130: 599, // ru-UA + 0x3e500000: 600, // rw + 0x3e500107: 601, // rw-RW + 0x3e600000: 602, // rwk + 0x3e60012f: 603, // rwk-TZ + 0x3eb00000: 604, // sah + 0x3eb00106: 605, // sah-RU + 0x3ec00000: 606, // saq + 0x3ec000a4: 607, // saq-KE + 0x3f300000: 608, // sbp + 0x3f30012f: 609, // sbp-TZ + 0x3fa00000: 610, // sd + 0x3fa000e8: 611, // sd-PK + 0x3fc00000: 612, // sdh + 0x3fd00000: 613, // se + 0x3fd00072: 614, // se-FI + 0x3fd000da: 615, // se-NO + 0x3fd0010c: 616, // se-SE + 0x3ff00000: 617, // seh + 0x3ff000d1: 618, // seh-MZ + 0x40100000: 619, // ses + 0x401000c3: 620, // ses-ML + 0x40200000: 621, // sg + 0x4020004c: 622, // sg-CF + 0x40800000: 623, // shi + 0x40857000: 624, // shi-Latn + 0x408570ba: 625, // shi-Latn-MA + 0x408dc000: 626, // shi-Tfng + 0x408dc0ba: 627, // shi-Tfng-MA + 0x40c00000: 628, // si + 0x40c000b3: 629, // si-LK + 0x41200000: 630, // sk + 0x41200111: 631, // sk-SK + 0x41600000: 632, // sl + 0x4160010f: 633, // sl-SI + 0x41c00000: 634, // sma + 0x41d00000: 635, // smi + 0x41e00000: 636, // smj + 0x41f00000: 637, // smn + 0x41f00072: 638, // smn-FI + 0x42200000: 639, // sms + 0x42300000: 640, // sn + 0x42300164: 641, // sn-ZW + 0x42900000: 642, // so + 0x42900062: 643, // so-DJ + 0x4290006f: 644, // so-ET + 0x429000a4: 645, // so-KE + 0x42900115: 646, // so-SO + 0x43100000: 647, // sq + 0x43100027: 648, // sq-AL + 0x431000c2: 649, // sq-MK + 0x4310014d: 650, // sq-XK + 0x43200000: 651, // sr + 0x4321f000: 652, // sr-Cyrl + 0x4321f033: 653, // sr-Cyrl-BA + 0x4321f0bd: 654, // sr-Cyrl-ME + 0x4321f105: 655, // sr-Cyrl-RS + 0x4321f14d: 656, // sr-Cyrl-XK + 0x43257000: 657, // sr-Latn + 0x43257033: 658, // sr-Latn-BA + 0x432570bd: 659, // sr-Latn-ME + 0x43257105: 660, // sr-Latn-RS + 0x4325714d: 661, // sr-Latn-XK + 0x43700000: 662, // ss + 0x43a00000: 663, // ssy + 0x43b00000: 664, // st + 0x44400000: 665, // sv + 0x44400031: 666, // sv-AX + 0x44400072: 667, // sv-FI + 0x4440010c: 668, // sv-SE + 0x44500000: 669, // sw + 0x4450004b: 670, // sw-CD + 0x445000a4: 671, // sw-KE + 0x4450012f: 672, // sw-TZ + 0x44500131: 673, // sw-UG + 0x44e00000: 674, // syr + 0x45000000: 675, // ta + 0x45000099: 676, // ta-IN + 0x450000b3: 677, // ta-LK + 0x450000d0: 678, // ta-MY + 0x4500010d: 679, // ta-SG + 0x46100000: 680, // te + 0x46100099: 681, // te-IN + 0x46400000: 682, // teo + 0x464000a4: 683, // teo-KE + 0x46400131: 684, // teo-UG + 0x46700000: 685, // tg + 0x46700124: 686, // tg-TJ + 0x46b00000: 687, // th + 0x46b00123: 688, // th-TH + 0x46f00000: 689, // ti + 0x46f0006d: 690, // ti-ER + 0x46f0006f: 691, // ti-ET + 0x47100000: 692, // tig + 0x47600000: 693, // tk + 0x47600127: 694, // tk-TM + 0x48000000: 695, // tn + 0x48200000: 696, // to + 0x48200129: 697, // to-TO + 0x48a00000: 698, // tr + 0x48a0005d: 699, // tr-CY + 0x48a0012b: 700, // tr-TR + 0x48e00000: 701, // ts + 0x49400000: 702, // tt + 0x49400106: 703, // tt-RU + 0x4a400000: 704, // twq + 0x4a4000d4: 705, // twq-NE + 0x4a900000: 706, // tzm + 0x4a9000ba: 707, // tzm-MA + 0x4ac00000: 708, // ug + 0x4ac00053: 709, // ug-CN + 0x4ae00000: 710, // uk + 0x4ae00130: 711, // uk-UA + 0x4b400000: 712, // ur + 0x4b400099: 713, // ur-IN + 0x4b4000e8: 714, // ur-PK + 0x4bc00000: 715, // uz + 0x4bc05000: 716, // uz-Arab + 0x4bc05024: 717, // uz-Arab-AF + 0x4bc1f000: 718, // uz-Cyrl + 0x4bc1f137: 719, // uz-Cyrl-UZ + 0x4bc57000: 720, // uz-Latn + 0x4bc57137: 721, // uz-Latn-UZ + 0x4be00000: 722, // vai + 0x4be57000: 723, // vai-Latn + 0x4be570b4: 724, // vai-Latn-LR + 0x4bee3000: 725, // vai-Vaii + 0x4bee30b4: 726, // vai-Vaii-LR + 0x4c000000: 727, // ve + 0x4c300000: 728, // vi + 0x4c30013e: 729, // vi-VN + 0x4c900000: 730, // vo + 0x4c900001: 731, // vo-001 + 0x4cc00000: 732, // vun + 0x4cc0012f: 733, // vun-TZ + 0x4ce00000: 734, // wa + 0x4cf00000: 735, // wae + 0x4cf0004e: 736, // wae-CH + 0x4e500000: 737, // wo + 0x4e500114: 738, // wo-SN + 0x4f200000: 739, // xh + 0x4fb00000: 740, // xog + 0x4fb00131: 741, // xog-UG + 0x50900000: 742, // yav + 0x50900052: 743, // yav-CM + 0x51200000: 744, // yi + 0x51200001: 745, // yi-001 + 0x51800000: 746, // yo + 0x5180003b: 747, // yo-BJ + 0x518000d6: 748, // yo-NG + 0x51f00000: 749, // yue + 0x51f38000: 750, // yue-Hans + 0x51f38053: 751, // yue-Hans-CN + 0x51f39000: 752, // yue-Hant + 0x51f3908d: 753, // yue-Hant-HK + 0x52800000: 754, // zgh + 0x528000ba: 755, // zgh-MA + 0x52900000: 756, // zh + 0x52938000: 757, // zh-Hans + 0x52938053: 758, // zh-Hans-CN + 0x5293808d: 759, // zh-Hans-HK + 0x529380c6: 760, // zh-Hans-MO + 0x5293810d: 761, // zh-Hans-SG + 0x52939000: 762, // zh-Hant + 0x5293908d: 763, // zh-Hant-HK + 0x529390c6: 764, // zh-Hant-MO + 0x5293912e: 765, // zh-Hant-TW + 0x52f00000: 766, // zu + 0x52f00161: 767, // zu-ZA } -// Total table size 4592 bytes (4KiB); checksum: C25F8AFF +// Total table size 4676 bytes (4KiB); checksum: 17BE3673 diff --git a/vendor/golang.org/x/text/language/language.go b/vendor/golang.org/x/text/language/language.go index 5eecceb619..b65e213ff8 100644 --- a/vendor/golang.org/x/text/language/language.go +++ b/vendor/golang.org/x/text/language/language.go @@ -2,105 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:generate go run maketables.go gen_common.go -output tables.go +//go:generate go run gen.go gen_common.go -output tables.go //go:generate go run gen_index.go -// Package language implements BCP 47 language tags and related functionality. -// -// The Tag type, which is used to represent languages, is agnostic to the -// meaning of its subtags. Tags are not fully canonicalized to preserve -// information that may be valuable in certain contexts. As a consequence, two -// different tags may represent identical languages. -// -// Initializing language- or locale-specific components usually consists of -// two steps. The first step is to select a display language based on the -// preferred languages of the user and the languages supported by an application. -// The second step is to create the language-specific services based on -// this selection. Each is discussed in more details below. -// -// Matching preferred against supported languages -// -// An application may support various languages. This list is typically limited -// by the languages for which there exists translations of the user interface. -// Similarly, a user may provide a list of preferred languages which is limited -// by the languages understood by this user. -// An application should use a Matcher to find the best supported language based -// on the user's preferred list. -// Matchers are aware of the intricacies of equivalence between languages. -// The default Matcher implementation takes into account things such as -// deprecated subtags, legacy tags, and mutual intelligibility between scripts -// and languages. -// -// A Matcher for English, Australian English, Danish, and standard Mandarin can -// be defined as follows: -// -// var matcher = language.NewMatcher([]language.Tag{ -// language.English, // The first language is used as fallback. -// language.MustParse("en-AU"), -// language.Danish, -// language.Chinese, -// }) -// -// The following code selects the best match for someone speaking Spanish and -// Norwegian: -// -// preferred := []language.Tag{ language.Spanish, language.Norwegian } -// tag, _, _ := matcher.Match(preferred...) -// -// In this case, the best match is Danish, as Danish is sufficiently a match to -// Norwegian to not have to fall back to the default. -// See ParseAcceptLanguage on how to handle the Accept-Language HTTP header. -// -// Selecting language-specific services -// -// One should always use the Tag returned by the Matcher to create an instance -// of any of the language-specific services provided by the text repository. -// This prevents the mixing of languages, such as having a different language for -// messages and display names, as well as improper casing or sorting order for -// the selected language. -// Using the returned Tag also allows user-defined settings, such as collation -// order or numbering system to be transparently passed as options. -// -// If you have language-specific data in your application, however, it will in -// most cases suffice to use the index returned by the matcher to identify -// the user language. -// The following loop provides an alternative in case this is not sufficient: -// -// supported := map[language.Tag]data{ -// language.English: enData, -// language.MustParse("en-AU"): enAUData, -// language.Danish: daData, -// language.Chinese: zhData, -// } -// tag, _, _ := matcher.Match(preferred...) -// for ; tag != language.Und; tag = tag.Parent() { -// if v, ok := supported[tag]; ok { -// return v -// } -// } -// return enData // should not reach here -// -// Repeatedly taking the Parent of the tag returned by Match will eventually -// match one of the tags used to initialize the Matcher. -// -// Canonicalization -// -// By default, only legacy and deprecated tags are converted into their -// canonical equivalent. All other information is preserved. This approach makes -// the confidence scores more accurate and allows matchers to distinguish -// between variants that are otherwise lost. -// -// As a consequence, two tags that should be treated as identical according to -// BCP 47 or CLDR, like "en-Latn" and "en", will be represented differently. The -// Matchers will handle such distinctions, though, and are aware of the -// equivalence relations. The CanonType type can be used to alter the -// canonicalization form. -// -// References -// -// BCP 47 - Tags for Identifying Languages -// http://tools.ietf.org/html/bcp47 -package language // import "golang.org/x/text/language" +package language // TODO: Remove above NOTE after: // - verifying that tables are dropped correctly (most notably matcher tables). @@ -129,8 +34,15 @@ const ( // specific language or locale. All language tag values are guaranteed to be // well-formed. type Tag struct { - lang langID - region regionID + lang langID + region regionID + // TODO: we will soon run out of positions for script. Idea: instead of + // storing lang, region, and script codes, store only the compact index and + // have a lookup table from this code to its expansion. This greatly speeds + // up table lookup, speed up common variant cases. + // This will also immediately free up 3 extra bytes. Also, the pVariant + // field can now be moved to the lookup table, as the compact index uniquely + // determines the offset of a possible variant. script scriptID pVariant byte // offset in str, includes preceding '-' pExt uint16 // offset of first extension, includes preceding '-' @@ -387,6 +299,26 @@ func (t Tag) String() string { return string(buf[:t.genCoreBytes(buf[:])]) } +// MarshalText implements encoding.TextMarshaler. +func (t Tag) MarshalText() (text []byte, err error) { + if t.str != "" { + text = append(text, t.str...) + } else if t.script == 0 && t.region == 0 { + text = append(text, t.lang.String()...) + } else { + buf := [maxCoreSize]byte{} + text = buf[:t.genCoreBytes(buf[:])] + } + return text, nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (t *Tag) UnmarshalText(text []byte) error { + tag, err := Raw.Parse(string(text)) + *t = tag + return err +} + // Base returns the base language of the language tag. If the base language is // unspecified, an attempt will be made to infer it from the context. // It uses a variant of CLDR's Add Likely Subtags algorithm. This is subject to change. diff --git a/vendor/golang.org/x/text/language/match.go b/vendor/golang.org/x/text/language/match.go index bb4fff24dd..15b74d125c 100644 --- a/vendor/golang.org/x/text/language/match.go +++ b/vendor/golang.org/x/text/language/match.go @@ -6,6 +6,39 @@ package language import "errors" +// A MatchOption configures a Matcher. +type MatchOption func(*matcher) + +// PreferSameScript will, in the absence of a match, result in the first +// preferred tag with the same script as a supported tag to match this supported +// tag. The default is currently true, but this may change in the future. +func PreferSameScript(preferSame bool) MatchOption { + return func(m *matcher) { m.preferSameScript = preferSame } +} + +// TODO(v1.0.0): consider making Matcher a concrete type, instead of interface. +// There doesn't seem to be too much need for multiple types. +// Making it a concrete type allows MatchStrings to be a method, which will +// improve its discoverability. + +// MatchStrings parses and matches the given strings until one of them matches +// the language in the Matcher. A string may be an Accept-Language header as +// handled by ParseAcceptLanguage. The default language is returned if no +// other language matched. +func MatchStrings(m Matcher, lang ...string) (tag Tag, index int) { + for _, accept := range lang { + desired, _, err := ParseAcceptLanguage(accept) + if err != nil { + continue + } + if tag, index, conf := m.Match(desired...); conf != No { + return tag, index + } + } + tag, index, _ = m.Match() + return +} + // Matcher is the interface that wraps the Match method. // // Match returns the best match for any of the given tags, along with @@ -36,25 +69,45 @@ func Comprehends(speaker, alternative Tag) Confidence { // matched tag in t, but is augmented with the Unicode extension ('u')of the // corresponding preferred tag. This allows user locale options to be passed // transparently. -func NewMatcher(t []Tag) Matcher { - return newMatcher(t) +func NewMatcher(t []Tag, options ...MatchOption) Matcher { + return newMatcher(t, options) } func (m *matcher) Match(want ...Tag) (t Tag, index int, c Confidence) { match, w, c := m.getBest(want...) - if match == nil { - t = m.default_.tag - } else { + if match != nil { t, index = match.tag, match.index + } else { + // TODO: this should be an option + t = m.default_.tag + if m.preferSameScript { + outer: + for _, w := range want { + script, _ := w.Script() + if script.scriptID == 0 { + // Don't do anything if there is no script, such as with + // private subtags. + continue + } + for i, h := range m.supported { + if script.scriptID == h.maxScript { + t, index = h.tag, i + break outer + } + } + } + } + // TODO: select first language tag based on script. + } + if w.region != 0 && t.region != 0 && t.region.contains(w.region) { + t, _ = Raw.Compose(t, Region{w.region}) } // Copy options from the user-provided tag into the result tag. This is hard // to do after the fact, so we do it here. - // TODO: consider also adding in variants that are compatible with the - // matched language. - // TODO: Add back region if it is non-ambiguous? Or create another tag to - // preserve the region? - if u, ok := w.Extension('u'); ok { - t, _ = Raw.Compose(t, u) + // TODO: add in alternative variants to -u-va-. + // TODO: add preferred region to -u-rg-. + if e := w.Extensions(); len(e) > 0 { + t, _ = Raw.Compose(t, e) } return t, index, c } @@ -91,7 +144,7 @@ var ErrMissingLikelyTagsData = errors.New("missing likely tags data") // addLikelySubtags sets subtags to their most likely value, given the locale. // In most cases this means setting fields for unknown values, but in some -// cases it may alter a value. It returns a ErrMissingLikelyTagsData error +// cases it may alter a value. It returns an ErrMissingLikelyTagsData error // if the given locale cannot be expanded. func (t Tag) addLikelySubtags() (Tag, error) { id, err := addTags(t) @@ -300,8 +353,9 @@ func minimizeTags(t Tag) (Tag, error) { // 1) compute the match between the two tags. // 2) if the match is better than the previous best match, replace it // with the new match. (see next section) -// b) if the current best match is above a certain threshold, return this -// match without proceeding to the next tag in "desired". [See Note 1] +// b) if the current best match is Exact and pin is true the result will be +// frozen to the language found thusfar, although better matches may +// still be found for the same language. // 3) If the best match so far is below a certain threshold, return "default". // // Ranking: @@ -350,9 +404,6 @@ func minimizeTags(t Tag) (Tag, error) { // found wins. // // Notes: -// [1] Note that even if we may not have a perfect match, if a match is above a -// certain threshold, it is considered a better match than any other match -// to a tag later in the list of preferred language tags. // [2] In practice, as matching of Exact is done in a separate phase from // matching the other levels, we reuse the Exact level to mean MaxExact in // the second phase. As a consequence, we only need the levels defined by @@ -388,16 +439,18 @@ func minimizeTags(t Tag) (Tag, error) { // matcher keeps a set of supported language tags, indexed by language. type matcher struct { - default_ *haveTag - index map[langID]*matchHeader - passSettings bool + default_ *haveTag + supported []*haveTag + index map[langID]*matchHeader + passSettings bool + preferSameScript bool } // matchHeader has the lists of tags for exact matches and matches based on // maximized and canonicalized tags for a given language. type matchHeader struct { - exact []*haveTag - max []*haveTag + haveTags []*haveTag + original bool } // haveTag holds a supported Tag and its maximized script and region. The maximized @@ -427,7 +480,7 @@ type haveTag struct { func makeHaveTag(tag Tag, index int) (haveTag, langID) { max := tag - if tag.lang != 0 { + if tag.lang != 0 || tag.region != 0 || tag.script != 0 { max, _ = max.canonicalize(All) max, _ = addTags(max) max.remakeString() @@ -452,29 +505,27 @@ func altScript(l langID, s scriptID) scriptID { // addIfNew adds a haveTag to the list of tags only if it is a unique tag. // Tags that have the same maximized values are linked by index. func (h *matchHeader) addIfNew(n haveTag, exact bool) { + h.original = h.original || exact // Don't add new exact matches. - for _, v := range h.exact { + for _, v := range h.haveTags { if v.tag.equalsRest(n.tag) { return } } - if exact { - h.exact = append(h.exact, &n) - } // Allow duplicate maximized tags, but create a linked list to allow quickly // comparing the equivalents and bail out. - for i, v := range h.max { + for i, v := range h.haveTags { if v.maxScript == n.maxScript && v.maxRegion == n.maxRegion && v.tag.variantOrPrivateTagStr() == n.tag.variantOrPrivateTagStr() { - for h.max[i].nextMax != 0 { - i = int(h.max[i].nextMax) + for h.haveTags[i].nextMax != 0 { + i = int(h.haveTags[i].nextMax) } - h.max[i].nextMax = uint16(len(h.max)) + h.haveTags[i].nextMax = uint16(len(h.haveTags)) break } } - h.max = append(h.max, &n) + h.haveTags = append(h.haveTags, &n) } // header returns the matchHeader for the given language. It creates one if @@ -501,9 +552,13 @@ func toConf(d uint8) Confidence { // newMatcher builds an index for the given supported tags and returns it as // a matcher. It also expands the index by considering various equivalence classes // for a given tag. -func newMatcher(supported []Tag) *matcher { +func newMatcher(supported []Tag, options []MatchOption) *matcher { m := &matcher{ - index: make(map[langID]*matchHeader), + index: make(map[langID]*matchHeader), + preferSameScript: true, + } + for _, o := range options { + o(m) } if len(supported) == 0 { m.default_ = &haveTag{} @@ -514,25 +569,28 @@ func newMatcher(supported []Tag) *matcher { for i, tag := range supported { pair, _ := makeHaveTag(tag, i) m.header(tag.lang).addIfNew(pair, true) + m.supported = append(m.supported, &pair) } - m.default_ = m.header(supported[0].lang).exact[0] + m.default_ = m.header(supported[0].lang).haveTags[0] + // Keep these in two different loops to support the case that two equivalent + // languages are distinguished, such as iw and he. for i, tag := range supported { pair, max := makeHaveTag(tag, i) if max != tag.lang { - m.header(max).addIfNew(pair, false) + m.header(max).addIfNew(pair, true) } } // update is used to add indexes in the map for equivalent languages. - // If force is true, the update will also apply to derived entries. To - // avoid applying a "transitive closure", use false. - update := func(want, have uint16, conf Confidence, force bool) { + // update will only add entries to original indexes, thus not computing any + // transitive relations. + update := func(want, have uint16, conf Confidence) { if hh := m.index[langID(have)]; hh != nil { - if !force && len(hh.exact) == 0 { + if !hh.original { return } hw := m.header(langID(want)) - for _, ht := range hh.max { + for _, ht := range hh.haveTags { v := *ht if conf < v.conf { v.conf = conf @@ -541,7 +599,7 @@ func newMatcher(supported []Tag) *matcher { if v.altScript != 0 { v.altScript = altScript(langID(want), v.maxScript) } - hw.addIfNew(v, conf == Exact && len(hh.exact) > 0) + hw.addIfNew(v, conf == Exact && hh.original) } } } @@ -549,9 +607,9 @@ func newMatcher(supported []Tag) *matcher { // Add entries for languages with mutual intelligibility as defined by CLDR's // languageMatch data. for _, ml := range matchLang { - update(ml.want, ml.have, toConf(ml.distance), false) + update(ml.want, ml.have, toConf(ml.distance)) if !ml.oneway { - update(ml.have, ml.want, toConf(ml.distance), false) + update(ml.have, ml.want, toConf(ml.distance)) } } @@ -561,10 +619,6 @@ func newMatcher(supported []Tag) *matcher { // (their canonicalization simply substitutes a different language code, but // nothing else), the match confidence is Exact, otherwise it is High. for i, lm := range langAliasMap { - if lm.from == _sh { - continue - } - // If deprecated codes match and there is no fiddling with the script or // or region, we consider it an exact match. conf := Exact @@ -572,9 +626,9 @@ func newMatcher(supported []Tag) *matcher { if !isExactEquivalent(langID(lm.from)) { conf = High } - update(lm.to, lm.from, conf, true) + update(lm.to, lm.from, conf) } - update(lm.from, lm.to, conf, true) + update(lm.from, lm.to, conf) } return m } @@ -583,28 +637,29 @@ func newMatcher(supported []Tag) *matcher { // account the order of preference of the given tags. func (m *matcher) getBest(want ...Tag) (got *haveTag, orig Tag, c Confidence) { best := bestMatch{} - for _, w := range want { + for i, w := range want { var max Tag // Check for exact match first. h := m.index[w.lang] if w.lang != 0 { - // Base language is defined. if h == nil { continue } - for i := range h.exact { - have := h.exact[i] - if have.tag.equalsRest(w) { - return have, w, Exact - } + // Base language is defined. + max, _ = w.canonicalize(Legacy | Deprecated | Macro) + // A region that is added through canonicalization is stronger than + // a maximized region: set it in the original (e.g. mo -> ro-MD). + if w.region != max.region { + w.region = max.region } - max, _ = w.canonicalize(Legacy | Deprecated) + // TODO: should we do the same for scripts? + // See test case: en, sr, nl ; sh ; sr max, _ = addTags(max) } else { // Base language is not defined. if h != nil { - for i := range h.exact { - have := h.exact[i] + for i := range h.haveTags { + have := h.haveTags[i] if have.tag.equalsRest(w) { return have, w, Exact } @@ -620,16 +675,23 @@ func (m *matcher) getBest(want ...Tag) (got *haveTag, orig Tag, c Confidence) { continue } } + pin := true + for _, t := range want[i+1:] { + if w.lang == t.lang { + pin = false + break + } + } // Check for match based on maximized tag. - for i := range h.max { - have := h.max[i] - best.update(have, w, max.script, max.region) + for i := range h.haveTags { + have := h.haveTags[i] + best.update(have, w, max.script, max.region, pin) if best.conf == Exact { for have.nextMax != 0 { - have = h.max[have.nextMax] - best.update(have, w, max.script, max.region) + have = h.haveTags[have.nextMax] + best.update(have, w, max.script, max.region, pin) } - return best.have, best.want, High + return best.have, best.want, best.conf } } } @@ -644,42 +706,68 @@ func (m *matcher) getBest(want ...Tag) (got *haveTag, orig Tag, c Confidence) { // bestMatch accumulates the best match so far. type bestMatch struct { - have *haveTag - want Tag - conf Confidence + have *haveTag + want Tag + conf Confidence + pinnedRegion regionID + pinLanguage bool + sameRegionGroup bool // Cached results from applying tie-breaking rules. - origLang bool - origReg bool - regDist uint8 - origScript bool - parentDist uint8 // 255 if have is not an ancestor of want tag. + origLang bool + origReg bool + paradigmReg bool + regGroupDist uint8 + origScript bool } // update updates the existing best match if the new pair is considered to be a -// better match. -// To determine if the given pair is a better match, it first computes the rough -// confidence level. If this surpasses the current match, it will replace it and -// update the tie-breaker rule cache. If there is a tie, it proceeds with applying -// a series of tie-breaker rules. If there is no conclusive winner after applying -// the tie-breaker rules, it leaves the current match as the preferred match. -func (m *bestMatch) update(have *haveTag, tag Tag, maxScript scriptID, maxRegion regionID) { +// better match. To determine if the given pair is a better match, it first +// computes the rough confidence level. If this surpasses the current match, it +// will replace it and update the tie-breaker rule cache. If there is a tie, it +// proceeds with applying a series of tie-breaker rules. If there is no +// conclusive winner after applying the tie-breaker rules, it leaves the current +// match as the preferred match. +// +// If pin is true and have and tag are a strong match, it will henceforth only +// consider matches for this language. This corresponds to the nothing that most +// users have a strong preference for the first defined language. A user can +// still prefer a second language over a dialect of the preferred language by +// explicitly specifying dialects, e.g. "en, nl, en-GB". In this case pin should +// be false. +func (m *bestMatch) update(have *haveTag, tag Tag, maxScript scriptID, maxRegion regionID, pin bool) { // Bail if the maximum attainable confidence is below that of the current best match. c := have.conf if c < m.conf { return } - if have.maxScript != maxScript { + // Don't change the language once we already have found an exact match. + if m.pinLanguage && tag.lang != m.want.lang { + return + } + // Pin the region group if we are comparing tags for the same language. + if tag.lang == m.want.lang && m.sameRegionGroup { + _, sameGroup := regionGroupDist(m.pinnedRegion, have.maxRegion, have.maxScript, m.want.lang) + if !sameGroup { + return + } + } + if c == Exact && have.maxScript == maxScript { + // If there is another language and then another entry of this language, + // don't pin anything, otherwise pin the language. + m.pinLanguage = pin + } + if have.tag.equalsRest(tag) { + } else if have.maxScript != maxScript { // There is usually very little comprehension between different scripts. - // In a few cases there may still be Low comprehension. This possibility is - // pre-computed and stored in have.altScript. + // In a few cases there may still be Low comprehension. This possibility + // is pre-computed and stored in have.altScript. if Low < m.conf || have.altScript != maxScript { return } c = Low } else if have.maxRegion != maxRegion { - // There is usually a small difference between languages across regions. - // We use the region distance (below) to disambiguate between equal matches. if High < c { + // There is usually a small difference between languages across regions. c = High } } @@ -715,10 +803,17 @@ func (m *bestMatch) update(have *haveTag, tag Tag, maxScript scriptID, maxRegion beaten = true } - // Next we prefer smaller distances between regions, as defined by regionDist. - regDist := regionDist(have.maxRegion, maxRegion, tag.lang) - if !beaten && m.regDist != regDist { - if regDist > m.regDist { + regGroupDist, sameGroup := regionGroupDist(have.maxRegion, maxRegion, maxScript, tag.lang) + if !beaten && m.regGroupDist != regGroupDist { + if regGroupDist > m.regGroupDist { + return + } + beaten = true + } + + paradigmReg := isParadigmLocale(tag.lang, have.maxRegion) + if !beaten && m.paradigmReg != paradigmReg { + if !paradigmReg { return } beaten = true @@ -733,77 +828,52 @@ func (m *bestMatch) update(have *haveTag, tag Tag, maxScript scriptID, maxRegion beaten = true } - // Finally we prefer tags which have a closer parent relationship. - parentDist := parentDistance(have.tag.region, tag) - if !beaten && m.parentDist != parentDist { - if parentDist > m.parentDist { - return - } - beaten = true - } - // Update m to the newly found best match. if beaten { m.have = have m.want = tag m.conf = c + m.pinnedRegion = maxRegion + m.sameRegionGroup = sameGroup m.origLang = origLang m.origReg = origReg + m.paradigmReg = paradigmReg m.origScript = origScript - m.regDist = regDist - m.parentDist = parentDist + m.regGroupDist = regGroupDist } } -// parentDistance returns the number of times Parent must be called before the -// regions match. It is assumed that it has already been checked that lang and -// script are identical. If haveRegion does not occur in the ancestor chain of -// tag, it returns 255. -func parentDistance(haveRegion regionID, tag Tag) uint8 { - p := tag.Parent() - d := uint8(1) - for haveRegion != p.region { - if p.region == 0 { - return 255 - } - p = p.Parent() - d++ - } - return d -} - -// regionDist wraps regionDistance with some exceptions to the algorithmic distance. -func regionDist(a, b regionID, lang langID) uint8 { - if lang == _en { - // Two variants of non-US English are close to each other, regardless of distance. - if a != _US && b != _US { - return 2 +func isParadigmLocale(lang langID, r regionID) bool { + for _, e := range paradigmLocales { + if langID(e[0]) == lang && (r == regionID(e[1]) || r == regionID(e[2])) { + return true } } - return uint8(regionDistance(a, b)) + return false } -// regionDistance computes the distance between two regions based on the -// distance in the graph of region containments as defined in CLDR. It iterates -// over increasingly inclusive sets of groups, represented as bit vectors, until -// the source bit vector has bits in common with the destination vector. -func regionDistance(a, b regionID) int { - if a == b { - return 0 +// regionGroupDist computes the distance between two regions based on their +// CLDR grouping. +func regionGroupDist(a, b regionID, script scriptID, lang langID) (dist uint8, same bool) { + const defaultDistance = 4 + + aGroup := uint(regionToGroups[a]) << 1 + bGroup := uint(regionToGroups[b]) << 1 + for _, ri := range matchRegion { + if langID(ri.lang) == lang && (ri.script == 0 || scriptID(ri.script) == script) { + group := uint(1 << (ri.group &^ 0x80)) + if 0x80&ri.group == 0 { + if aGroup&bGroup&group != 0 { // Both regions are in the group. + return ri.distance, ri.distance == defaultDistance + } + } else { + if (aGroup|bGroup)&group == 0 { // Both regions are not in the group. + return ri.distance, ri.distance == defaultDistance + } + } + } } - p, q := regionInclusion[a], regionInclusion[b] - if p < nRegionGroups { - p, q = q, p - } - set := regionInclusionBits - if q < nRegionGroups && set[p]&(1<