From ed3cd197dd41911e76dfee2bb14c522a0d5c953b Mon Sep 17 00:00:00 2001 From: Umputun Date: Sun, 3 Jan 2021 03:55:00 -0600 Subject: [PATCH] bump deps --- backend/app/cmd/server.go | 2 +- backend/app/store/service/service.go | 2 +- backend/app/store/service/title.go | 4 +- backend/go.mod | 10 +- backend/go.sum | 20 +- .../vendor/github.com/go-pkgz/lcw/cache.go | 32 +- .../github.com/go-pkgz/lcw/expirable_cache.go | 6 +- backend/vendor/github.com/go-pkgz/lcw/go.mod | 10 +- backend/vendor/github.com/go-pkgz/lcw/go.sum | 16 +- .../github.com/go-pkgz/lcw/lru_cache.go | 6 +- .../vendor/github.com/go-pkgz/lcw/options.go | 4 +- .../github.com/go-pkgz/lcw/redis_cache.go | 6 +- .../vendor/github.com/go-pkgz/lcw/scache.go | 2 +- .../github.com/go-pkgz/lgr/.golangci.yml | 26 +- backend/vendor/github.com/go-pkgz/lgr/LICENSE | 2 +- .../vendor/github.com/go-pkgz/lgr/README.md | 47 +- .../vendor/github.com/go-pkgz/lgr/adaptor.go | 11 + backend/vendor/github.com/go-pkgz/lgr/go.mod | 4 +- backend/vendor/github.com/go-pkgz/lgr/go.sum | 9 +- .../vendor/github.com/go-pkgz/lgr/logger.go | 115 +- .../vendor/github.com/go-pkgz/lgr/mapper.go | 28 + .../vendor/github.com/go-pkgz/lgr/options.go | 16 +- .../github.com/go-redis/redis/v7/.travis.yml | 2 - .../github.com/go-redis/redis/v7/CHANGELOG.md | 4 + .../github.com/go-redis/redis/v7/Makefile | 2 +- .../github.com/go-redis/redis/v7/README.md | 7 +- .../github.com/go-redis/redis/v7/cluster.go | 11 +- .../github.com/go-redis/redis/v7/command.go | 35 +- .../github.com/go-redis/redis/v7/commands.go | 10 + .../github.com/go-redis/redis/v7/error.go | 15 + .../go-redis/redis/v7/internal/pool/pool.go | 2 + .../redis/v7/internal/proto/reader.go | 2 + .../redis/v7/internal/proto/writer.go | 2 +- .../github.com/go-redis/redis/v7/options.go | 8 +- .../github.com/go-redis/redis/v7/pubsub.go | 4 +- .../github.com/go-redis/redis/v7/redis.go | 6 +- .../github.com/go-redis/redis/v7/result.go | 8 + .../github.com/go-redis/redis/v7/ring.go | 10 +- .../github.com/go-redis/redis/v7/sentinel.go | 6 + .../github.com/go-redis/redis/v7/universal.go | 4 + .../vendor/github.com/google/uuid/README.md | 2 +- .../vendor/github.com/google/uuid/marshal.go | 7 +- .../vendor/github.com/google/uuid/version1.go | 12 +- .../vendor/github.com/google/uuid/version4.go | 7 +- .../russross/blackfriday/v2/README.md | 90 +- .../russross/blackfriday/v2/block.go | 30 +- .../github.com/russross/blackfriday/v2/doc.go | 28 + .../russross/blackfriday/v2/entities.go | 2236 +++++++++++++++++ .../github.com/russross/blackfriday/v2/esc.go | 42 +- .../russross/blackfriday/v2/html.go | 9 +- .../russross/blackfriday/v2/inline.go | 2 +- .../russross/blackfriday/v2/node.go | 12 +- .../sanitized_anchor_name/.travis.yml | 16 - .../shurcooL/sanitized_anchor_name/LICENSE | 21 - .../shurcooL/sanitized_anchor_name/README.md | 36 - .../shurcooL/sanitized_anchor_name/go.mod | 1 - .../shurcooL/sanitized_anchor_name/main.go | 29 - backend/vendor/go.etcd.io/bbolt/README.md | 11 +- backend/vendor/go.etcd.io/bbolt/freelist.go | 57 +- backend/vendor/go.etcd.io/bbolt/node.go | 25 +- backend/vendor/go.etcd.io/bbolt/page.go | 57 +- backend/vendor/go.etcd.io/bbolt/tx.go | 27 +- backend/vendor/go.etcd.io/bbolt/unsafe.go | 39 + backend/vendor/modules.txt | 14 +- 64 files changed, 2945 insertions(+), 381 deletions(-) create mode 100644 backend/vendor/github.com/go-pkgz/lgr/mapper.go create mode 100644 backend/vendor/github.com/russross/blackfriday/v2/entities.go delete mode 100644 backend/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml delete mode 100644 backend/vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE delete mode 100644 backend/vendor/github.com/shurcooL/sanitized_anchor_name/README.md delete mode 100644 backend/vendor/github.com/shurcooL/sanitized_anchor_name/go.mod delete mode 100644 backend/vendor/github.com/shurcooL/sanitized_anchor_name/main.go create mode 100644 backend/vendor/go.etcd.io/bbolt/unsafe.go diff --git a/backend/app/cmd/server.go b/backend/app/cmd/server.go index 5dc2a57f..e15bec31 100644 --- a/backend/app/cmd/server.go +++ b/backend/app/cmd/server.go @@ -977,5 +977,5 @@ func (c *authRefreshCache) Get(key interface{}) (interface{}, bool) { // Set implements cache setter with key converted to string func (c *authRefreshCache) Set(key, value interface{}) { - _, _ = c.LoadingCache.Get(key.(string), func() (cache.Value, error) { return value, nil }) + _, _ = c.LoadingCache.Get(key.(string), func() (interface{}, error) { return value, nil }) } diff --git a/backend/app/store/service/service.go b/backend/app/store/service/service.go index d1ee262b..a16c5201 100644 --- a/backend/app/store/service/service.go +++ b/backend/app/store/service/service.go @@ -507,7 +507,7 @@ func (s *DataStore) HasReplies(comment store.Comment) bool { // When this code is reached, key "comment.ID" is not in cache. // Calling cache.Get on it will put it in cache with 5 minutes TTL. // We call it with empty struct as value as we care about keys and not values. - _, _ = s.repliesCache.Get(comment.ID, func() (lcw.Value, error) { return struct{}{}, nil }) + _, _ = s.repliesCache.Get(comment.ID, func() (interface{}, error) { return struct{}{}, nil }) return true } } diff --git a/backend/app/store/service/title.go b/backend/app/store/service/title.go index 0a22a28b..e30f12c9 100644 --- a/backend/app/store/service/title.go +++ b/backend/app/store/service/title.go @@ -40,7 +40,7 @@ func NewTitleExtractor(client http.Client) *TitleExtractor { // Get page for url and return title func (t *TitleExtractor) Get(url string) (string, error) { client := http.Client{Timeout: t.client.Timeout, Transport: t.client.Transport} - b, err := t.cache.Get(url, func() (lcw.Value, error) { + b, err := t.cache.Get(url, func() (interface{}, error) { resp, err := client.Get(url) if err != nil { return nil, errors.Wrapf(err, "failed to load page %s", url) @@ -63,7 +63,7 @@ func (t *TitleExtractor) Get(url string) (string, error) { // on error save result (empty string) to cache too and return "" title if err != nil { - _, _ = t.cache.Get(url, func() (lcw.Value, error) { return "", nil }) + _, _ = t.cache.Get(url, func() (interface{}, error) { return "", nil }) return "", err } diff --git a/backend/go.mod b/backend/go.mod index 026a0557..fdbbf05a 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -14,12 +14,12 @@ require ( github.com/go-chi/render v1.0.1 github.com/go-pkgz/auth v1.13.1 github.com/go-pkgz/jrpc v0.2.0 - github.com/go-pkgz/lcw v0.7.1 - github.com/go-pkgz/lgr v0.7.0 + github.com/go-pkgz/lcw v0.8.1 + github.com/go-pkgz/lgr v0.10.4 github.com/go-pkgz/repeater v1.1.3 github.com/go-pkgz/rest v1.5.0 github.com/go-pkgz/syncs v1.1.1 - github.com/google/uuid v1.1.1 + github.com/google/uuid v1.1.2 github.com/gorilla/feeds v1.1.1 github.com/hashicorp/go-multierror v1.1.0 github.com/kyokomi/emoji v2.2.1+incompatible @@ -27,10 +27,10 @@ require ( github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/rs/xid v1.2.1 - github.com/russross/blackfriday/v2 v2.0.1 + github.com/russross/blackfriday/v2 v2.1.0 github.com/stretchr/testify v1.6.1 github.com/umputun/go-flags v1.5.1 - go.etcd.io/bbolt v1.3.4 + go.etcd.io/bbolt v1.3.5 go.uber.org/goleak v1.0.0 golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 golang.org/x/image v0.0.0-20200119044424-58c23975cae1 diff --git a/backend/go.sum b/backend/go.sum index a60a96f4..20942744 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -64,18 +64,18 @@ github.com/go-pkgz/expirable-cache v0.0.3 h1:rTh6qNPp78z0bQE6HDhXBHUwqnV9i09Vm6d github.com/go-pkgz/expirable-cache v0.0.3/go.mod h1:+IauqN00R2FqNRLCLA+X5YljQJrwB179PfiAoMPlTlQ= github.com/go-pkgz/jrpc v0.2.0 h1:CLy/eZyekjraVrxZV18N2R1mYLMJ/nWrgdfyIOGPY/E= github.com/go-pkgz/jrpc v0.2.0/go.mod h1:wd8vtQ4CgtCnuqua6x2b1SKIgv0VSOh5Dn0uUITbiUE= -github.com/go-pkgz/lcw v0.7.1 h1:2Q2k1am6xb2KgxZG84kL072q66rlWFUR+MvgPcDcJXA= -github.com/go-pkgz/lcw v0.7.1/go.mod h1:3P6g9QrJsDePXEMe42ywO+tW08L17tBJGwIDdI7lZ6g= -github.com/go-pkgz/lgr v0.7.0 h1:S/AAPwt/RE9a5mNJskA7dGVp+Dq6SMIW6LYjG3ITxY8= -github.com/go-pkgz/lgr v0.7.0/go.mod h1:yMgxU+GobMRJgIEbSzDKy/67W18S7qmGx/7BVL5AB8Q= +github.com/go-pkgz/lcw v0.8.1 h1:Bpt2yYTE1J8hIhz8tjdm1WPOgH13eo5iTNsXyop7cMQ= +github.com/go-pkgz/lcw v0.8.1/go.mod h1:Xw0/ZfApATgbjVPYRZO4XHdWyxAjErDWDWJ7TLlw1Vc= +github.com/go-pkgz/lgr v0.10.4 h1:l7qyFjqEZgwRgaQQSEp6tve4A3OU80VrfzpvtEX8ngw= +github.com/go-pkgz/lgr v0.10.4/go.mod h1:CD0s1z6EFpIUplV067gitF77tn25JItzwHNKAPqeCF0= github.com/go-pkgz/repeater v1.1.3 h1:q6+JQF14ESSy28Dd7F+wRelY4F+41HJ0LEy/szNnMiE= github.com/go-pkgz/repeater v1.1.3/go.mod h1:hVTavuO5x3Gxnu8zW7d6sQBfAneKV8X2FjU48kGfpKw= github.com/go-pkgz/rest v1.5.0 h1:C8SxXcXza4GiUUAn/95iCkvoIrGbS30qpwK19iqlrWQ= github.com/go-pkgz/rest v1.5.0/go.mod h1:nQaM3RhSTUAmbBZWY4hfe4buyeC9VckvhoCktiQXJxI= github.com/go-pkgz/syncs v1.1.1 h1:jWN+y6FS/Xe+8z4l3QMbSnODGyaxDHGojIS+wyKIjxg= github.com/go-pkgz/syncs v1.1.1/go.mod h1:bt9lxWRRJ9vOCMGc8Big8ttjYHLKP88ofj1y38UlaHE= -github.com/go-redis/redis/v7 v7.2.0 h1:CrCexy/jYWZjW0AyVoHlcJUeZN19VWlbepTh1Vq6dJs= -github.com/go-redis/redis/v7 v7.2.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= +github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4= +github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2T1yBBLxTan3mn/3OM0CyRt0= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= @@ -115,8 +115,8 @@ github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/feeds v1.1.1 h1:HwKXxqzcRNg9to+BbvJog4+f3s/xzvtZXICcQGutYfY= @@ -197,6 +197,8 @@ github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 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/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= @@ -266,6 +268,8 @@ github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb h1:ZkM6LRnq40pR1Ox github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.mongodb.org/mongo-driver v1.4.4 h1:bsPHfODES+/yx2PCWzUYMH8xj6PVniPI8DQrsJuSXSs= go.mongodb.org/mongo-driver v1.4.4/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo= diff --git a/backend/vendor/github.com/go-pkgz/lcw/cache.go b/backend/vendor/github.com/go-pkgz/lcw/cache.go index e7452a47..56f9f0a1 100644 --- a/backend/vendor/github.com/go-pkgz/lcw/cache.go +++ b/backend/vendor/github.com/go-pkgz/lcw/cache.go @@ -12,9 +12,6 @@ import ( "fmt" ) -// Value type wraps interface{} -type Value interface{} - // Sizer allows to perform size-based restrictions, optional. // If not defined both maxValueSize and maxCacheSize checks will be ignored type Sizer interface { @@ -23,14 +20,14 @@ type Sizer interface { // LoadingCache defines guava-like cache with Get method returning cached value ao retrieving it if not in cache type LoadingCache interface { - Get(key string, fn func() (Value, error)) (val Value, err error) // load or get from cache - Peek(key string) (Value, bool) // get from cache by key - Invalidate(fn func(key string) bool) // invalidate items for func(key) == true - Delete(key string) // delete by key - Purge() // clear cache - Stat() CacheStat // cache stats - Keys() []string // list of all keys - Close() error // close open connections + Get(key string, fn func() (interface{}, error)) (val interface{}, err error) // load or get from cache + Peek(key string) (interface{}, bool) // get from cache by key + Invalidate(fn func(key string) bool) // invalidate items for func(key) == true + Delete(key string) // delete by key + Purge() // clear cache + Stat() CacheStat // cache stats + Keys() []string // list of all keys + Close() error // close open connections } // CacheStat represent stats values @@ -44,8 +41,12 @@ type CacheStat struct { // String formats cache stats func (s CacheStat) String() string { - return fmt.Sprintf("{hits:%d, misses:%d, ratio:%.1f%%, keys:%d, size:%d, errors:%d}", - s.Hits, s.Misses, 100*(float64(s.Hits)/float64(s.Hits+s.Misses)), s.Keys, s.Size, s.Errors) + ratio := 0.0 + if s.Hits+s.Misses > 0 { + ratio = float64(s.Hits) / float64(s.Hits+s.Misses) + } + return fmt.Sprintf("{hits:%d, misses:%d, ratio:%.2f, keys:%d, size:%d, errors:%d}", + s.Hits, s.Misses, ratio, s.Keys, s.Size, s.Errors) } // Nop is do-nothing implementation of LoadingCache @@ -57,10 +58,10 @@ func NewNopCache() *Nop { } // Get calls fn without any caching -func (n *Nop) Get(key string, fn func() (Value, error)) (Value, error) { return fn() } +func (n *Nop) Get(key string, fn func() (interface{}, error)) (interface{}, error) { return fn() } // Peek does nothing and always returns false -func (n *Nop) Peek(key string) (Value, bool) { return nil, false } +func (n *Nop) Peek(key string) (interface{}, bool) { return nil, false } // Invalidate does nothing for nop cache func (n *Nop) Invalidate(fn func(key string) bool) {} @@ -83,4 +84,3 @@ func (n *Nop) Stat() CacheStat { func (n *Nop) Close() error { return nil } - diff --git a/backend/vendor/github.com/go-pkgz/lcw/expirable_cache.go b/backend/vendor/github.com/go-pkgz/lcw/expirable_cache.go index 8b20f7ec..5e114b3d 100644 --- a/backend/vendor/github.com/go-pkgz/lcw/expirable_cache.go +++ b/backend/vendor/github.com/go-pkgz/lcw/expirable_cache.go @@ -69,7 +69,7 @@ func NewExpirableCache(opts ...Option) (*ExpirableCache, error) { } // Get gets value by key or load with fn if not found in cache -func (c *ExpirableCache) Get(key string, fn func() (Value, error)) (data Value, err error) { +func (c *ExpirableCache) Get(key string, fn func() (interface{}, error)) (data interface{}, err error) { if v, ok := c.backend.Get(key); ok { atomic.AddInt64(&c.Hits, 1) return v, nil @@ -104,7 +104,7 @@ func (c *ExpirableCache) Invalidate(fn func(key string) bool) { } // Peek returns the key value (or undefined if not found) without updating the "recently used"-ness of the key. -func (c *ExpirableCache) Peek(key string) (Value, bool) { +func (c *ExpirableCache) Peek(key string) (interface{}, bool) { return c.backend.Peek(key) } @@ -156,7 +156,7 @@ func (c *ExpirableCache) keys() int { return c.backend.ItemCount() } -func (c *ExpirableCache) allowed(key string, data Value) bool { +func (c *ExpirableCache) allowed(key string, data interface{}) bool { if c.backend.ItemCount() >= c.maxKeys { return false } diff --git a/backend/vendor/github.com/go-pkgz/lcw/go.mod b/backend/vendor/github.com/go-pkgz/lcw/go.mod index bd7894d5..dc6623f7 100644 --- a/backend/vendor/github.com/go-pkgz/lcw/go.mod +++ b/backend/vendor/github.com/go-pkgz/lcw/go.mod @@ -1,13 +1,13 @@ module github.com/go-pkgz/lcw +go 1.15 + require ( github.com/alicebob/miniredis/v2 v2.11.4 - github.com/go-redis/redis/v7 v7.2.0 - github.com/google/uuid v1.1.1 + github.com/go-redis/redis/v7 v7.4.0 + github.com/google/uuid v1.1.2 github.com/hashicorp/go-multierror v1.1.0 github.com/hashicorp/golang-lru v0.5.4 github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.5.1 + github.com/stretchr/testify v1.6.1 ) - -go 1.13 diff --git a/backend/vendor/github.com/go-pkgz/lcw/go.sum b/backend/vendor/github.com/go-pkgz/lcw/go.sum index 8f189aae..a1f4244f 100644 --- a/backend/vendor/github.com/go-pkgz/lcw/go.sum +++ b/backend/vendor/github.com/go-pkgz/lcw/go.sum @@ -9,15 +9,15 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/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/go-redis/redis/v7 v7.2.0 h1:CrCexy/jYWZjW0AyVoHlcJUeZN19VWlbepTh1Vq6dJs= -github.com/go-redis/redis/v7 v7.2.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= +github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4= +github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/gomodule/redigo v1.7.1-0.20190322064113-39e2c31b7ca3 h1:6amM4HsNPOvMLVc2ZnyqrjeQ92YAVWn7T4WBKK87inY= github.com/gomodule/redigo v1.7.1-0.20190322064113-39e2c31b7ca3/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= @@ -40,9 +40,10 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb h1:ZkM6LRnq40pR1Ox0hTHlnpkcOTuFIDQpZ1IN8rKKhX0= github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -67,6 +68,7 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy 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/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/backend/vendor/github.com/go-pkgz/lcw/lru_cache.go b/backend/vendor/github.com/go-pkgz/lcw/lru_cache.go index 914ab954..ba3c3b3d 100644 --- a/backend/vendor/github.com/go-pkgz/lcw/lru_cache.go +++ b/backend/vendor/github.com/go-pkgz/lcw/lru_cache.go @@ -65,7 +65,7 @@ func (c *LruCache) init() error { } // Get gets value by key or load with fn if not found in cache -func (c *LruCache) Get(key string, fn func() (Value, error)) (data Value, err error) { +func (c *LruCache) Get(key string, fn func() (interface{}, error)) (data interface{}, err error) { if v, ok := c.backend.Get(key); ok { atomic.AddInt64(&c.Hits, 1) return v, nil @@ -97,7 +97,7 @@ func (c *LruCache) Get(key string, fn func() (Value, error)) (data Value, err er } // Peek returns the key value (or undefined if not found) without updating the "recently used"-ness of the key. -func (c *LruCache) Peek(key string) (Value, bool) { +func (c *LruCache) Peek(key string) (interface{}, bool) { return c.backend.Peek(key) } @@ -162,7 +162,7 @@ func (c *LruCache) keys() int { return c.backend.Len() } -func (c *LruCache) allowed(key string, data Value) bool { +func (c *LruCache) allowed(key string, data interface{}) bool { if c.maxKeySize > 0 && len(key) > c.maxKeySize { return false } diff --git a/backend/vendor/github.com/go-pkgz/lcw/options.go b/backend/vendor/github.com/go-pkgz/lcw/options.go index 5a93d2b1..b46dad20 100644 --- a/backend/vendor/github.com/go-pkgz/lcw/options.go +++ b/backend/vendor/github.com/go-pkgz/lcw/options.go @@ -13,7 +13,7 @@ type options struct { maxKeySize int maxCacheSize int64 ttl time.Duration - onEvicted func(key string, value Value) + onEvicted func(key string, value interface{}) eventBus eventbus.PubSub } @@ -81,7 +81,7 @@ func TTL(ttl time.Duration) Option { } // OnEvicted sets callback on invalidation event -func OnEvicted(fn func(key string, value Value)) Option { +func OnEvicted(fn func(key string, value interface{})) Option { return func(o *options) error { o.onEvicted = fn return nil diff --git a/backend/vendor/github.com/go-pkgz/lcw/redis_cache.go b/backend/vendor/github.com/go-pkgz/lcw/redis_cache.go index e2deb985..b7353a33 100644 --- a/backend/vendor/github.com/go-pkgz/lcw/redis_cache.go +++ b/backend/vendor/github.com/go-pkgz/lcw/redis_cache.go @@ -41,7 +41,7 @@ func NewRedisCache(backend *redis.Client, opts ...Option) (*RedisCache, error) { } // Get gets value by key or load with fn if not found in cache -func (c *RedisCache) Get(key string, fn func() (Value, error)) (data Value, err error) { +func (c *RedisCache) Get(key string, fn func() (interface{}, error)) (data interface{}, err error) { v, getErr := c.backend.Get(key).Result() switch getErr { // RedisClient returns nil when find a key in DB @@ -84,7 +84,7 @@ func (c *RedisCache) Invalidate(fn func(key string) bool) { } // Peek returns the key value (or undefined if not found) without updating the "recently used"-ness of the key. -func (c *RedisCache) Peek(key string) (Value, bool) { +func (c *RedisCache) Peek(key string) (interface{}, bool) { ret, err := c.backend.Get(key).Result() if err != nil { return nil, false @@ -132,7 +132,7 @@ func (c *RedisCache) keys() int { return int(c.backend.DBSize().Val()) } -func (c *RedisCache) allowed(key string, data Value) bool { +func (c *RedisCache) allowed(key string, data interface{}) bool { if c.maxKeys > 0 && c.backend.DBSize().Val() >= int64(c.maxKeys) { return false } diff --git a/backend/vendor/github.com/go-pkgz/lcw/scache.go b/backend/vendor/github.com/go-pkgz/lcw/scache.go index 793f92a8..fe9023d4 100644 --- a/backend/vendor/github.com/go-pkgz/lcw/scache.go +++ b/backend/vendor/github.com/go-pkgz/lcw/scache.go @@ -20,7 +20,7 @@ func NewScache(lc LoadingCache) *Scache { // Get retrieves a key from underlying backend func (m *Scache) Get(key Key, fn func() ([]byte, error)) (data []byte, err error) { keyStr := key.String() - val, err := m.lc.Get(keyStr, func() (value Value, e error) { + val, err := m.lc.Get(keyStr, func() (value interface{}, e error) { return fn() }) return val.([]byte), err diff --git a/backend/vendor/github.com/go-pkgz/lgr/.golangci.yml b/backend/vendor/github.com/go-pkgz/lgr/.golangci.yml index 989af86e..23fd915e 100644 --- a/backend/vendor/github.com/go-pkgz/lgr/.golangci.yml +++ b/backend/vendor/github.com/go-pkgz/lgr/.golangci.yml @@ -23,11 +23,12 @@ linters-settings: - experimental disabled-checks: - wrapperFunc + - hugeParam linters: - disable-all: true enable: - megacheck + - golint - govet - unconvert - megacheck @@ -42,19 +43,28 @@ linters: - typecheck - ineffassign - varcheck + - stylecheck + - gochecknoinits + - scopelint + - gocritic + - nakedret + - gosimple + - prealloc fast: false - + disable-all: true run: -# modules-download-mode: vendor + output: + format: tab skip-dirs: - vendor issues: exclude-rules: - - text: "weak cryptographic primitive" + - text: "should have a package comment, unless it's in another file for this package" linters: - - gosec - -service: - golangci-lint-version: 1.16.x \ No newline at end of file + - golint + - text: "at least one file in a package should have a package comment" + linters: + - stylecheck + exclude-use-default: false diff --git a/backend/vendor/github.com/go-pkgz/lgr/LICENSE b/backend/vendor/github.com/go-pkgz/lgr/LICENSE index ac540250..c1b684bf 100644 --- a/backend/vendor/github.com/go-pkgz/lgr/LICENSE +++ b/backend/vendor/github.com/go-pkgz/lgr/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Umputun +Copyright (c) 2020 Umputun Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/backend/vendor/github.com/go-pkgz/lgr/README.md b/backend/vendor/github.com/go-pkgz/lgr/README.md index 9e2d14d7..f01f999a 100644 --- a/backend/vendor/github.com/go-pkgz/lgr/README.md +++ b/backend/vendor/github.com/go-pkgz/lgr/README.md @@ -1,4 +1,5 @@ -# lgr - simple logger with some extras [![Build Status](https://github.com/go-pkgz/lgr/workflows/build/badge.svg)](https://github.com/go-pkgz/lgr/actions) [![Coverage Status](https://coveralls.io/repos/github/go-pkgz/lgr/badge.svg?branch=master)](https://coveralls.io/github/go-pkgz/lgr?branch=master) [![godoc](https://godoc.org/github.com/go-pkgz/lgr?status.svg)](https://godoc.org/github.com/go-pkgz/lgr) +# lgr - simple logger with some extras +[![Build Status](https://github.com/go-pkgz/lgr/workflows/build/badge.svg)](https://github.com/go-pkgz/lgr/actions) [![Coverage Status](https://coveralls.io/repos/github/go-pkgz/lgr/badge.svg?branch=master)](https://coveralls.io/github/go-pkgz/lgr?branch=master) [![godoc](https://godoc.org/github.com/go-pkgz/lgr?status.svg)](https://godoc.org/github.com/go-pkgz/lgr) ## install @@ -24,7 +25,7 @@ _Without `lgr.Caller*` it will drop `{caller}` part_ ### interfaces and default loggers -- `lgr` package provides a single interface `lgr.L` with a single method `Logf(format string, args ...interface{})`. Function wrapper `lgr.Func` allows to make `lgr.L` from a function directly. +- `lgr` package provides a single interface `lgr.L` with a single method `Logf(format string, args ...interface{})`. Function wrapper `lgr.Func` allows making `lgr.L` from a function directly. - Default logger functionality can be used without `lgr.New` (see "global logger") - Two predefined loggers available: `lgr.NoOp` (do-nothing logger) and `lgr.Std` (passing directly to stdlib log) @@ -41,8 +42,10 @@ _Without `lgr.Caller*` it will drop `{caller}` part_ - `lgr.CallerPkg` - adds the caller package - `lgr.LevelBraces` - wraps levels with "[" and "]" - `lgr.Msec` - adds milliseconds to timestamp -- `lgr.Format` - sets custom template, overwrite all other formatting modifiers. +- `lgr.Format` - sets a custom template, overwrite all other formatting modifiers. - `lgr.Secret(secret ...)` - sets list of the secrets to hide from the logging outputs. +- `lgr.Map(mapper)` - sets mapper functions to change elements of the logging output based on levels. +- `lgr.StackTraceOnError` - turns on stack trace for ERROR level. example: `l := lgr.New(lgr.Debug, lgr.Msec)` @@ -61,16 +64,16 @@ Several predefined templates provided and can be passed directly to `lgr.Format` User can make a custom template and pass it directly to `lgr.Format`. For example: -```go +```go lgr.Format(`{{.Level}} - {{.DT.Format "2006-01-02T15:04:05Z07:00"}} - {{.CallerPkg}} - {{.Message}}`) ``` _Note: formatter (predefined or custom) adds measurable overhead - the cost will depend on the version of Go, but is between 30 and 50% in recent tests with 1.12. You can validate this in your environment via benchmarks: `go test -bench=. -run=Bench`_ - + ### levels -`lgr.Logf` recognizes prefixes like "INFO" or "[INFO]" as levels. The full list of supported levels - "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "PANIC" and "FATAL" +`lgr.Logf` recognize prefixes like `INFO` or `[INFO]` as levels. The full list of supported levels - `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `PANIC` and `FATAL`. - `TRACE` will be filtered unless `lgr.Trace` option defined - `DEBUG` will be filtered unless `lgr.Debug` or `lgr.Trace` options defined @@ -78,7 +81,29 @@ _Note: formatter (predefined or custom) adds measurable overhead - the cost will - `ERROR` sends messages to both out and err writers - `FATAL` and send messages to both out and err writers and exit(1) - `PANIC` does the same as `FATAL` but in addition sends dump of callers and runtime info to err. - + +### mapper + +Elements of the output can be altered with a set of user defined function passed as `lgr.Map` options. Such a mapper changes +the value of an element (i.e. timestamp, level, message, caller) and has separate functions for each level. Note: both level +and messages elements handled by the same function for a given level. + +_A typical use-case is to produce colorful output with a user-define colorization library._ + +example with [fatih/color](https://github.com/fatih/color): + +```go + colorizer := lgr.Mapper{ + ErrorFunc: func(s string) string { return color.New(color.FgHiRed).Sprint(s) }, + WarnFunc: func(s string) string { return color.New(color.FgHiYellow).Sprint(s) }, + InfoFunc: func(s string) string { return color.New(color.FgHiWhite).Sprint(s) }, + DebugFunc: func(s string) string { return color.New(color.FgWhite).Sprint(s) }, + CallerFunc: func(s string) string { return color.New(color.FgBlue).Sprint(s) }, + TimeFunc: func(s string) string { return color.New(color.FgCyan).Sprint(s) }, + } + + logOpts := []lgr.Option{lgr.Msec, lgr.LevelBraces, lgr.Map(colorizer)} +``` ### adaptors `lgr` logger can be converted to `io.Writer` or `*log.Logger` @@ -86,10 +111,14 @@ _Note: formatter (predefined or custom) adds measurable overhead - the cost will - `lgr.ToWriter(l lgr.L, level string) io.Writer` - makes io.Writer forwarding write ops to underlying `lgr.L` - `lgr.ToStdLogger(l lgr.L, level string) *log.Logger` - makes standard logger on top of `lgr.L` -_`level` parameter is optional, if defined (non-empty) will enforce the level._ - +_`level` parameter is optional, if defined (non-empty) will enforce the level._ + +- `lgr.SetupStdLogger(opts ...Option)` initializes std global logger (`log.std`) with lgr logger and given options. +All standard methods like `log.Print`, `log.Println`, `log.Fatal` and so on will be forwarder to lgr. + ### global logger Users **should avoid** global logger and pass the concrete logger as a dependency. However, in some cases a global logger may be needed, for example migration from stdlib `log` to `lgr`. For such cases `log "github.com/go-pkgz/lgr"` can be imported instead of `log` package. Global logger provides `lgr.Printf`, `lgr.Print` and `lgr.Fatalf` functions. User can customize the logger by calling `lgr.Setup(options ...)`. The instance of this logger can be retrieved with `lgr.Default()` + diff --git a/backend/vendor/github.com/go-pkgz/lgr/adaptor.go b/backend/vendor/github.com/go-pkgz/lgr/adaptor.go index 2627325d..03e80eb9 100644 --- a/backend/vendor/github.com/go-pkgz/lgr/adaptor.go +++ b/backend/vendor/github.com/go-pkgz/lgr/adaptor.go @@ -25,6 +25,17 @@ func ToWriter(l L, level string) *Writer { return &Writer{l, level} } +// ToStdLogger makes standard logger func ToStdLogger(l L, level string) *log.Logger { return log.New(ToWriter(l, level), "", 0) } + +// SetupStdLogger makes the default std logger with lgr.L +func SetupStdLogger(opts ...Option) { + logOpts := append([]Option{CallerDepth(3)}, opts...) // skip 3 more frames to compensate stdlog calls + l := New(logOpts...) + l.reTrace = reTraceStd // std logger split on log/ path + log.SetOutput(ToWriter(l, "")) + log.SetPrefix("") + log.SetFlags(0) +} diff --git a/backend/vendor/github.com/go-pkgz/lgr/go.mod b/backend/vendor/github.com/go-pkgz/lgr/go.mod index f8783dcf..4ea4d22f 100644 --- a/backend/vendor/github.com/go-pkgz/lgr/go.mod +++ b/backend/vendor/github.com/go-pkgz/lgr/go.mod @@ -1,5 +1,5 @@ module github.com/go-pkgz/lgr -require github.com/stretchr/testify v1.3.0 +require github.com/stretchr/testify v1.6.1 -go 1.13 +go 1.15 diff --git a/backend/vendor/github.com/go-pkgz/lgr/go.sum b/backend/vendor/github.com/go-pkgz/lgr/go.sum index 4347755a..1f1e7af9 100644 --- a/backend/vendor/github.com/go-pkgz/lgr/go.sum +++ b/backend/vendor/github.com/go-pkgz/lgr/go.sum @@ -2,6 +2,11 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/backend/vendor/github.com/go-pkgz/lgr/logger.go b/backend/vendor/github.com/go-pkgz/lgr/logger.go index baec9720..9ba12d33 100644 --- a/backend/vendor/github.com/go-pkgz/lgr/logger.go +++ b/backend/vendor/github.com/go-pkgz/lgr/logger.go @@ -6,7 +6,6 @@ // Debug and trace levels can be filtered based on lgr.Trace and lgr.Debug options. // ERROR, FATAL and PANIC levels send to err as well. FATAL terminate caller application with os.Exit(1) // and PANIC also prints stack trace. - package lgr import ( @@ -15,6 +14,7 @@ import ( "io" "os" "path" + "regexp" "runtime" "strconv" "strings" @@ -26,16 +26,27 @@ import ( var levels = []string{"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "PANIC", "FATAL"} const ( - Short = `{{.DT.Format "2006/01/02 15:04:05"}} {{.Level}} {{.Message}}` - WithMsec = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} {{.Message}}` - WithPkg = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerPkg}}) {{.Message}}` + // Short logging format + Short = `{{.DT.Format "2006/01/02 15:04:05"}} {{.Level}} {{.Message}}` + // WithMsec is a logging format with milliseconds + WithMsec = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} {{.Message}}` + // WithPkg is WithMsec logging format with caller package + WithPkg = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerPkg}}) {{.Message}}` + // ShortDebug is WithMsec logging format with caller file and line ShortDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFile}}:{{.CallerLine}}) {{.Message}}` - FuncDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFunc}}) {{.Message}}` - FullDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFile}}:{{.CallerLine}} {{.CallerFunc}}) {{.Message}}` + // FuncDebug is WithMsec logging format with caller function + FuncDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFunc}}) {{.Message}}` + // FullDebug is WithMsec logging format with caller file, line and function + FullDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFile}}:{{.CallerLine}} {{.CallerFunc}}) {{.Message}}` ) var secretReplacement = []byte("******") +var ( + reTraceDefault = regexp.MustCompile(`.*/lgr/logger\.go.*\n`) + reTraceStd = regexp.MustCompile(`.*/log/log\.go.*\n`) +) + // Logger provided simple logger with basic support of levels. Thread safe type Logger struct { // set with Option calls @@ -48,7 +59,8 @@ type Logger struct { levelBraces bool // encloses level with [], i.e. [INFO] callerDepth int // how many stack frames to skip, relative to the real (reported) frame format string // layout template - secrets []string // sub-strings to secrets by matching + secrets [][]byte // sub-strings to secrets by matching + mapper Mapper // map (alter) output based on levels // internal use now nowFn @@ -57,7 +69,9 @@ type Logger struct { lock sync.Mutex callerOn bool levelBracesOn bool + errorDump bool templ *template.Template + reTrace *regexp.Regexp } // can be redefined internally for testing @@ -85,6 +99,8 @@ func New(options ...Option) *Logger { stdout: os.Stdout, stderr: os.Stderr, callerDepth: 0, + mapper: nopMapper, + reTrace: reTraceDefault, } for _, opt := range options { opt(&res) @@ -124,9 +140,16 @@ func (l *Logger) Logf(format string, args ...interface{}) { l.logf(format, args...) } +//nolint gocyclo func (l *Logger) logf(format string, args ...interface{}) { - lv, msg := l.extractLevel(fmt.Sprintf(format, args...)) + var lv, msg string + if len(args) == 0 { + lv, msg = l.extractLevel(format) + } else { + lv, msg = l.extractLevel(fmt.Sprintf(format, args...)) + } + if lv == "DEBUG" && !l.dbg { return } @@ -177,6 +200,15 @@ func (l *Logger) logf(format string, args ...interface{}) { if l.stderr != l.stdout { _, _ = l.stderr.Write(data) } + if l.errorDump { + stackInfo := make([]byte, 1024*1024) + if stackSize := runtime.Stack(stackInfo, false); stackSize > 0 { + traceLines := l.reTrace.Split(string(stackInfo[:stackSize]), -1) + if len(traceLines) > 0 { + _, _ = l.stdout.Write([]byte(">>> stack trace:\n" + traceLines[len(traceLines)-1])) + } + } + } case "FATAL": if l.stderr != l.stdout { _, _ = l.stderr.Write(data) @@ -195,7 +227,7 @@ func (l *Logger) logf(format string, args ...interface{}) { func (l *Logger) hideSecrets(data []byte) []byte { for _, h := range l.secrets { - data = bytes.Replace(data, []byte(h), secretReplacement, -1) + data = bytes.Replace(data, h, secretReplacement, -1) } return data } @@ -268,15 +300,17 @@ func (l *Logger) formatWithOptions(elems layout) (res string) { parts := make([]string, 0, 4) - parts = append(parts, orElse(l.msec, - func() string { return elems.DT.Format("2006/01/02 15:04:05.000") }, - func() string { return elems.DT.Format("2006/01/02 15:04:05") }, - )) - - parts = append(parts, orElse(l.levelBraces, - func() string { return `[` + elems.Level + `]` }, - func() string { return elems.Level }, - )) + parts = append( + parts, + l.mapper.TimeFunc(orElse(l.msec, + func() string { return elems.DT.Format("2006/01/02 15:04:05.000") }, + func() string { return elems.DT.Format("2006/01/02 15:04:05") }, + )), + l.levelMapper(elems.Level)(orElse(l.levelBraces, + func() string { return `[` + elems.Level + `]` }, + func() string { return elems.Level }, + )), + ) if l.callerFile || l.callerFunc || l.callerPkg { var callerParts []string @@ -290,10 +324,20 @@ func (l *Logger) formatWithOptions(elems layout) (res string) { if v := orElse(l.callerPkg, func() string { return elems.CallerPkg }, nothing); v != "" { callerParts = append(callerParts, v) } - parts = append(parts, "{"+strings.Join(callerParts, " ")+"}") + + caller := "{" + strings.Join(callerParts, " ") + "}" + if l.mapper.CallerFunc != nil { + caller = l.mapper.CallerFunc(caller) + } + parts = append(parts, caller) } - parts = append(parts, elems.Message) + msg := elems.Message + if l.mapper.MessageFunc != nil { + msg = l.mapper.MessageFunc(elems.Message) + } + + parts = append(parts, l.levelMapper(elems.Level)(msg)) return strings.Join(parts, " ") } @@ -320,6 +364,37 @@ func (l *Logger) extractLevel(line string) (level, msg string) { return "INFO", line } +func (l *Logger) levelMapper(level string) mapFunc { + + nop := func(s string) string { + return s + } + + switch level { + case "TRACE", "DEBUG": + if l.mapper.DebugFunc == nil { + return nop + } + return l.mapper.DebugFunc + case "INFO ": + if l.mapper.InfoFunc == nil { + return nop + } + return l.mapper.InfoFunc + case "WARN ": + if l.mapper.WarnFunc == nil { + return nop + } + return l.mapper.WarnFunc + case "ERROR", "PANIC", "FATAL": + if l.mapper.ErrorFunc == nil { + return nop + } + return l.mapper.ErrorFunc + } + return func(s string) string { return s } +} + // getDump reads runtime stack and returns as a string func getDump() []byte { maxSize := 5 * 1024 * 1024 diff --git a/backend/vendor/github.com/go-pkgz/lgr/mapper.go b/backend/vendor/github.com/go-pkgz/lgr/mapper.go new file mode 100644 index 00000000..c7bcc6e0 --- /dev/null +++ b/backend/vendor/github.com/go-pkgz/lgr/mapper.go @@ -0,0 +1,28 @@ +package lgr + +// Mapper defines optional functions to change elements of the logged message for each part, based on levels. +// Only some mapFunc can be defined, by default does nothing. Can be used to alter the output, for example making some +// part of the output colorful. +type Mapper struct { + MessageFunc mapFunc // message mapper on all levels + ErrorFunc mapFunc // message mapper on ERROR level + WarnFunc mapFunc // message mapper on WARN level + InfoFunc mapFunc // message mapper on INFO level + DebugFunc mapFunc // message mapper on DEBUG level + + CallerFunc mapFunc // caller mapper, all levels + TimeFunc mapFunc // time mapper, all levels +} + +type mapFunc func(string) string + +// nopMapper is a default, doing nothing +var nopMapper = Mapper{ + MessageFunc: func(s string) string { return s }, + ErrorFunc: func(s string) string { return s }, + WarnFunc: func(s string) string { return s }, + InfoFunc: func(s string) string { return s }, + DebugFunc: func(s string) string { return s }, + CallerFunc: func(s string) string { return s }, + TimeFunc: func(s string) string { return s }, +} diff --git a/backend/vendor/github.com/go-pkgz/lgr/options.go b/backend/vendor/github.com/go-pkgz/lgr/options.go index 4de15d88..646d4863 100644 --- a/backend/vendor/github.com/go-pkgz/lgr/options.go +++ b/backend/vendor/github.com/go-pkgz/lgr/options.go @@ -73,6 +73,20 @@ func Msec(l *Logger) { // Useful to prevent passwords or other sensitive tokens to be logged. func Secret(vals ...string) Option { return func(l *Logger) { - l.secrets = vals + for _, v := range vals { + l.secrets = append(l.secrets, []byte(v)) + } } } + +// Map sets mapper functions to change elements of the logged message based on levels. +func Map(m Mapper) Option { + return func(l *Logger) { + l.mapper = m + } +} + +// StackTraceOnError turns on stack trace for ERROR level. +func StackTraceOnError(l *Logger) { + l.errorDump = true +} diff --git a/backend/vendor/github.com/go-redis/redis/v7/.travis.yml b/backend/vendor/github.com/go-redis/redis/v7/.travis.yml index 0c1eef91..3f93932b 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/.travis.yml +++ b/backend/vendor/github.com/go-redis/redis/v7/.travis.yml @@ -1,12 +1,10 @@ dist: xenial -sudo: false language: go services: - redis-server go: - - 1.11.x - 1.12.x - 1.13.x - tip diff --git a/backend/vendor/github.com/go-redis/redis/v7/CHANGELOG.md b/backend/vendor/github.com/go-redis/redis/v7/CHANGELOG.md index 88701cfd..bd4eccff 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/CHANGELOG.md +++ b/backend/vendor/github.com/go-redis/redis/v7/CHANGELOG.md @@ -4,6 +4,10 @@ - Existing `HMSet` is renamed to `HSet` and old deprecated `HMSet` is restored for Redis 3 users. +## v7.1 + +- Existing `Cmd.String` is renamed to `Cmd.Text`. New `Cmd.String` implements `fmt.Stringer` interface. + ## v7 - *Important*. Tx.Pipeline now returns a non-transactional pipeline. Use Tx.TxPipeline for a transactional pipeline. diff --git a/backend/vendor/github.com/go-redis/redis/v7/Makefile b/backend/vendor/github.com/go-redis/redis/v7/Makefile index 421993ef..86609c6e 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/Makefile +++ b/backend/vendor/github.com/go-redis/redis/v7/Makefile @@ -14,7 +14,7 @@ bench: testdeps testdata/redis: mkdir -p $@ - wget -qO- http://download.redis.io/releases/redis-5.0.7.tar.gz | tar xvz --strip-components=1 -C $@ + wget -qO- http://download.redis.io/redis-stable.tar.gz | tar xvz --strip-components=1 -C $@ testdata/redis/src/redis-server: testdata/redis cd $< && make all diff --git a/backend/vendor/github.com/go-redis/redis/v7/README.md b/backend/vendor/github.com/go-redis/redis/v7/README.md index 7331a56b..0fbb506e 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/README.md +++ b/backend/vendor/github.com/go-redis/redis/v7/README.md @@ -101,7 +101,7 @@ set, err := client.SetNX("key", "value", 10*time.Second).Result() vals, err := client.Sort("list", &redis.Sort{Offset: 0, Count: 2, Order: "ASC"}).Result() // ZRANGEBYSCORE zset -inf +inf WITHSCORES LIMIT 0 2 -vals, err := client.ZRangeByScoreWithScores("zset", redis.ZRangeBy{ +vals, err := client.ZRangeByScoreWithScores("zset", &redis.ZRangeBy{ Min: "-inf", Max: "+inf", Offset: 0, @@ -109,7 +109,10 @@ vals, err := client.ZRangeByScoreWithScores("zset", redis.ZRangeBy{ }).Result() // ZINTERSTORE out 2 zset1 zset2 WEIGHTS 2 3 AGGREGATE SUM -vals, err := client.ZInterStore("out", redis.ZStore{Weights: []int64{2, 3}}, "zset1", "zset2").Result() +vals, err := client.ZInterStore("out", &redis.ZStore{ + Keys: []string{"zset1", "zset2"}, + Weights: []int64{2, 3} +}).Result() // EVAL "return {KEYS[1],ARGV[1]}" 1 "key" "hello" vals, err := client.Eval("return {KEYS[1],ARGV[1]}", []string{"key"}, "hello").Result() diff --git a/backend/vendor/github.com/go-redis/redis/v7/cluster.go b/backend/vendor/github.com/go-redis/redis/v7/cluster.go index 2cf6e01b..1907de6c 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/cluster.go +++ b/backend/vendor/github.com/go-redis/redis/v7/cluster.go @@ -57,6 +57,7 @@ type ClusterOptions struct { OnConnect func(*Conn) error + Username string Password string MaxRetries int @@ -67,6 +68,9 @@ type ClusterOptions struct { ReadTimeout time.Duration WriteTimeout time.Duration + // NewClient creates a cluster node client with provided name and options. + NewClient func(opt *Options) *Client + // PoolSize applies per cluster node and not for the whole cluster. PoolSize int MinIdleConns int @@ -118,6 +122,10 @@ func (opt *ClusterOptions) init() { case 0: opt.MaxRetryBackoff = 512 * time.Millisecond } + + if opt.NewClient == nil { + opt.NewClient = NewClient + } } func (opt *ClusterOptions) clientOptions() *Options { @@ -130,6 +138,7 @@ func (opt *ClusterOptions) clientOptions() *Options { MaxRetries: opt.MaxRetries, MinRetryBackoff: opt.MinRetryBackoff, MaxRetryBackoff: opt.MaxRetryBackoff, + Username: opt.Username, Password: opt.Password, readOnly: opt.ReadOnly, @@ -162,7 +171,7 @@ func newClusterNode(clOpt *ClusterOptions, addr string) *clusterNode { opt := clOpt.clientOptions() opt.Addr = addr node := clusterNode{ - Client: NewClient(opt), + Client: clOpt.NewClient(opt), } node.latency = math.MaxUint32 diff --git a/backend/vendor/github.com/go-redis/redis/v7/command.go b/backend/vendor/github.com/go-redis/redis/v7/command.go index 266e3892..dd7fe4a9 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/command.go +++ b/backend/vendor/github.com/go-redis/redis/v7/command.go @@ -671,7 +671,7 @@ func (cmd *StringCmd) Time() (time.Time, error) { if cmd.err != nil { return time.Time{}, cmd.err } - return time.Parse(time.RFC3339, cmd.Val()) + return time.Parse(time.RFC3339Nano, cmd.Val()) } func (cmd *StringCmd) Scan(val interface{}) error { @@ -1885,6 +1885,7 @@ type CommandInfo struct { Name string Arity int8 Flags []string + ACLFlags []string FirstKeyPos int8 LastKeyPos int8 StepCount int8 @@ -1934,8 +1935,14 @@ func (cmd *CommandsInfoCmd) readReply(rd *proto.Reader) error { } func commandInfoParser(rd *proto.Reader, n int64) (interface{}, error) { - if n != 6 { - return nil, fmt.Errorf("redis: got %d elements in COMMAND reply, wanted 6", n) + const numArgRedis5 = 6 + const numArgRedis6 = 7 + + switch n { + case numArgRedis5, numArgRedis6: + // continue + default: + return nil, fmt.Errorf("redis: got %d elements in COMMAND reply, wanted 7", n) } var cmd CommandInfo @@ -1995,6 +2002,28 @@ func commandInfoParser(rd *proto.Reader, n int64) (interface{}, error) { } } + if n == numArgRedis5 { + return &cmd, nil + } + + _, err = rd.ReadReply(func(rd *proto.Reader, n int64) (interface{}, error) { + cmd.ACLFlags = make([]string, n) + for i := 0; i < len(cmd.ACLFlags); i++ { + switch s, err := rd.ReadString(); { + case err == Nil: + cmd.ACLFlags[i] = "" + case err != nil: + return nil, err + default: + cmd.ACLFlags[i] = s + } + } + return nil, nil + }) + if err != nil { + return nil, err + } + return &cmd, nil } diff --git a/backend/vendor/github.com/go-redis/redis/v7/commands.go b/backend/vendor/github.com/go-redis/redis/v7/commands.go index d4447c4d..da5ceda1 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/commands.go +++ b/backend/vendor/github.com/go-redis/redis/v7/commands.go @@ -302,6 +302,7 @@ type Cmdable interface { type StatefulCmdable interface { Cmdable Auth(password string) *StatusCmd + AuthACL(username, password string) *StatusCmd Select(index int) *StatusCmd SwapDB(index1, index2 int) *StatusCmd ClientSetName(name string) *BoolCmd @@ -324,6 +325,15 @@ func (c statefulCmdable) Auth(password string) *StatusCmd { return cmd } +// Perform an AUTH command, using the given user and pass. +// Should be used to authenticate the current connection with one of the connections defined in the ACL list +// when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system. +func (c statefulCmdable) AuthACL(username, password string) *StatusCmd { + cmd := NewStatusCmd("auth", username, password) + _ = c(cmd) + return cmd +} + func (c cmdable) Echo(message interface{}) *StringCmd { cmd := NewStringCmd("echo", message) _ = c(cmd) diff --git a/backend/vendor/github.com/go-redis/redis/v7/error.go b/backend/vendor/github.com/go-redis/redis/v7/error.go index a84c44f1..0ffaca9f 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/error.go +++ b/backend/vendor/github.com/go-redis/redis/v7/error.go @@ -6,9 +6,24 @@ import ( "net" "strings" + "github.com/go-redis/redis/v7/internal/pool" "github.com/go-redis/redis/v7/internal/proto" ) +var ErrClosed = pool.ErrClosed + +type Error interface { + error + + // RedisError is a no-op function but + // serves to distinguish types that are Redis + // errors from ordinary errors: a type is a + // Redis error if it has a RedisError method. + RedisError() +} + +var _ Error = proto.RedisError("") + func isRetryableError(err error, retryTimeout bool) bool { switch err { case nil, context.Canceled, context.DeadlineExceeded: diff --git a/backend/vendor/github.com/go-redis/redis/v7/internal/pool/pool.go b/backend/vendor/github.com/go-redis/redis/v7/internal/pool/pool.go index bbf5b300..a8d8276a 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/internal/pool/pool.go +++ b/backend/vendor/github.com/go-redis/redis/v7/internal/pool/pool.go @@ -94,7 +94,9 @@ func NewConnPool(opt *Options) *ConnPool { closedCh: make(chan struct{}), } + p.connsMu.Lock() p.checkMinIdleConns() + p.connsMu.Unlock() if opt.IdleTimeout > 0 && opt.IdleCheckFrequency > 0 { go p.reaper(opt.IdleCheckFrequency) diff --git a/backend/vendor/github.com/go-redis/redis/v7/internal/proto/reader.go b/backend/vendor/github.com/go-redis/redis/v7/internal/proto/reader.go index 24fc0bd8..d3f646e9 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/internal/proto/reader.go +++ b/backend/vendor/github.com/go-redis/redis/v7/internal/proto/reader.go @@ -24,6 +24,8 @@ type RedisError string func (e RedisError) Error() string { return string(e) } +func (RedisError) RedisError() {} + //------------------------------------------------------------------------------ type MultiBulkParse func(*Reader, int64) (interface{}, error) diff --git a/backend/vendor/github.com/go-redis/redis/v7/internal/proto/writer.go b/backend/vendor/github.com/go-redis/redis/v7/internal/proto/writer.go index cd83d658..d552f1e8 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/internal/proto/writer.go +++ b/backend/vendor/github.com/go-redis/redis/v7/internal/proto/writer.go @@ -93,7 +93,7 @@ func (w *Writer) writeArg(v interface{}) error { } return w.int(0) case time.Time: - return w.string(v.Format(time.RFC3339)) + return w.string(v.Format(time.RFC3339Nano)) case encoding.BinaryMarshaler: b, err := v.MarshalBinary() if err != nil { diff --git a/backend/vendor/github.com/go-redis/redis/v7/options.go b/backend/vendor/github.com/go-redis/redis/v7/options.go index 621d3a37..47dcc29b 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/options.go +++ b/backend/vendor/github.com/go-redis/redis/v7/options.go @@ -40,8 +40,13 @@ type Options struct { // Hook that is called when new connection is established. OnConnect func(*Conn) error + // Use the specified Username to authenticate the current connection with one of the connections defined in the ACL + // list when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system. + Username string + // Optional password. Must match the password specified in the - // requirepass server configuration option. + // requirepass server configuration option (if connecting to a Redis 5.0 instance, or lower), + // or the User Password when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system. Password string // Database to be selected after connecting to the server. DB int @@ -187,6 +192,7 @@ func ParseURL(redisURL string) (*Options, error) { } if u.User != nil { + o.Username = u.User.Username() if p, ok := u.User.Password(); ok { o.Password = p } diff --git a/backend/vendor/github.com/go-redis/redis/v7/pubsub.go b/backend/vendor/github.com/go-redis/redis/v7/pubsub.go index e1164093..26cde242 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/pubsub.go +++ b/backend/vendor/github.com/go-redis/redis/v7/pubsub.go @@ -309,9 +309,11 @@ func (c *PubSub) newMessage(reply interface{}) (interface{}, error) { case []interface{}: switch kind := reply[0].(string); kind { case "subscribe", "unsubscribe", "psubscribe", "punsubscribe": + // Can be nil in case of "unsubscribe". + channel, _ := reply[1].(string) return &Subscription{ Kind: kind, - Channel: reply[1].(string), + Channel: channel, Count: int(reply[2].(int64)), }, nil case "message": diff --git a/backend/vendor/github.com/go-redis/redis/v7/redis.go b/backend/vendor/github.com/go-redis/redis/v7/redis.go index 93032579..3d9dfed7 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/redis.go +++ b/backend/vendor/github.com/go-redis/redis/v7/redis.go @@ -241,7 +241,11 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error { _, err := conn.Pipelined(func(pipe Pipeliner) error { if c.opt.Password != "" { - pipe.Auth(c.opt.Password) + if c.opt.Username != "" { + pipe.AuthACL(c.opt.Username, c.opt.Password) + } else { + pipe.Auth(c.opt.Password) + } } if c.opt.DB > 0 { diff --git a/backend/vendor/github.com/go-redis/redis/v7/result.go b/backend/vendor/github.com/go-redis/redis/v7/result.go index 4b7de63a..5bec26ca 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/result.go +++ b/backend/vendor/github.com/go-redis/redis/v7/result.go @@ -98,6 +98,14 @@ func NewStringIntMapCmdResult(val map[string]int64, err error) *StringIntMapCmd return &cmd } +// NewTimeCmdResult returns a TimeCmd initialised with val and err for testing +func NewTimeCmdResult(val time.Time, err error) *TimeCmd { + var cmd TimeCmd + cmd.val = val + cmd.SetErr(err) + return &cmd +} + // NewZSliceCmdResult returns a ZSliceCmd initialised with val and err for testing func NewZSliceCmdResult(val []Z, err error) *ZSliceCmd { var cmd ZSliceCmd diff --git a/backend/vendor/github.com/go-redis/redis/v7/ring.go b/backend/vendor/github.com/go-redis/redis/v7/ring.go index e1b49917..44fc623f 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/ring.go +++ b/backend/vendor/github.com/go-redis/redis/v7/ring.go @@ -56,6 +56,9 @@ type RingOptions struct { // See https://arxiv.org/abs/1406.2294 for reference HashReplicas int + // NewClient creates a shard client with provided name and options. + NewClient func(name string, opt *Options) *Client + // Optional hook that is called when a new shard is created. OnNewShard func(*Client) @@ -390,7 +393,12 @@ func NewRing(opt *RingOptions) *Ring { func newRingShard(opt *RingOptions, name, addr string) *Client { clopt := opt.clientOptions(name) clopt.Addr = addr - shard := NewClient(clopt) + var shard *Client + if opt.NewClient != nil { + shard = opt.NewClient(name, clopt) + } else { + shard = NewClient(clopt) + } if opt.OnNewShard != nil { opt.OnNewShard(shard) } diff --git a/backend/vendor/github.com/go-redis/redis/v7/sentinel.go b/backend/vendor/github.com/go-redis/redis/v7/sentinel.go index 6487ef63..8aa40ef7 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/sentinel.go +++ b/backend/vendor/github.com/go-redis/redis/v7/sentinel.go @@ -22,6 +22,7 @@ type FailoverOptions struct { MasterName string // A seed list of host:port addresses of sentinel nodes. SentinelAddrs []string + SentinelUsername string SentinelPassword string // Following options are copied from Options struct. @@ -29,6 +30,7 @@ type FailoverOptions struct { Dialer func(ctx context.Context, network, addr string) (net.Conn, error) OnConnect func(*Conn) error + Username string Password string DB int @@ -57,6 +59,7 @@ func (opt *FailoverOptions) options() *Options { OnConnect: opt.OnConnect, DB: opt.DB, + Username: opt.Username, Password: opt.Password, MaxRetries: opt.MaxRetries, @@ -88,6 +91,7 @@ func NewFailoverClient(failoverOpt *FailoverOptions) *Client { failover := &sentinelFailover{ masterName: failoverOpt.MasterName, sentinelAddrs: failoverOpt.SentinelAddrs, + username: failoverOpt.SentinelUsername, password: failoverOpt.SentinelPassword, opt: opt, @@ -281,6 +285,7 @@ type sentinelFailover struct { sentinelAddrs []string opt *Options + username string password string pool *pool.ConnPool @@ -372,6 +377,7 @@ func (c *sentinelFailover) masterAddr() (string, error) { Addr: sentinelAddr, Dialer: c.opt.Dialer, + Username: c.username, Password: c.password, MaxRetries: c.opt.MaxRetries, diff --git a/backend/vendor/github.com/go-redis/redis/v7/universal.go b/backend/vendor/github.com/go-redis/redis/v7/universal.go index 21c4d07a..005ca682 100644 --- a/backend/vendor/github.com/go-redis/redis/v7/universal.go +++ b/backend/vendor/github.com/go-redis/redis/v7/universal.go @@ -22,6 +22,7 @@ type UniversalOptions struct { Dialer func(ctx context.Context, network, addr string) (net.Conn, error) OnConnect func(*Conn) error + Username string Password string MaxRetries int MinRetryBackoff time.Duration @@ -60,6 +61,7 @@ func (o *UniversalOptions) Cluster() *ClusterOptions { Dialer: o.Dialer, OnConnect: o.OnConnect, + Username: o.Username, Password: o.Password, MaxRedirects: o.MaxRedirects, @@ -99,6 +101,7 @@ func (o *UniversalOptions) Failover() *FailoverOptions { OnConnect: o.OnConnect, DB: o.DB, + Username: o.Username, Password: o.Password, MaxRetries: o.MaxRetries, @@ -133,6 +136,7 @@ func (o *UniversalOptions) Simple() *Options { OnConnect: o.OnConnect, DB: o.DB, + Username: o.Username, Password: o.Password, MaxRetries: o.MaxRetries, diff --git a/backend/vendor/github.com/google/uuid/README.md b/backend/vendor/github.com/google/uuid/README.md index 9d92c11f..f765a46f 100644 --- a/backend/vendor/github.com/google/uuid/README.md +++ b/backend/vendor/github.com/google/uuid/README.md @@ -16,4 +16,4 @@ change is the ability to represent an invalid UUID (vs a NIL UUID). Full `go doc` style documentation for the package can be viewed online without installing this package by using the GoDoc site here: -http://godoc.org/github.com/google/uuid +http://pkg.go.dev/github.com/google/uuid diff --git a/backend/vendor/github.com/google/uuid/marshal.go b/backend/vendor/github.com/google/uuid/marshal.go index 7f9e0c6c..14bd3407 100644 --- a/backend/vendor/github.com/google/uuid/marshal.go +++ b/backend/vendor/github.com/google/uuid/marshal.go @@ -16,10 +16,11 @@ func (uuid UUID) MarshalText() ([]byte, error) { // UnmarshalText implements encoding.TextUnmarshaler. func (uuid *UUID) UnmarshalText(data []byte) error { id, err := ParseBytes(data) - if err == nil { - *uuid = id + if err != nil { + return err } - return err + *uuid = id + return nil } // MarshalBinary implements encoding.BinaryMarshaler. diff --git a/backend/vendor/github.com/google/uuid/version1.go b/backend/vendor/github.com/google/uuid/version1.go index 199a1ac6..46310962 100644 --- a/backend/vendor/github.com/google/uuid/version1.go +++ b/backend/vendor/github.com/google/uuid/version1.go @@ -17,12 +17,6 @@ import ( // // In most cases, New should be used. func NewUUID() (UUID, error) { - nodeMu.Lock() - if nodeID == zeroID { - setNodeInterface("") - } - nodeMu.Unlock() - var uuid UUID now, seq, err := GetTime() if err != nil { @@ -38,7 +32,13 @@ func NewUUID() (UUID, error) { binary.BigEndian.PutUint16(uuid[4:], timeMid) binary.BigEndian.PutUint16(uuid[6:], timeHi) binary.BigEndian.PutUint16(uuid[8:], seq) + + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } copy(uuid[10:], nodeID[:]) + nodeMu.Unlock() return uuid, nil } diff --git a/backend/vendor/github.com/google/uuid/version4.go b/backend/vendor/github.com/google/uuid/version4.go index 84af91c9..c110465d 100644 --- a/backend/vendor/github.com/google/uuid/version4.go +++ b/backend/vendor/github.com/google/uuid/version4.go @@ -27,8 +27,13 @@ func New() UUID { // equivalent to the odds of creating a few tens of trillions of UUIDs in a // year and having one duplicate. func NewRandom() (UUID, error) { + return NewRandomFromReader(rander) +} + +// NewRandomFromReader returns a UUID based on bytes read from a given io.Reader. +func NewRandomFromReader(r io.Reader) (UUID, error) { var uuid UUID - _, err := io.ReadFull(rander, uuid[:]) + _, err := io.ReadFull(r, uuid[:]) if err != nil { return Nil, err } diff --git a/backend/vendor/github.com/russross/blackfriday/v2/README.md b/backend/vendor/github.com/russross/blackfriday/v2/README.md index d5a8649b..d9c08a22 100644 --- a/backend/vendor/github.com/russross/blackfriday/v2/README.md +++ b/backend/vendor/github.com/russross/blackfriday/v2/README.md @@ -1,4 +1,6 @@ -Blackfriday [![Build Status](https://travis-ci.org/russross/blackfriday.svg?branch=master)](https://travis-ci.org/russross/blackfriday) +Blackfriday +[![Build Status][BuildV2SVG]][BuildV2URL] +[![PkgGoDev][PkgGoDevV2SVG]][PkgGoDevV2URL] =========== Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It @@ -16,19 +18,21 @@ It started as a translation from C of [Sundown][3]. Installation ------------ -Blackfriday is compatible with any modern Go release. With Go 1.7 and git -installed: +Blackfriday is compatible with modern Go releases in module mode. +With Go installed: - go get gopkg.in/russross/blackfriday.v2 + go get github.com/russross/blackfriday/v2 -will download, compile, and install the package into your `$GOPATH` -directory hierarchy. Alternatively, you can achieve the same if you -import it into a project: +will resolve and add the package to the current development module, +then build and install it. Alternatively, you can achieve the same +if you import it in a package: - import "gopkg.in/russross/blackfriday.v2" + import "github.com/russross/blackfriday/v2" and `go get` without parameters. +Legacy GOPATH mode is unsupported. + Versions -------- @@ -36,13 +40,9 @@ 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. +https://pkg.go.dev/github.com/russross/blackfriday/v2. -It is `go get`-able via 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. +It is `go get`-able in module mode at `github.com/russross/blackfriday/v2`. Version 2 offers a number of improvements over v1: @@ -62,6 +62,11 @@ Potential drawbacks: 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://pkg.go.dev/github.com/russross/blackfriday. + + Usage ----- @@ -91,7 +96,7 @@ Here's an example of simple usage of Blackfriday together with Bluemonday: ```go import ( "github.com/microcosm-cc/bluemonday" - "github.com/russross/blackfriday" + "github.com/russross/blackfriday/v2" ) // ... @@ -104,6 +109,8 @@ html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) 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: @@ -114,7 +121,7 @@ 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 @@ -123,6 +130,22 @@ 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 `AutoHeadingIDs` extension 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://pkg.go.dev/github.com/russross/blackfriday/v2#hdr-Sanitized_Anchor_Names. + +[`SanitizedAnchorName`](https://pkg.go.dev/github.com/russross/blackfriday/v2#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://pkg.go.dev/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 -------- @@ -199,6 +222,15 @@ implements the following extensions: 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. @@ -250,7 +282,7 @@ 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): +* [github_flavored_markdown](https://pkg.go.dev/github.com/shurcooL/github_flavored_markdown): provides a GitHub Flavored Markdown renderer with fenced code block highlighting, clickable heading anchor links. @@ -261,20 +293,28 @@ are a few of note: * [markdownfmt](https://github.com/shurcooL/markdownfmt): like gofmt, but for markdown. -* [LaTeX output](https://github.com/Ambrevar/Blackfriday-LaTeX): +* [LaTeX output](https://gitlab.com/ambrevar/blackfriday-latex): renders output as LaTeX. +* [bfchroma](https://github.com/Depado/bfchroma/): provides convenience + integration with the [Chroma](https://github.com/alecthomas/chroma) code + highlighting library. bfchroma is only compatible with v2 of Blackfriday and + provides a drop-in renderer ready to use with Blackfriday, as well as + options and means for further customization. + * [Blackfriday-Confluence](https://github.com/kentaro-m/blackfriday-confluence): provides a [Confluence Wiki Markup](https://confluence.atlassian.com/doc/confluence-wiki-markup-251003035.html) renderer. +* [Blackfriday-Slack](https://github.com/karriereat/blackfriday-slack): converts markdown to slack message style -Todo + +TODO ---- * More unit testing -* Improve unicode support. It does not understand all unicode +* 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. + some instances. It is safe on all UTF-8 input. License @@ -286,6 +326,10 @@ License [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" + [4]: https://pkg.go.dev/github.com/russross/blackfriday/v2#Parse "Parse func" [5]: https://github.com/microcosm-cc/bluemonday "Bluemonday" - [6]: https://labix.org/gopkg.in "gopkg.in" + + [BuildV2SVG]: https://travis-ci.org/russross/blackfriday.svg?branch=v2 + [BuildV2URL]: https://travis-ci.org/russross/blackfriday + [PkgGoDevV2SVG]: https://pkg.go.dev/badge/github.com/russross/blackfriday/v2 + [PkgGoDevV2URL]: https://pkg.go.dev/github.com/russross/blackfriday/v2 diff --git a/backend/vendor/github.com/russross/blackfriday/v2/block.go b/backend/vendor/github.com/russross/blackfriday/v2/block.go index b8607474..dcd61e6e 100644 --- a/backend/vendor/github.com/russross/blackfriday/v2/block.go +++ b/backend/vendor/github.com/russross/blackfriday/v2/block.go @@ -18,8 +18,7 @@ import ( "html" "regexp" "strings" - - "github.com/shurcooL/sanitized_anchor_name" + "unicode" ) const ( @@ -259,7 +258,7 @@ func (p *Markdown) prefixHeading(data []byte) int { } if end > i { if id == "" && p.extensions&AutoHeadingIDs != 0 { - id = sanitized_anchor_name.Create(string(data[i:end])) + id = SanitizedAnchorName(string(data[i:end])) } block := p.addBlock(Heading, data[i:end]) block.HeadingID = id @@ -673,6 +672,7 @@ func (p *Markdown) fencedCodeBlock(data []byte, doRender bool) int { if beg == 0 || beg >= len(data) { return 0 } + fenceLength := beg - 1 var work bytes.Buffer work.Write([]byte(info)) @@ -706,6 +706,7 @@ func (p *Markdown) fencedCodeBlock(data []byte, doRender bool) int { if doRender { block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer block.IsFenced = true + block.FenceLength = fenceLength finalizeCodeBlock(block) } @@ -1503,7 +1504,7 @@ func (p *Markdown) paragraph(data []byte) int { id := "" if p.extensions&AutoHeadingIDs != 0 { - id = sanitized_anchor_name.Create(string(data[prev:eol])) + id = SanitizedAnchorName(string(data[prev:eol])) } block := p.addBlock(Heading, data[prev:eol]) @@ -1588,3 +1589,24 @@ func skipUntilChar(text []byte, start int, char byte) int { } return i } + +// SanitizedAnchorName returns a sanitized anchor name for the given text. +// +// It implements the algorithm specified in the package comment. +func SanitizedAnchorName(text string) string { + var anchorName []rune + futureDash := false + for _, r := range text { + switch { + case unicode.IsLetter(r) || unicode.IsNumber(r): + if futureDash && len(anchorName) > 0 { + anchorName = append(anchorName, '-') + } + futureDash = false + anchorName = append(anchorName, unicode.ToLower(r)) + default: + futureDash = true + } + } + return string(anchorName) +} diff --git a/backend/vendor/github.com/russross/blackfriday/v2/doc.go b/backend/vendor/github.com/russross/blackfriday/v2/doc.go index 5b3fa987..57ff152a 100644 --- a/backend/vendor/github.com/russross/blackfriday/v2/doc.go +++ b/backend/vendor/github.com/russross/blackfriday/v2/doc.go @@ -15,4 +15,32 @@ // // If you're interested in calling Blackfriday from command line, see // https://github.com/russross/blackfriday-tool. +// +// 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 AutoHeadingIDs extension is enabled. The +// algorithm is specified below, so that other packages can create +// compatible anchor names and links to those anchors. +// +// The algorithm iterates over the input text, interpreted as UTF-8, +// one Unicode code point (rune) at a time. All runes that are letters (category L) +// or numbers (category N) are considered valid characters. They are mapped to +// lower case, and included in the output. All other runes are considered +// invalid characters. Invalid characters that precede the first valid character, +// as well as invalid character that follow the last valid character +// are dropped completely. All other sequences of invalid characters +// between two valid characters are replaced with a single dash character '-'. +// +// 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. It can be useful for clients +// that want a small package and don't need full functionality of blackfriday. package blackfriday + +// NOTE: Keep Sanitized Anchor Name algorithm in sync with package +// github.com/shurcooL/sanitized_anchor_name. +// Otherwise, users of sanitized_anchor_name will get anchor names +// that are incompatible with those generated by blackfriday. diff --git a/backend/vendor/github.com/russross/blackfriday/v2/entities.go b/backend/vendor/github.com/russross/blackfriday/v2/entities.go new file mode 100644 index 00000000..a2c3edb6 --- /dev/null +++ b/backend/vendor/github.com/russross/blackfriday/v2/entities.go @@ -0,0 +1,2236 @@ +package blackfriday + +// Extracted from https://html.spec.whatwg.org/multipage/entities.json +var entities = map[string]bool{ + "Æ": true, + "Æ": true, + "&": true, + "&": true, + "Á": true, + "Á": true, + "Ă": true, + "Â": true, + "Â": true, + "А": true, + "𝔄": true, + "À": true, + "À": true, + "Α": true, + "Ā": true, + "⩓": true, + "Ą": true, + "𝔸": true, + "⁡": true, + "Å": true, + "Å": true, + "𝒜": true, + "≔": true, + "Ã": true, + "Ã": true, + "Ä": true, + "Ä": true, + "∖": true, + "⫧": true, + "⌆": true, + "Б": true, + "∵": true, + "ℬ": true, + "Β": true, + "𝔅": true, + "𝔹": true, + "˘": true, + "ℬ": true, + "≎": true, + "Ч": true, + "©": true, + "©": true, + "Ć": true, + "⋒": true, + "ⅅ": true, + "ℭ": true, + "Č": true, + "Ç": true, + "Ç": true, + "Ĉ": true, + "∰": true, + "Ċ": true, + "¸": true, + "·": true, + "ℭ": true, + "Χ": true, + "⊙": true, + "⊖": true, + "⊕": true, + "⊗": true, + "∲": true, + "”": true, + "’": true, + "∷": true, + "⩴": true, + "≡": true, + "∯": true, + "∮": true, + "ℂ": true, + "∐": true, + "∳": true, + "⨯": true, + "𝒞": true, + "⋓": true, + "≍": true, + "ⅅ": true, + "⤑": true, + "Ђ": true, + "Ѕ": true, + "Џ": true, + "‡": true, + "↡": true, + "⫤": true, + "Ď": true, + "Д": true, + "∇": true, + "Δ": true, + "𝔇": true, + "´": true, + "˙": true, + "˝": true, + "`": true, + "˜": true, + "⋄": true, + "ⅆ": true, + "𝔻": true, + "¨": true, + "⃜": true, + "≐": true, + "∯": true, + "¨": true, + "⇓": true, + "⇐": true, + "⇔": true, + "⫤": true, + "⟸": true, + "⟺": true, + "⟹": true, + "⇒": true, + "⊨": true, + "⇑": true, + "⇕": true, + "∥": true, + "↓": true, + "⤓": true, + "⇵": true, + "̑": true, + "⥐": true, + "⥞": true, + "↽": true, + "⥖": true, + "⥟": true, + "⇁": true, + "⥗": true, + "⊤": true, + "↧": true, + "⇓": true, + "𝒟": true, + "Đ": true, + "Ŋ": true, + "Ð": true, + "Ð": true, + "É": true, + "É": true, + "Ě": true, + "Ê": true, + "Ê": true, + "Э": true, + "Ė": true, + "𝔈": true, + "È": true, + "È": true, + "∈": true, + "Ē": true, + "◻": true, + "▫": true, + "Ę": true, + "𝔼": true, + "Ε": true, + "⩵": true, + "≂": true, + "⇌": true, + "ℰ": true, + "⩳": true, + "Η": true, + "Ë": true, + "Ë": true, + "∃": true, + "ⅇ": true, + "Ф": true, + "𝔉": true, + "◼": true, + "▪": true, + "𝔽": true, + "∀": true, + "ℱ": true, + "ℱ": true, + "Ѓ": true, + ">": true, + ">": true, + "Γ": true, + "Ϝ": true, + "Ğ": true, + "Ģ": true, + "Ĝ": true, + "Г": true, + "Ġ": true, + "𝔊": true, + "⋙": true, + "𝔾": true, + "≥": true, + "⋛": true, + "≧": true, + "⪢": true, + "≷": true, + "⩾": true, + "≳": true, + "𝒢": true, + "≫": true, + "Ъ": true, + "ˇ": true, + "^": true, + "Ĥ": true, + "ℌ": true, + "ℋ": true, + "ℍ": true, + "─": true, + "ℋ": true, + "Ħ": true, + "≎": true, + "≏": true, + "Е": true, + "IJ": true, + "Ё": true, + "Í": true, + "Í": true, + "Î": true, + "Î": true, + "И": true, + "İ": true, + "ℑ": true, + "Ì": true, + "Ì": true, + "ℑ": true, + "Ī": true, + "ⅈ": true, + "⇒": true, + "∬": true, + "∫": true, + "⋂": true, + "⁣": true, + "⁢": true, + "Į": true, + "𝕀": true, + "Ι": true, + "ℐ": true, + "Ĩ": true, + "І": true, + "Ï": true, + "Ï": true, + "Ĵ": true, + "Й": true, + "𝔍": true, + "𝕁": true, + "𝒥": true, + "Ј": true, + "Є": true, + "Х": true, + "Ќ": true, + "Κ": true, + "Ķ": true, + "К": true, + "𝔎": true, + "𝕂": true, + "𝒦": true, + "Љ": true, + "<": true, + "<": true, + "Ĺ": true, + "Λ": true, + "⟪": true, + "ℒ": true, + "↞": true, + "Ľ": true, + "Ļ": true, + "Л": true, + "⟨": true, + "←": true, + "⇤": true, + "⇆": true, + "⌈": true, + "⟦": true, + "⥡": true, + "⇃": true, + "⥙": true, + "⌊": true, + "↔": true, + "⥎": true, + "⊣": true, + "↤": true, + "⥚": true, + "⊲": true, + "⧏": true, + "⊴": true, + "⥑": true, + "⥠": true, + "↿": true, + "⥘": true, + "↼": true, + "⥒": true, + "⇐": true, + "⇔": true, + "⋚": true, + "≦": true, + "≶": true, + "⪡": true, + "⩽": true, + "≲": true, + "𝔏": true, + "⋘": true, + "⇚": true, + "Ŀ": true, + "⟵": true, + "⟷": true, + "⟶": true, + "⟸": true, + "⟺": true, + "⟹": true, + "𝕃": true, + "↙": true, + "↘": true, + "ℒ": true, + "↰": true, + "Ł": true, + "≪": true, + "⤅": true, + "М": true, + " ": true, + "ℳ": true, + "𝔐": true, + "∓": true, + "𝕄": true, + "ℳ": true, + "Μ": true, + "Њ": true, + "Ń": true, + "Ň": true, + "Ņ": true, + "Н": true, + "​": true, + "​": true, + "​": true, + "​": true, + "≫": true, + "≪": true, + " ": true, + "𝔑": true, + "⁠": true, + " ": true, + "ℕ": true, + "⫬": true, + "≢": true, + "≭": true, + "∦": true, + "∉": true, + "≠": true, + "≂̸": true, + "∄": true, + "≯": true, + "≱": true, + "≧̸": true, + "≫̸": true, + "≹": true, + "⩾̸": true, + "≵": true, + "≎̸": true, + "≏̸": true, + "⋪": true, + "⧏̸": true, + "⋬": true, + "≮": true, + "≰": true, + "≸": true, + "≪̸": true, + "⩽̸": true, + "≴": true, + "⪢̸": true, + "⪡̸": true, + "⊀": true, + "⪯̸": true, + "⋠": true, + "∌": true, + "⋫": true, + "⧐̸": true, + "⋭": true, + "⊏̸": true, + "⋢": true, + "⊐̸": true, + "⋣": true, + "⊂⃒": true, + "⊈": true, + "⊁": true, + "⪰̸": true, + "⋡": true, + "≿̸": true, + "⊃⃒": true, + "⊉": true, + "≁": true, + "≄": true, + "≇": true, + "≉": true, + "∤": true, + "𝒩": true, + "Ñ": true, + "Ñ": true, + "Ν": true, + "Œ": true, + "Ó": true, + "Ó": true, + "Ô": true, + "Ô": true, + "О": true, + "Ő": true, + "𝔒": true, + "Ò": true, + "Ò": true, + "Ō": true, + "Ω": true, + "Ο": true, + "𝕆": true, + "“": true, + "‘": true, + "⩔": true, + "𝒪": true, + "Ø": true, + "Ø": true, + "Õ": true, + "Õ": true, + "⨷": true, + "Ö": true, + "Ö": true, + "‾": true, + "⏞": true, + "⎴": true, + "⏜": true, + "∂": true, + "П": true, + "𝔓": true, + "Φ": true, + "Π": true, + "±": true, + "ℌ": true, + "ℙ": true, + "⪻": true, + "≺": true, + "⪯": true, + "≼": true, + "≾": true, + "″": true, + "∏": true, + "∷": true, + "∝": true, + "𝒫": true, + "Ψ": true, + """: true, + """: true, + "𝔔": true, + "ℚ": true, + "𝒬": true, + "⤐": true, + "®": true, + "®": true, + "Ŕ": true, + "⟫": true, + "↠": true, + "⤖": true, + "Ř": true, + "Ŗ": true, + "Р": true, + "ℜ": true, + "∋": true, + "⇋": true, + "⥯": true, + "ℜ": true, + "Ρ": true, + "⟩": true, + "→": true, + "⇥": true, + "⇄": true, + "⌉": true, + "⟧": true, + "⥝": true, + "⇂": true, + "⥕": true, + "⌋": true, + "⊢": true, + "↦": true, + "⥛": true, + "⊳": true, + "⧐": true, + "⊵": true, + "⥏": true, + "⥜": true, + "↾": true, + "⥔": true, + "⇀": true, + "⥓": true, + "⇒": true, + "ℝ": true, + "⥰": true, + "⇛": true, + "ℛ": true, + "↱": true, + "⧴": true, + "Щ": true, + "Ш": true, + "Ь": true, + "Ś": true, + "⪼": true, + "Š": true, + "Ş": true, + "Ŝ": true, + "С": true, + "𝔖": true, + "↓": true, + "←": true, + "→": true, + "↑": true, + "Σ": true, + "∘": true, + "𝕊": true, + "√": true, + "□": true, + "⊓": true, + "⊏": true, + "⊑": true, + "⊐": true, + "⊒": true, + "⊔": true, + "𝒮": true, + "⋆": true, + "⋐": true, + "⋐": true, + "⊆": true, + "≻": true, + "⪰": true, + "≽": true, + "≿": true, + "∋": true, + "∑": true, + "⋑": true, + "⊃": true, + "⊇": true, + "⋑": true, + "Þ": true, + "Þ": true, + "™": true, + "Ћ": true, + "Ц": true, + " ": true, + "Τ": true, + "Ť": true, + "Ţ": true, + "Т": true, + "𝔗": true, + "∴": true, + "Θ": true, + "  ": true, + " ": true, + "∼": true, + "≃": true, + "≅": true, + "≈": true, + "𝕋": true, + "⃛": true, + "𝒯": true, + "Ŧ": true, + "Ú": true, + "Ú": true, + "↟": true, + "⥉": true, + "Ў": true, + "Ŭ": true, + "Û": true, + "Û": true, + "У": true, + "Ű": true, + "𝔘": true, + "Ù": true, + "Ù": true, + "Ū": true, + "_": true, + "⏟": true, + "⎵": true, + "⏝": true, + "⋃": true, + "⊎": true, + "Ų": true, + "𝕌": true, + "↑": true, + "⤒": true, + "⇅": true, + "↕": true, + "⥮": true, + "⊥": true, + "↥": true, + "⇑": true, + "⇕": true, + "↖": true, + "↗": true, + "ϒ": true, + "Υ": true, + "Ů": true, + "𝒰": true, + "Ũ": true, + "Ü": true, + "Ü": true, + "⊫": true, + "⫫": true, + "В": true, + "⊩": true, + "⫦": true, + "⋁": true, + "‖": true, + "‖": true, + "∣": true, + "|": true, + "❘": true, + "≀": true, + " ": true, + "𝔙": true, + "𝕍": true, + "𝒱": true, + "⊪": true, + "Ŵ": true, + "⋀": true, + "𝔚": true, + "𝕎": true, + "𝒲": true, + "𝔛": true, + "Ξ": true, + "𝕏": true, + "𝒳": true, + "Я": true, + "Ї": true, + "Ю": true, + "Ý": true, + "Ý": true, + "Ŷ": true, + "Ы": true, + "𝔜": true, + "𝕐": true, + "𝒴": true, + "Ÿ": true, + "Ж": true, + "Ź": true, + "Ž": true, + "З": true, + "Ż": true, + "​": true, + "Ζ": true, + "ℨ": true, + "ℤ": true, + "𝒵": true, + "á": true, + "á": true, + "ă": true, + "∾": true, + "∾̳": true, + "∿": true, + "â": true, + "â": true, + "´": true, + "´": true, + "а": true, + "æ": true, + "æ": true, + "⁡": true, + "𝔞": true, + "à": true, + "à": true, + "ℵ": true, + "ℵ": true, + "α": true, + "ā": true, + "⨿": true, + "&": true, + "&": true, + "∧": true, + "⩕": true, + "⩜": true, + "⩘": true, + "⩚": true, + "∠": true, + "⦤": true, + "∠": true, + "∡": true, + "⦨": true, + "⦩": true, + "⦪": true, + "⦫": true, + "⦬": true, + "⦭": true, + "⦮": true, + "⦯": true, + "∟": true, + "⊾": true, + "⦝": true, + "∢": true, + "Å": true, + "⍼": true, + "ą": true, + "𝕒": true, + "≈": true, + "⩰": true, + "⩯": true, + "≊": true, + "≋": true, + "'": true, + "≈": true, + "≊": true, + "å": true, + "å": true, + "𝒶": true, + "*": true, + "≈": true, + "≍": true, + "ã": true, + "ã": true, + "ä": true, + "ä": true, + "∳": true, + "⨑": true, + "⫭": true, + "≌": true, + "϶": true, + "‵": true, + "∽": true, + "⋍": true, + "⊽": true, + "⌅": true, + "⌅": true, + "⎵": true, + "⎶": true, + "≌": true, + "б": true, + "„": true, + "∵": true, + "∵": true, + "⦰": true, + "϶": true, + "ℬ": true, + "β": true, + "ℶ": true, + "≬": true, + "𝔟": true, + "⋂": true, + "◯": true, + "⋃": true, + "⨀": true, + "⨁": true, + "⨂": true, + "⨆": true, + "★": true, + "▽": true, + "△": true, + "⨄": true, + "⋁": true, + "⋀": true, + "⤍": true, + "⧫": true, + "▪": true, + "▴": true, + "▾": true, + "◂": true, + "▸": true, + "␣": true, + "▒": true, + "░": true, + "▓": true, + "█": true, + "=⃥": true, + "≡⃥": true, + "⌐": true, + "𝕓": true, + "⊥": true, + "⊥": true, + "⋈": true, + "╗": true, + "╔": true, + "╖": true, + "╓": true, + "═": true, + "╦": true, + "╩": true, + "╤": true, + "╧": true, + "╝": true, + "╚": true, + "╜": true, + "╙": true, + "║": true, + "╬": true, + "╣": true, + "╠": true, + "╫": true, + "╢": true, + "╟": true, + "⧉": true, + "╕": true, + "╒": true, + "┐": true, + "┌": true, + "─": true, + "╥": true, + "╨": true, + "┬": true, + "┴": true, + "⊟": true, + "⊞": true, + "⊠": true, + "╛": true, + "╘": true, + "┘": true, + "└": true, + "│": true, + "╪": true, + "╡": true, + "╞": true, + "┼": true, + "┤": true, + "├": true, + "‵": true, + "˘": true, + "¦": true, + "¦": true, + "𝒷": true, + "⁏": true, + "∽": true, + "⋍": true, + "\": true, + "⧅": true, + "⟈": true, + "•": true, + "•": true, + "≎": true, + "⪮": true, + "≏": true, + "≏": true, + "ć": true, + "∩": true, + "⩄": true, + "⩉": true, + "⩋": true, + "⩇": true, + "⩀": true, + "∩︀": true, + "⁁": true, + "ˇ": true, + "⩍": true, + "č": true, + "ç": true, + "ç": true, + "ĉ": true, + "⩌": true, + "⩐": true, + "ċ": true, + "¸": true, + "¸": true, + "⦲": true, + "¢": true, + "¢": true, + "·": true, + "𝔠": true, + "ч": true, + "✓": true, + "✓": true, + "χ": true, + "○": true, + "⧃": true, + "ˆ": true, + "≗": true, + "↺": true, + "↻": true, + "®": true, + "Ⓢ": true, + "⊛": true, + "⊚": true, + "⊝": true, + "≗": true, + "⨐": true, + "⫯": true, + "⧂": true, + "♣": true, + "♣": true, + ":": true, + "≔": true, + "≔": true, + ",": true, + "@": true, + "∁": true, + "∘": true, + "∁": true, + "ℂ": true, + "≅": true, + "⩭": true, + "∮": true, + "𝕔": true, + "∐": true, + "©": true, + "©": true, + "℗": true, + "↵": true, + "✗": true, + "𝒸": true, + "⫏": true, + "⫑": true, + "⫐": true, + "⫒": true, + "⋯": true, + "⤸": true, + "⤵": true, + "⋞": true, + "⋟": true, + "↶": true, + "⤽": true, + "∪": true, + "⩈": true, + "⩆": true, + "⩊": true, + "⊍": true, + "⩅": true, + "∪︀": true, + "↷": true, + "⤼": true, + "⋞": true, + "⋟": true, + "⋎": true, + "⋏": true, + "¤": true, + "¤": true, + "↶": true, + "↷": true, + "⋎": true, + "⋏": true, + "∲": true, + "∱": true, + "⌭": true, + "⇓": true, + "⥥": true, + "†": true, + "ℸ": true, + "↓": true, + "‐": true, + "⊣": true, + "⤏": true, + "˝": true, + "ď": true, + "д": true, + "ⅆ": true, + "‡": true, + "⇊": true, + "⩷": true, + "°": true, + "°": true, + "δ": true, + "⦱": true, + "⥿": true, + "𝔡": true, + "⇃": true, + "⇂": true, + "⋄": true, + "⋄": true, + "♦": true, + "♦": true, + "¨": true, + "ϝ": true, + "⋲": true, + "÷": true, + "÷": true, + "÷": true, + "⋇": true, + "⋇": true, + "ђ": true, + "⌞": true, + "⌍": true, + "$": true, + "𝕕": true, + "˙": true, + "≐": true, + "≑": true, + "∸": true, + "∔": true, + "⊡": true, + "⌆": true, + "↓": true, + "⇊": true, + "⇃": true, + "⇂": true, + "⤐": true, + "⌟": true, + "⌌": true, + "𝒹": true, + "ѕ": true, + "⧶": true, + "đ": true, + "⋱": true, + "▿": true, + "▾": true, + "⇵": true, + "⥯": true, + "⦦": true, + "џ": true, + "⟿": true, + "⩷": true, + "≑": true, + "é": true, + "é": true, + "⩮": true, + "ě": true, + "≖": true, + "ê": true, + "ê": true, + "≕": true, + "э": true, + "ė": true, + "ⅇ": true, + "≒": true, + "𝔢": true, + "⪚": true, + "è": true, + "è": true, + "⪖": true, + "⪘": true, + "⪙": true, + "⏧": true, + "ℓ": true, + "⪕": true, + "⪗": true, + "ē": true, + "∅": true, + "∅": true, + "∅": true, + " ": true, + " ": true, + " ": true, + "ŋ": true, + " ": true, + "ę": true, + "𝕖": true, + "⋕": true, + "⧣": true, + "⩱": true, + "ε": true, + "ε": true, + "ϵ": true, + "≖": true, + "≕": true, + "≂": true, + "⪖": true, + "⪕": true, + "=": true, + "≟": true, + "≡": true, + "⩸": true, + "⧥": true, + "≓": true, + "⥱": true, + "ℯ": true, + "≐": true, + "≂": true, + "η": true, + "ð": true, + "ð": true, + "ë": true, + "ë": true, + "€": true, + "!": true, + "∃": true, + "ℰ": true, + "ⅇ": true, + "≒": true, + "ф": true, + "♀": true, + "ffi": true, + "ff": true, + "ffl": true, + "𝔣": true, + "fi": true, + "fj": true, + "♭": true, + "fl": true, + "▱": true, + "ƒ": true, + "𝕗": true, + "∀": true, + "⋔": true, + "⫙": true, + "⨍": true, + "½": true, + "½": true, + "⅓": true, + "¼": true, + "¼": true, + "⅕": true, + "⅙": true, + "⅛": true, + "⅔": true, + "⅖": true, + "¾": true, + "¾": true, + "⅗": true, + "⅜": true, + "⅘": true, + "⅚": true, + "⅝": true, + "⅞": true, + "⁄": true, + "⌢": true, + "𝒻": true, + "≧": true, + "⪌": true, + "ǵ": true, + "γ": true, + "ϝ": true, + "⪆": true, + "ğ": true, + "ĝ": true, + "г": true, + "ġ": true, + "≥": true, + "⋛": true, + "≥": true, + "≧": true, + "⩾": true, + "⩾": true, + "⪩": true, + "⪀": true, + "⪂": true, + "⪄": true, + "⋛︀": true, + "⪔": true, + "𝔤": true, + "≫": true, + "⋙": true, + "ℷ": true, + "ѓ": true, + "≷": true, + "⪒": true, + "⪥": true, + "⪤": true, + "≩": true, + "⪊": true, + "⪊": true, + "⪈": true, + "⪈": true, + "≩": true, + "⋧": true, + "𝕘": true, + "`": true, + "ℊ": true, + "≳": true, + "⪎": true, + "⪐": true, + ">": true, + ">": true, + "⪧": true, + "⩺": true, + "⋗": true, + "⦕": true, + "⩼": true, + "⪆": true, + "⥸": true, + "⋗": true, + "⋛": true, + "⪌": true, + "≷": true, + "≳": true, + "≩︀": true, + "≩︀": true, + "⇔": true, + " ": true, + "½": true, + "ℋ": true, + "ъ": true, + "↔": true, + "⥈": true, + "↭": true, + "ℏ": true, + "ĥ": true, + "♥": true, + "♥": true, + "…": true, + "⊹": true, + "𝔥": true, + "⤥": true, + "⤦": true, + "⇿": true, + "∻": true, + "↩": true, + "↪": true, + "𝕙": true, + "―": true, + "𝒽": true, + "ℏ": true, + "ħ": true, + "⁃": true, + "‐": true, + "í": true, + "í": true, + "⁣": true, + "î": true, + "î": true, + "и": true, + "е": true, + "¡": true, + "¡": true, + "⇔": true, + "𝔦": true, + "ì": true, + "ì": true, + "ⅈ": true, + "⨌": true, + "∭": true, + "⧜": true, + "℩": true, + "ij": true, + "ī": true, + "ℑ": true, + "ℐ": true, + "ℑ": true, + "ı": true, + "⊷": true, + "Ƶ": true, + "∈": true, + "℅": true, + "∞": true, + "⧝": true, + "ı": true, + "∫": true, + "⊺": true, + "ℤ": true, + "⊺": true, + "⨗": true, + "⨼": true, + "ё": true, + "į": true, + "𝕚": true, + "ι": true, + "⨼": true, + "¿": true, + "¿": true, + "𝒾": true, + "∈": true, + "⋹": true, + "⋵": true, + "⋴": true, + "⋳": true, + "∈": true, + "⁢": true, + "ĩ": true, + "і": true, + "ï": true, + "ï": true, + "ĵ": true, + "й": true, + "𝔧": true, + "ȷ": true, + "𝕛": true, + "𝒿": true, + "ј": true, + "є": true, + "κ": true, + "ϰ": true, + "ķ": true, + "к": true, + "𝔨": true, + "ĸ": true, + "х": true, + "ќ": true, + "𝕜": true, + "𝓀": true, + "⇚": true, + "⇐": true, + "⤛": true, + "⤎": true, + "≦": true, + "⪋": true, + "⥢": true, + "ĺ": true, + "⦴": true, + "ℒ": true, + "λ": true, + "⟨": true, + "⦑": true, + "⟨": true, + "⪅": true, + "«": true, + "«": true, + "←": true, + "⇤": true, + "⤟": true, + "⤝": true, + "↩": true, + "↫": true, + "⤹": true, + "⥳": true, + "↢": true, + "⪫": true, + "⤙": true, + "⪭": true, + "⪭︀": true, + "⤌": true, + "❲": true, + "{": true, + "[": true, + "⦋": true, + "⦏": true, + "⦍": true, + "ľ": true, + "ļ": true, + "⌈": true, + "{": true, + "л": true, + "⤶": true, + "“": true, + "„": true, + "⥧": true, + "⥋": true, + "↲": true, + "≤": true, + "←": true, + "↢": true, + "↽": true, + "↼": true, + "⇇": true, + "↔": true, + "⇆": true, + "⇋": true, + "↭": true, + "⋋": true, + "⋚": true, + "≤": true, + "≦": true, + "⩽": true, + "⩽": true, + "⪨": true, + "⩿": true, + "⪁": true, + "⪃": true, + "⋚︀": true, + "⪓": true, + "⪅": true, + "⋖": true, + "⋚": true, + "⪋": true, + "≶": true, + "≲": true, + "⥼": true, + "⌊": true, + "𝔩": true, + "≶": true, + "⪑": true, + "↽": true, + "↼": true, + "⥪": true, + "▄": true, + "љ": true, + "≪": true, + "⇇": true, + "⌞": true, + "⥫": true, + "◺": true, + "ŀ": true, + "⎰": true, + "⎰": true, + "≨": true, + "⪉": true, + "⪉": true, + "⪇": true, + "⪇": true, + "≨": true, + "⋦": true, + "⟬": true, + "⇽": true, + "⟦": true, + "⟵": true, + "⟷": true, + "⟼": true, + "⟶": true, + "↫": true, + "↬": true, + "⦅": true, + "𝕝": true, + "⨭": true, + "⨴": true, + "∗": true, + "_": true, + "◊": true, + "◊": true, + "⧫": true, + "(": true, + "⦓": true, + "⇆": true, + "⌟": true, + "⇋": true, + "⥭": true, + "‎": true, + "⊿": true, + "‹": true, + "𝓁": true, + "↰": true, + "≲": true, + "⪍": true, + "⪏": true, + "[": true, + "‘": true, + "‚": true, + "ł": true, + "<": true, + "<": true, + "⪦": true, + "⩹": true, + "⋖": true, + "⋋": true, + "⋉": true, + "⥶": true, + "⩻": true, + "⦖": true, + "◃": true, + "⊴": true, + "◂": true, + "⥊": true, + "⥦": true, + "≨︀": true, + "≨︀": true, + "∺": true, + "¯": true, + "¯": true, + "♂": true, + "✠": true, + "✠": true, + "↦": true, + "↦": true, + "↧": true, + "↤": true, + "↥": true, + "▮": true, + "⨩": true, + "м": true, + "—": true, + "∡": true, + "𝔪": true, + "℧": true, + "µ": true, + "µ": true, + "∣": true, + "*": true, + "⫰": true, + "·": true, + "·": true, + "−": true, + "⊟": true, + "∸": true, + "⨪": true, + "⫛": true, + "…": true, + "∓": true, + "⊧": true, + "𝕞": true, + "∓": true, + "𝓂": true, + "∾": true, + "μ": true, + "⊸": true, + "⊸": true, + "⋙̸": true, + "≫⃒": true, + "≫̸": true, + "⇍": true, + "⇎": true, + "⋘̸": true, + "≪⃒": true, + "≪̸": true, + "⇏": true, + "⊯": true, + "⊮": true, + "∇": true, + "ń": true, + "∠⃒": true, + "≉": true, + "⩰̸": true, + "≋̸": true, + "ʼn": true, + "≉": true, + "♮": true, + "♮": true, + "ℕ": true, + " ": true, + " ": true, + "≎̸": true, + "≏̸": true, + "⩃": true, + "ň": true, + "ņ": true, + "≇": true, + "⩭̸": true, + "⩂": true, + "н": true, + "–": true, + "≠": true, + "⇗": true, + "⤤": true, + "↗": true, + "↗": true, + "≐̸": true, + "≢": true, + "⤨": true, + "≂̸": true, + "∄": true, + "∄": true, + "𝔫": true, + "≧̸": true, + "≱": true, + "≱": true, + "≧̸": true, + "⩾̸": true, + "⩾̸": true, + "≵": true, + "≯": true, + "≯": true, + "⇎": true, + "↮": true, + "⫲": true, + "∋": true, + "⋼": true, + "⋺": true, + "∋": true, + "њ": true, + "⇍": true, + "≦̸": true, + "↚": true, + "‥": true, + "≰": true, + "↚": true, + "↮": true, + "≰": true, + "≦̸": true, + "⩽̸": true, + "⩽̸": true, + "≮": true, + "≴": true, + "≮": true, + "⋪": true, + "⋬": true, + "∤": true, + "𝕟": true, + "¬": true, + "¬": true, + "∉": true, + "⋹̸": true, + "⋵̸": true, + "∉": true, + "⋷": true, + "⋶": true, + "∌": true, + "∌": true, + "⋾": true, + "⋽": true, + "∦": true, + "∦": true, + "⫽⃥": true, + "∂̸": true, + "⨔": true, + "⊀": true, + "⋠": true, + "⪯̸": true, + "⊀": true, + "⪯̸": true, + "⇏": true, + "↛": true, + "⤳̸": true, + "↝̸": true, + "↛": true, + "⋫": true, + "⋭": true, + "⊁": true, + "⋡": true, + "⪰̸": true, + "𝓃": true, + "∤": true, + "∦": true, + "≁": true, + "≄": true, + "≄": true, + "∤": true, + "∦": true, + "⋢": true, + "⋣": true, + "⊄": true, + "⫅̸": true, + "⊈": true, + "⊂⃒": true, + "⊈": true, + "⫅̸": true, + "⊁": true, + "⪰̸": true, + "⊅": true, + "⫆̸": true, + "⊉": true, + "⊃⃒": true, + "⊉": true, + "⫆̸": true, + "≹": true, + "ñ": true, + "ñ": true, + "≸": true, + "⋪": true, + "⋬": true, + "⋫": true, + "⋭": true, + "ν": true, + "#": true, + "№": true, + " ": true, + "⊭": true, + "⤄": true, + "≍⃒": true, + "⊬": true, + "≥⃒": true, + ">⃒": true, + "⧞": true, + "⤂": true, + "≤⃒": true, + "<⃒": true, + "⊴⃒": true, + "⤃": true, + "⊵⃒": true, + "∼⃒": true, + "⇖": true, + "⤣": true, + "↖": true, + "↖": true, + "⤧": true, + "Ⓢ": true, + "ó": true, + "ó": true, + "⊛": true, + "⊚": true, + "ô": true, + "ô": true, + "о": true, + "⊝": true, + "ő": true, + "⨸": true, + "⊙": true, + "⦼": true, + "œ": true, + "⦿": true, + "𝔬": true, + "˛": true, + "ò": true, + "ò": true, + "⧁": true, + "⦵": true, + "Ω": true, + "∮": true, + "↺": true, + "⦾": true, + "⦻": true, + "‾": true, + "⧀": true, + "ō": true, + "ω": true, + "ο": true, + "⦶": true, + "⊖": true, + "𝕠": true, + "⦷": true, + "⦹": true, + "⊕": true, + "∨": true, + "↻": true, + "⩝": true, + "ℴ": true, + "ℴ": true, + "ª": true, + "ª": true, + "º": true, + "º": true, + "⊶": true, + "⩖": true, + "⩗": true, + "⩛": true, + "ℴ": true, + "ø": true, + "ø": true, + "⊘": true, + "õ": true, + "õ": true, + "⊗": true, + "⨶": true, + "ö": true, + "ö": true, + "⌽": true, + "∥": true, + "¶": true, + "¶": true, + "∥": true, + "⫳": true, + "⫽": true, + "∂": true, + "п": true, + "%": true, + ".": true, + "‰": true, + "⊥": true, + "‱": true, + "𝔭": true, + "φ": true, + "ϕ": true, + "ℳ": true, + "☎": true, + "π": true, + "⋔": true, + "ϖ": true, + "ℏ": true, + "ℎ": true, + "ℏ": true, + "+": true, + "⨣": true, + "⊞": true, + "⨢": true, + "∔": true, + "⨥": true, + "⩲": true, + "±": true, + "±": true, + "⨦": true, + "⨧": true, + "±": true, + "⨕": true, + "𝕡": true, + "£": true, + "£": true, + "≺": true, + "⪳": true, + "⪷": true, + "≼": true, + "⪯": true, + "≺": true, + "⪷": true, + "≼": true, + "⪯": true, + "⪹": true, + "⪵": true, + "⋨": true, + "≾": true, + "′": true, + "ℙ": true, + "⪵": true, + "⪹": true, + "⋨": true, + "∏": true, + "⌮": true, + "⌒": true, + "⌓": true, + "∝": true, + "∝": true, + "≾": true, + "⊰": true, + "𝓅": true, + "ψ": true, + " ": true, + "𝔮": true, + "⨌": true, + "𝕢": true, + "⁗": true, + "𝓆": true, + "ℍ": true, + "⨖": true, + "?": true, + "≟": true, + """: true, + """: true, + "⇛": true, + "⇒": true, + "⤜": true, + "⤏": true, + "⥤": true, + "∽̱": true, + "ŕ": true, + "√": true, + "⦳": true, + "⟩": true, + "⦒": true, + "⦥": true, + "⟩": true, + "»": true, + "»": true, + "→": true, + "⥵": true, + "⇥": true, + "⤠": true, + "⤳": true, + "⤞": true, + "↪": true, + "↬": true, + "⥅": true, + "⥴": true, + "↣": true, + "↝": true, + "⤚": true, + "∶": true, + "ℚ": true, + "⤍": true, + "❳": true, + "}": true, + "]": true, + "⦌": true, + "⦎": true, + "⦐": true, + "ř": true, + "ŗ": true, + "⌉": true, + "}": true, + "р": true, + "⤷": true, + "⥩": true, + "”": true, + "”": true, + "↳": true, + "ℜ": true, + "ℛ": true, + "ℜ": true, + "ℝ": true, + "▭": true, + "®": true, + "®": true, + "⥽": true, + "⌋": true, + "𝔯": true, + "⇁": true, + "⇀": true, + "⥬": true, + "ρ": true, + "ϱ": true, + "→": true, + "↣": true, + "⇁": true, + "⇀": true, + "⇄": true, + "⇌": true, + "⇉": true, + "↝": true, + "⋌": true, + "˚": true, + "≓": true, + "⇄": true, + "⇌": true, + "‏": true, + "⎱": true, + "⎱": true, + "⫮": true, + "⟭": true, + "⇾": true, + "⟧": true, + "⦆": true, + "𝕣": true, + "⨮": true, + "⨵": true, + ")": true, + "⦔": true, + "⨒": true, + "⇉": true, + "›": true, + "𝓇": true, + "↱": true, + "]": true, + "’": true, + "’": true, + "⋌": true, + "⋊": true, + "▹": true, + "⊵": true, + "▸": true, + "⧎": true, + "⥨": true, + "℞": true, + "ś": true, + "‚": true, + "≻": true, + "⪴": true, + "⪸": true, + "š": true, + "≽": true, + "⪰": true, + "ş": true, + "ŝ": true, + "⪶": true, + "⪺": true, + "⋩": true, + "⨓": true, + "≿": true, + "с": true, + "⋅": true, + "⊡": true, + "⩦": true, + "⇘": true, + "⤥": true, + "↘": true, + "↘": true, + "§": true, + "§": true, + ";": true, + "⤩": true, + "∖": true, + "∖": true, + "✶": true, + "𝔰": true, + "⌢": true, + "♯": true, + "щ": true, + "ш": true, + "∣": true, + "∥": true, + "­": true, + "­": true, + "σ": true, + "ς": true, + "ς": true, + "∼": true, + "⩪": true, + "≃": true, + "≃": true, + "⪞": true, + "⪠": true, + "⪝": true, + "⪟": true, + "≆": true, + "⨤": true, + "⥲": true, + "←": true, + "∖": true, + "⨳": true, + "⧤": true, + "∣": true, + "⌣": true, + "⪪": true, + "⪬": true, + "⪬︀": true, + "ь": true, + "/": true, + "⧄": true, + "⌿": true, + "𝕤": true, + "♠": true, + "♠": true, + "∥": true, + "⊓": true, + "⊓︀": true, + "⊔": true, + "⊔︀": true, + "⊏": true, + "⊑": true, + "⊏": true, + "⊑": true, + "⊐": true, + "⊒": true, + "⊐": true, + "⊒": true, + "□": true, + "□": true, + "▪": true, + "▪": true, + "→": true, + "𝓈": true, + "∖": true, + "⌣": true, + "⋆": true, + "☆": true, + "★": true, + "ϵ": true, + "ϕ": true, + "¯": true, + "⊂": true, + "⫅": true, + "⪽": true, + "⊆": true, + "⫃": true, + "⫁": true, + "⫋": true, + "⊊": true, + "⪿": true, + "⥹": true, + "⊂": true, + "⊆": true, + "⫅": true, + "⊊": true, + "⫋": true, + "⫇": true, + "⫕": true, + "⫓": true, + "≻": true, + "⪸": true, + "≽": true, + "⪰": true, + "⪺": true, + "⪶": true, + "⋩": true, + "≿": true, + "∑": true, + "♪": true, + "¹": true, + "¹": true, + "²": true, + "²": true, + "³": true, + "³": true, + "⊃": true, + "⫆": true, + "⪾": true, + "⫘": true, + "⊇": true, + "⫄": true, + "⟉": true, + "⫗": true, + "⥻": true, + "⫂": true, + "⫌": true, + "⊋": true, + "⫀": true, + "⊃": true, + "⊇": true, + "⫆": true, + "⊋": true, + "⫌": true, + "⫈": true, + "⫔": true, + "⫖": true, + "⇙": true, + "⤦": true, + "↙": true, + "↙": true, + "⤪": true, + "ß": true, + "ß": true, + "⌖": true, + "τ": true, + "⎴": true, + "ť": true, + "ţ": true, + "т": true, + "⃛": true, + "⌕": true, + "𝔱": true, + "∴": true, + "∴": true, + "θ": true, + "ϑ": true, + "ϑ": true, + "≈": true, + "∼": true, + " ": true, + "≈": true, + "∼": true, + "þ": true, + "þ": true, + "˜": true, + "×": true, + "×": true, + "⊠": true, + "⨱": true, + "⨰": true, + "∭": true, + "⤨": true, + "⊤": true, + "⌶": true, + "⫱": true, + "𝕥": true, + "⫚": true, + "⤩": true, + "‴": true, + "™": true, + "▵": true, + "▿": true, + "◃": true, + "⊴": true, + "≜": true, + "▹": true, + "⊵": true, + "◬": true, + "≜": true, + "⨺": true, + "⨹": true, + "⧍": true, + "⨻": true, + "⏢": true, + "𝓉": true, + "ц": true, + "ћ": true, + "ŧ": true, + "≬": true, + "↞": true, + "↠": true, + "⇑": true, + "⥣": true, + "ú": true, + "ú": true, + "↑": true, + "ў": true, + "ŭ": true, + "û": true, + "û": true, + "у": true, + "⇅": true, + "ű": true, + "⥮": true, + "⥾": true, + "𝔲": true, + "ù": true, + "ù": true, + "↿": true, + "↾": true, + "▀": true, + "⌜": true, + "⌜": true, + "⌏": true, + "◸": true, + "ū": true, + "¨": true, + "¨": true, + "ų": true, + "𝕦": true, + "↑": true, + "↕": true, + "↿": true, + "↾": true, + "⊎": true, + "υ": true, + "ϒ": true, + "υ": true, + "⇈": true, + "⌝": true, + "⌝": true, + "⌎": true, + "ů": true, + "◹": true, + "𝓊": true, + "⋰": true, + "ũ": true, + "▵": true, + "▴": true, + "⇈": true, + "ü": true, + "ü": true, + "⦧": true, + "⇕": true, + "⫨": true, + "⫩": true, + "⊨": true, + "⦜": true, + "ϵ": true, + "ϰ": true, + "∅": true, + "ϕ": true, + "ϖ": true, + "∝": true, + "↕": true, + "ϱ": true, + "ς": true, + "⊊︀": true, + "⫋︀": true, + "⊋︀": true, + "⫌︀": true, + "ϑ": true, + "⊲": true, + "⊳": true, + "в": true, + "⊢": true, + "∨": true, + "⊻": true, + "≚": true, + "⋮": true, + "|": true, + "|": true, + "𝔳": true, + "⊲": true, + "⊂⃒": true, + "⊃⃒": true, + "𝕧": true, + "∝": true, + "⊳": true, + "𝓋": true, + "⫋︀": true, + "⊊︀": true, + "⫌︀": true, + "⊋︀": true, + "⦚": true, + "ŵ": true, + "⩟": true, + "∧": true, + "≙": true, + "℘": true, + "𝔴": true, + "𝕨": true, + "℘": true, + "≀": true, + "≀": true, + "𝓌": true, + "⋂": true, + "◯": true, + "⋃": true, + "▽": true, + "𝔵": true, + "⟺": true, + "⟷": true, + "ξ": true, + "⟸": true, + "⟵": true, + "⟼": true, + "⋻": true, + "⨀": true, + "𝕩": true, + "⨁": true, + "⨂": true, + "⟹": true, + "⟶": true, + "𝓍": true, + "⨆": true, + "⨄": true, + "△": true, + "⋁": true, + "⋀": true, + "ý": true, + "ý": true, + "я": true, + "ŷ": true, + "ы": true, + "¥": true, + "¥": true, + "𝔶": true, + "ї": true, + "𝕪": true, + "𝓎": true, + "ю": true, + "ÿ": true, + "ÿ": true, + "ź": true, + "ž": true, + "з": true, + "ż": true, + "ℨ": true, + "ζ": true, + "𝔷": true, + "ж": true, + "⇝": true, + "𝕫": true, + "𝓏": true, + "‍": true, + "‌": true, +} diff --git a/backend/vendor/github.com/russross/blackfriday/v2/esc.go b/backend/vendor/github.com/russross/blackfriday/v2/esc.go index 6385f27c..6ab60102 100644 --- a/backend/vendor/github.com/russross/blackfriday/v2/esc.go +++ b/backend/vendor/github.com/russross/blackfriday/v2/esc.go @@ -13,13 +13,27 @@ var htmlEscaper = [256][]byte{ } func escapeHTML(w io.Writer, s []byte) { + escapeEntities(w, s, false) +} + +func escapeAllHTML(w io.Writer, s []byte) { + escapeEntities(w, s, true) +} + +func escapeEntities(w io.Writer, s []byte, escapeValidEntities bool) { var start, end int for end < len(s) { escSeq := htmlEscaper[s[end]] if escSeq != nil { - w.Write(s[start:end]) - w.Write(escSeq) - start = end + 1 + isEntity, entityEnd := nodeIsEntity(s, end) + if isEntity && !escapeValidEntities { + w.Write(s[start : entityEnd+1]) + start = entityEnd + 1 + } else { + w.Write(s[start:end]) + w.Write(escSeq) + start = end + 1 + } } end++ } @@ -28,6 +42,28 @@ func escapeHTML(w io.Writer, s []byte) { } } +func nodeIsEntity(s []byte, end int) (isEntity bool, endEntityPos int) { + isEntity = false + endEntityPos = end + 1 + + if s[end] == '&' { + for endEntityPos < len(s) { + if s[endEntityPos] == ';' { + if entities[string(s[end:endEntityPos+1])] { + isEntity = true + break + } + } + if !isalnum(s[endEntityPos]) && s[endEntityPos] != '&' && s[endEntityPos] != '#' { + break + } + endEntityPos++ + } + } + + return isEntity, endEntityPos +} + func escLink(w io.Writer, text []byte) { unesc := html.UnescapeString(string(text)) escapeHTML(w, []byte(unesc)) diff --git a/backend/vendor/github.com/russross/blackfriday/v2/html.go b/backend/vendor/github.com/russross/blackfriday/v2/html.go index 284c8718..cb4f26e3 100644 --- a/backend/vendor/github.com/russross/blackfriday/v2/html.go +++ b/backend/vendor/github.com/russross/blackfriday/v2/html.go @@ -132,7 +132,10 @@ func NewHTMLRenderer(params HTMLRendererParameters) *HTMLRenderer { } if params.FootnoteReturnLinkContents == "" { - params.FootnoteReturnLinkContents = `[return]` + // U+FE0E is VARIATION SELECTOR-15. + // It suppresses automatic emoji presentation of the preceding + // U+21A9 LEFTWARDS ARROW WITH HOOK on iOS and iPadOS. + params.FootnoteReturnLinkContents = "↩\ufe0e" } return &HTMLRenderer{ @@ -616,7 +619,7 @@ func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkSt } case Code: r.out(w, codeTag) - escapeHTML(w, node.Literal) + escapeAllHTML(w, node.Literal) r.out(w, codeCloseTag) case Document: break @@ -762,7 +765,7 @@ func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkSt r.cr(w) r.out(w, preTag) r.tag(w, codeTag[:len(codeTag)-1], attrs) - escapeHTML(w, node.Literal) + escapeAllHTML(w, node.Literal) r.out(w, codeCloseTag) r.out(w, preCloseTag) if node.Parent.Type != Item { diff --git a/backend/vendor/github.com/russross/blackfriday/v2/inline.go b/backend/vendor/github.com/russross/blackfriday/v2/inline.go index 4ed29079..d45bd941 100644 --- a/backend/vendor/github.com/russross/blackfriday/v2/inline.go +++ b/backend/vendor/github.com/russross/blackfriday/v2/inline.go @@ -278,7 +278,7 @@ func link(p *Markdown, data []byte, offset int) (int, *Node) { case data[i] == '\n': textHasNl = true - case data[i-1] == '\\': + case isBackslashEscaped(data, i): continue case data[i] == '[': diff --git a/backend/vendor/github.com/russross/blackfriday/v2/node.go b/backend/vendor/github.com/russross/blackfriday/v2/node.go index 51b9e8c1..04e6050c 100644 --- a/backend/vendor/github.com/russross/blackfriday/v2/node.go +++ b/backend/vendor/github.com/russross/blackfriday/v2/node.go @@ -199,7 +199,8 @@ func (n *Node) InsertBefore(sibling *Node) { } } -func (n *Node) isContainer() bool { +// IsContainer returns true if 'n' can contain children. +func (n *Node) IsContainer() bool { switch n.Type { case Document: fallthrough @@ -238,6 +239,11 @@ func (n *Node) isContainer() bool { } } +// IsLeaf returns true if 'n' is a leaf node. +func (n *Node) IsLeaf() bool { + return !n.IsContainer() +} + func (n *Node) canContain(t NodeType) bool { if n.Type == List { return t == Item @@ -309,11 +315,11 @@ func newNodeWalker(root *Node) *nodeWalker { } func (nw *nodeWalker) next() { - if (!nw.current.isContainer() || !nw.entering) && nw.current == nw.root { + if (!nw.current.IsContainer() || !nw.entering) && nw.current == nw.root { nw.current = nil return } - if nw.entering && nw.current.isContainer() { + if nw.entering && nw.current.IsContainer() { if nw.current.FirstChild != nil { nw.current = nw.current.FirstChild nw.entering = true diff --git a/backend/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml b/backend/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml deleted file mode 100644 index 93b1fcdb..00000000 --- a/backend/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -sudo: false -language: go -go: - - 1.x - - master -matrix: - allow_failures: - - go: master - 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/backend/vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE b/backend/vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE deleted file mode 100644 index c35c17af..00000000 --- a/backend/vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2015 Dmitri Shuralyov - -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/backend/vendor/github.com/shurcooL/sanitized_anchor_name/README.md b/backend/vendor/github.com/shurcooL/sanitized_anchor_name/README.md deleted file mode 100644 index 670bf0fe..00000000 --- a/backend/vendor/github.com/shurcooL/sanitized_anchor_name/README.md +++ /dev/null @@ -1,36 +0,0 @@ -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/backend/vendor/github.com/shurcooL/sanitized_anchor_name/go.mod b/backend/vendor/github.com/shurcooL/sanitized_anchor_name/go.mod deleted file mode 100644 index 1e255347..00000000 --- a/backend/vendor/github.com/shurcooL/sanitized_anchor_name/go.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/shurcooL/sanitized_anchor_name diff --git a/backend/vendor/github.com/shurcooL/sanitized_anchor_name/main.go b/backend/vendor/github.com/shurcooL/sanitized_anchor_name/main.go deleted file mode 100644 index 6a77d124..00000000 --- a/backend/vendor/github.com/shurcooL/sanitized_anchor_name/main.go +++ /dev/null @@ -1,29 +0,0 @@ -// 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. -package sanitized_anchor_name // import "github.com/shurcooL/sanitized_anchor_name" - -import "unicode" - -// Create returns a sanitized anchor name for the given text. -func Create(text string) string { - var anchorName []rune - var futureDash = false - for _, r := range text { - switch { - case unicode.IsLetter(r) || unicode.IsNumber(r): - if futureDash && len(anchorName) > 0 { - anchorName = append(anchorName, '-') - } - futureDash = false - anchorName = append(anchorName, unicode.ToLower(r)) - default: - futureDash = true - } - } - return string(anchorName) -} diff --git a/backend/vendor/go.etcd.io/bbolt/README.md b/backend/vendor/go.etcd.io/bbolt/README.md index 2dff3761..c9e64b1a 100644 --- a/backend/vendor/go.etcd.io/bbolt/README.md +++ b/backend/vendor/go.etcd.io/bbolt/README.md @@ -152,11 +152,12 @@ 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. - +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 +any read-only transaction is open. Even a nested read-only transaction can cause +a deadlock, as the child transaction can block the parent transaction from releasing +its resources. #### Read-write transactions diff --git a/backend/vendor/go.etcd.io/bbolt/freelist.go b/backend/vendor/go.etcd.io/bbolt/freelist.go index d441b692..697a4696 100644 --- a/backend/vendor/go.etcd.io/bbolt/freelist.go +++ b/backend/vendor/go.etcd.io/bbolt/freelist.go @@ -2,7 +2,6 @@ package bbolt import ( "fmt" - "reflect" "sort" "unsafe" ) @@ -94,24 +93,8 @@ func (f *freelist) pending_count() int { return count } -// copyallunsafe copies a list of all free ids and all pending ids in one sorted list. +// copyall copies a list of all free ids and all pending ids in one sorted list. // f.count returns the minimum length required for dst. -func (f *freelist) copyallunsafe(dstptr unsafe.Pointer) { // dstptr is []pgid data pointer - m := make(pgids, 0, f.pending_count()) - for _, txp := range f.pending { - m = append(m, txp.ids...) - } - sort.Sort(m) - fpgids := f.getFreePageIDs() - sz := len(fpgids) + len(m) - dst := *(*[]pgid)(unsafe.Pointer(&reflect.SliceHeader{ - Data: uintptr(dstptr), - Len: sz, - Cap: sz, - })) - mergepgids(dst, fpgids, m) -} - func (f *freelist) copyall(dst []pgid) { m := make(pgids, 0, f.pending_count()) for _, txp := range f.pending { @@ -284,21 +267,23 @@ func (f *freelist) read(p *page) { } // If the page.count is at the max uint16 value (64k) then it's considered // an overflow and the size of the freelist is stored as the first element. - var idx, count uintptr = 0, uintptr(p.count) + var idx, count = 0, int(p.count) if count == 0xFFFF { idx = 1 - count = uintptr(*(*pgid)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(*p)))) + c := *(*pgid)(unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))) + count = int(c) + if count < 0 { + panic(fmt.Sprintf("leading element count %d overflows int", c)) + } } // Copy the list of page ids from the freelist. if count == 0 { f.ids = nil } else { - ids := *(*[]pgid)(unsafe.Pointer(&reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(*p) + idx*unsafe.Sizeof(pgid(0)), - Len: int(count), - Cap: int(count), - })) + var ids []pgid + data := unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p), unsafe.Sizeof(ids[0]), idx) + unsafeSlice(unsafe.Pointer(&ids), data, count) // copy the ids, so we don't modify on the freelist page directly idsCopy := make([]pgid, count) @@ -331,16 +316,22 @@ func (f *freelist) write(p *page) error { // The page.count can only hold up to 64k elements so if we overflow that // number then we handle it by putting the size in the first element. - lenids := f.count() - if lenids == 0 { - p.count = uint16(lenids) - } else if lenids < 0xFFFF { - p.count = uint16(lenids) - f.copyallunsafe(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(*p))) + l := f.count() + if l == 0 { + p.count = uint16(l) + } else if l < 0xFFFF { + p.count = uint16(l) + var ids []pgid + data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p)) + unsafeSlice(unsafe.Pointer(&ids), data, l) + f.copyall(ids) } else { p.count = 0xFFFF - *(*pgid)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(*p))) = pgid(lenids) - f.copyallunsafe(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(*p) + unsafe.Sizeof(pgid(0)))) + var ids []pgid + data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p)) + unsafeSlice(unsafe.Pointer(&ids), data, l+1) + ids[0] = pgid(l) + f.copyall(ids[1:]) } return nil diff --git a/backend/vendor/go.etcd.io/bbolt/node.go b/backend/vendor/go.etcd.io/bbolt/node.go index 1690eef3..73988b5c 100644 --- a/backend/vendor/go.etcd.io/bbolt/node.go +++ b/backend/vendor/go.etcd.io/bbolt/node.go @@ -3,7 +3,6 @@ package bbolt import ( "bytes" "fmt" - "reflect" "sort" "unsafe" ) @@ -208,36 +207,32 @@ func (n *node) write(p *page) { } // Loop over each item and write it to the page. - bp := uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(*p) + n.pageElementSize()*uintptr(len(n.inodes)) + // off tracks the offset into p of the start of the next data. + off := unsafe.Sizeof(*p) + n.pageElementSize()*uintptr(len(n.inodes)) for i, item := range n.inodes { _assert(len(item.key) > 0, "write: zero-length inode key") + // Create a slice to write into of needed size and advance + // byte pointer for next iteration. + sz := len(item.key) + len(item.value) + b := unsafeByteSlice(unsafe.Pointer(p), off, 0, sz) + off += uintptr(sz) + // Write the page element. if n.isLeaf { elem := p.leafPageElement(uint16(i)) - elem.pos = uint32(bp - uintptr(unsafe.Pointer(elem))) + elem.pos = uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))) elem.flags = item.flags elem.ksize = uint32(len(item.key)) elem.vsize = uint32(len(item.value)) } else { elem := p.branchPageElement(uint16(i)) - elem.pos = uint32(bp - uintptr(unsafe.Pointer(elem))) + elem.pos = uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))) elem.ksize = uint32(len(item.key)) elem.pgid = item.pgid _assert(elem.pgid != p.id, "write: circular dependency occurred") } - // Create a slice to write into of needed size and advance - // byte pointer for next iteration. - klen, vlen := len(item.key), len(item.value) - sz := klen + vlen - b := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ - Data: bp, - Len: sz, - Cap: sz, - })) - bp += uintptr(sz) - // Write data for the element to the end of the page. l := copy(b, item.key) copy(b[l:], item.value) diff --git a/backend/vendor/go.etcd.io/bbolt/page.go b/backend/vendor/go.etcd.io/bbolt/page.go index b5c16997..c9a158fb 100644 --- a/backend/vendor/go.etcd.io/bbolt/page.go +++ b/backend/vendor/go.etcd.io/bbolt/page.go @@ -3,7 +3,6 @@ package bbolt import ( "fmt" "os" - "reflect" "sort" "unsafe" ) @@ -51,13 +50,13 @@ func (p *page) typ() string { // meta returns a pointer to the metadata section of the page. func (p *page) meta() *meta { - return (*meta)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(*p))) + return (*meta)(unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))) } // leafPageElement retrieves the leaf node by index func (p *page) leafPageElement(index uint16) *leafPageElement { - off := uintptr(index) * unsafe.Sizeof(leafPageElement{}) - return (*leafPageElement)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(*p) + off)) + return (*leafPageElement)(unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p), + leafPageElementSize, int(index))) } // leafPageElements retrieves a list of leaf nodes. @@ -65,17 +64,16 @@ func (p *page) leafPageElements() []leafPageElement { if p.count == 0 { return nil } - return *(*[]leafPageElement)(unsafe.Pointer(&reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(*p), - Len: int(p.count), - Cap: int(p.count), - })) + var elems []leafPageElement + data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p)) + unsafeSlice(unsafe.Pointer(&elems), data, int(p.count)) + return elems } // branchPageElement retrieves the branch node by index func (p *page) branchPageElement(index uint16) *branchPageElement { - off := uintptr(index) * unsafe.Sizeof(branchPageElement{}) - return (*branchPageElement)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(*p) + off)) + return (*branchPageElement)(unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p), + unsafe.Sizeof(branchPageElement{}), int(index))) } // branchPageElements retrieves a list of branch nodes. @@ -83,20 +81,15 @@ func (p *page) branchPageElements() []branchPageElement { if p.count == 0 { return nil } - return *(*[]branchPageElement)(unsafe.Pointer(&reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(*p), - Len: int(p.count), - Cap: int(p.count), - })) + var elems []branchPageElement + data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p)) + unsafeSlice(unsafe.Pointer(&elems), data, int(p.count)) + return elems } // dump writes n bytes of the page to STDERR as hex output. func (p *page) hexdump(n int) { - buf := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(p)), - Len: n, - Cap: n, - })) + buf := unsafeByteSlice(unsafe.Pointer(p), 0, 0, n) fmt.Fprintf(os.Stderr, "%x\n", buf) } @@ -115,11 +108,7 @@ type branchPageElement struct { // key returns a byte slice of the node key. func (n *branchPageElement) key() []byte { - return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(n)) + uintptr(n.pos), - Len: int(n.ksize), - Cap: int(n.ksize), - })) + return unsafeByteSlice(unsafe.Pointer(n), 0, int(n.pos), int(n.pos)+int(n.ksize)) } // leafPageElement represents a node on a leaf page. @@ -132,20 +121,16 @@ type leafPageElement struct { // key returns a byte slice of the node key. func (n *leafPageElement) key() []byte { - return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(n)) + uintptr(n.pos), - Len: int(n.ksize), - Cap: int(n.ksize), - })) + i := int(n.pos) + j := i + int(n.ksize) + return unsafeByteSlice(unsafe.Pointer(n), 0, i, j) } // value returns a byte slice of the node value. func (n *leafPageElement) value() []byte { - return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(n)) + uintptr(n.pos) + uintptr(n.ksize), - Len: int(n.vsize), - Cap: int(n.vsize), - })) + i := int(n.pos) + int(n.ksize) + j := i + int(n.vsize) + return unsafeByteSlice(unsafe.Pointer(n), 0, i, j) } // PageInfo represents human readable information about a page. diff --git a/backend/vendor/go.etcd.io/bbolt/tx.go b/backend/vendor/go.etcd.io/bbolt/tx.go index 13937cdb..4b1a64a8 100644 --- a/backend/vendor/go.etcd.io/bbolt/tx.go +++ b/backend/vendor/go.etcd.io/bbolt/tx.go @@ -4,7 +4,6 @@ import ( "fmt" "io" "os" - "reflect" "sort" "strings" "time" @@ -524,24 +523,18 @@ func (tx *Tx) write() error { // Write pages to disk in order. for _, p := range pages { - size := (int(p.overflow) + 1) * tx.db.pageSize + rem := (uint64(p.overflow) + 1) * uint64(tx.db.pageSize) offset := int64(p.id) * int64(tx.db.pageSize) + var written uintptr // Write out page in "max allocation" sized chunks. - ptr := uintptr(unsafe.Pointer(p)) for { - // Limit our write to our max allocation size. - sz := size + sz := rem if sz > maxAllocSize-1 { sz = maxAllocSize - 1 } + buf := unsafeByteSlice(unsafe.Pointer(p), written, 0, int(sz)) - // Write chunk to disk. - buf := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ - Data: ptr, - Len: sz, - Cap: sz, - })) if _, err := tx.db.ops.writeAt(buf, offset); err != nil { return err } @@ -550,14 +543,14 @@ func (tx *Tx) write() error { tx.stats.Write++ // Exit inner for loop if we've written all the chunks. - size -= sz - if size == 0 { + rem -= sz + if rem == 0 { break } // Otherwise move offset forward and move pointer to next chunk. offset += int64(sz) - ptr += uintptr(sz) + written += uintptr(sz) } } @@ -576,11 +569,7 @@ func (tx *Tx) write() error { continue } - buf := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(p)), - Len: tx.db.pageSize, - Cap: tx.db.pageSize, - })) + buf := unsafeByteSlice(unsafe.Pointer(p), 0, 0, tx.db.pageSize) // See https://go.googlesource.com/go/+/f03c9202c43e0abb130669852082117ca50aa9b1 for i := range buf { diff --git a/backend/vendor/go.etcd.io/bbolt/unsafe.go b/backend/vendor/go.etcd.io/bbolt/unsafe.go new file mode 100644 index 00000000..c0e50375 --- /dev/null +++ b/backend/vendor/go.etcd.io/bbolt/unsafe.go @@ -0,0 +1,39 @@ +package bbolt + +import ( + "reflect" + "unsafe" +) + +func unsafeAdd(base unsafe.Pointer, offset uintptr) unsafe.Pointer { + return unsafe.Pointer(uintptr(base) + offset) +} + +func unsafeIndex(base unsafe.Pointer, offset uintptr, elemsz uintptr, n int) unsafe.Pointer { + return unsafe.Pointer(uintptr(base) + offset + uintptr(n)*elemsz) +} + +func unsafeByteSlice(base unsafe.Pointer, offset uintptr, i, j int) []byte { + // See: https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices + // + // This memory is not allocated from C, but it is unmanaged by Go's + // garbage collector and should behave similarly, and the compiler + // should produce similar code. Note that this conversion allows a + // subslice to begin after the base address, with an optional offset, + // while the URL above does not cover this case and only slices from + // index 0. However, the wiki never says that the address must be to + // the beginning of a C allocation (or even that malloc was used at + // all), so this is believed to be correct. + return (*[maxAllocSize]byte)(unsafeAdd(base, offset))[i:j:j] +} + +// unsafeSlice modifies the data, len, and cap of a slice variable pointed to by +// the slice parameter. This helper should be used over other direct +// manipulation of reflect.SliceHeader to prevent misuse, namely, converting +// from reflect.SliceHeader to a Go slice type. +func unsafeSlice(slice, data unsafe.Pointer, len int) { + s := (*reflect.SliceHeader)(slice) + s.Data = uintptr(data) + s.Cap = len + s.Len = len +} diff --git a/backend/vendor/modules.txt b/backend/vendor/modules.txt index 733fad7c..49a97417 100644 --- a/backend/vendor/modules.txt +++ b/backend/vendor/modules.txt @@ -104,12 +104,12 @@ github.com/go-pkgz/expirable-cache # github.com/go-pkgz/jrpc v0.2.0 ## explicit github.com/go-pkgz/jrpc -# github.com/go-pkgz/lcw v0.7.1 +# github.com/go-pkgz/lcw v0.8.1 ## explicit github.com/go-pkgz/lcw github.com/go-pkgz/lcw/eventbus github.com/go-pkgz/lcw/internal/cache -# github.com/go-pkgz/lgr v0.7.0 +# github.com/go-pkgz/lgr v0.10.4 ## explicit github.com/go-pkgz/lgr # github.com/go-pkgz/repeater v1.1.3 @@ -123,7 +123,7 @@ github.com/go-pkgz/rest/logger # github.com/go-pkgz/syncs v1.1.1 ## explicit github.com/go-pkgz/syncs -# github.com/go-redis/redis/v7 v7.2.0 +# github.com/go-redis/redis/v7 v7.4.0 github.com/go-redis/redis/v7 github.com/go-redis/redis/v7/internal github.com/go-redis/redis/v7/internal/consistenthash @@ -137,7 +137,7 @@ github.com/go-stack/stack github.com/golang/protobuf/proto # github.com/golang/snappy v0.0.1 github.com/golang/snappy -# github.com/google/uuid v1.1.1 +# github.com/google/uuid v1.1.2 ## explicit github.com/google/uuid # github.com/gorilla/feeds v1.1.1 @@ -178,11 +178,9 @@ github.com/rakyll/statik/fs # github.com/rs/xid v1.2.1 ## explicit github.com/rs/xid -# github.com/russross/blackfriday/v2 v2.0.1 +# github.com/russross/blackfriday/v2 v2.1.0 ## explicit github.com/russross/blackfriday/v2 -# github.com/shurcooL/sanitized_anchor_name v1.0.0 -github.com/shurcooL/sanitized_anchor_name # github.com/stretchr/objx v0.1.1 github.com/stretchr/objx # github.com/stretchr/testify v1.6.1 @@ -197,7 +195,7 @@ github.com/umputun/go-flags github.com/xdg/scram # github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc github.com/xdg/stringprep -# go.etcd.io/bbolt v1.3.4 +# go.etcd.io/bbolt v1.3.5 ## explicit go.etcd.io/bbolt # go.mongodb.org/mongo-driver v1.4.4