summaryrefslogtreecommitdiffstats
path: root/src/cmd/go/internal/modfetch
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/go/internal/modfetch')
-rw-r--r--src/cmd/go/internal/modfetch/bootstrap.go17
-rw-r--r--src/cmd/go/internal/modfetch/cache.go815
-rw-r--r--src/cmd/go/internal/modfetch/cache_test.go27
-rw-r--r--src/cmd/go/internal/modfetch/codehost/codehost.go376
-rw-r--r--src/cmd/go/internal/modfetch/codehost/git.go925
-rw-r--r--src/cmd/go/internal/modfetch/codehost/git_test.go795
-rw-r--r--src/cmd/go/internal/modfetch/codehost/shell.go141
-rw-r--r--src/cmd/go/internal/modfetch/codehost/svn.go168
-rw-r--r--src/cmd/go/internal/modfetch/codehost/vcs.go644
-rw-r--r--src/cmd/go/internal/modfetch/coderepo.go1215
-rw-r--r--src/cmd/go/internal/modfetch/coderepo_test.go965
-rw-r--r--src/cmd/go/internal/modfetch/fetch.go1002
-rw-r--r--src/cmd/go/internal/modfetch/key.go9
-rw-r--r--src/cmd/go/internal/modfetch/proxy.go453
-rw-r--r--src/cmd/go/internal/modfetch/repo.go411
-rw-r--r--src/cmd/go/internal/modfetch/sumdb.go315
-rw-r--r--src/cmd/go/internal/modfetch/toolchain.go181
-rw-r--r--src/cmd/go/internal/modfetch/zip_sum_test/testdata/zip_sums.csv2119
-rw-r--r--src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go232
19 files changed, 10810 insertions, 0 deletions
diff --git a/src/cmd/go/internal/modfetch/bootstrap.go b/src/cmd/go/internal/modfetch/bootstrap.go
new file mode 100644
index 0000000..e23669f
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/bootstrap.go
@@ -0,0 +1,17 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build cmd_go_bootstrap
+
+package modfetch
+
+import "golang.org/x/mod/module"
+
+func useSumDB(mod module.Version) bool {
+ return false
+}
+
+func lookupSumDB(mod module.Version) (string, []string, error) {
+ panic("bootstrap")
+}
diff --git a/src/cmd/go/internal/modfetch/cache.go b/src/cmd/go/internal/modfetch/cache.go
new file mode 100644
index 0000000..5a727c6
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/cache.go
@@ -0,0 +1,815 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modfetch
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/fs"
+ "math/rand"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "sync"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/gover"
+ "cmd/go/internal/lockedfile"
+ "cmd/go/internal/modfetch/codehost"
+ "cmd/go/internal/par"
+ "cmd/go/internal/robustio"
+
+ "golang.org/x/mod/module"
+ "golang.org/x/mod/semver"
+)
+
+func cacheDir(ctx context.Context, path string) (string, error) {
+ if err := checkCacheDir(ctx); err != nil {
+ return "", err
+ }
+ enc, err := module.EscapePath(path)
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(cfg.GOMODCACHE, "cache/download", enc, "/@v"), nil
+}
+
+func CachePath(ctx context.Context, m module.Version, suffix string) (string, error) {
+ if gover.IsToolchain(m.Path) {
+ return "", ErrToolchain
+ }
+ dir, err := cacheDir(ctx, m.Path)
+ if err != nil {
+ return "", err
+ }
+ if !gover.ModIsValid(m.Path, m.Version) {
+ return "", fmt.Errorf("non-semver module version %q", m.Version)
+ }
+ if module.CanonicalVersion(m.Version) != m.Version {
+ return "", fmt.Errorf("non-canonical module version %q", m.Version)
+ }
+ encVer, err := module.EscapeVersion(m.Version)
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(dir, encVer+"."+suffix), nil
+}
+
+// DownloadDir returns the directory to which m should have been downloaded.
+// An error will be returned if the module path or version cannot be escaped.
+// An error satisfying errors.Is(err, fs.ErrNotExist) will be returned
+// along with the directory if the directory does not exist or if the directory
+// is not completely populated.
+func DownloadDir(ctx context.Context, m module.Version) (string, error) {
+ if gover.IsToolchain(m.Path) {
+ return "", ErrToolchain
+ }
+ if err := checkCacheDir(ctx); err != nil {
+ return "", err
+ }
+ enc, err := module.EscapePath(m.Path)
+ if err != nil {
+ return "", err
+ }
+ if !gover.ModIsValid(m.Path, m.Version) {
+ return "", fmt.Errorf("non-semver module version %q", m.Version)
+ }
+ if module.CanonicalVersion(m.Version) != m.Version {
+ return "", fmt.Errorf("non-canonical module version %q", m.Version)
+ }
+ encVer, err := module.EscapeVersion(m.Version)
+ if err != nil {
+ return "", err
+ }
+
+ // Check whether the directory itself exists.
+ dir := filepath.Join(cfg.GOMODCACHE, enc+"@"+encVer)
+ if fi, err := os.Stat(dir); os.IsNotExist(err) {
+ return dir, err
+ } else if err != nil {
+ return dir, &DownloadDirPartialError{dir, err}
+ } else if !fi.IsDir() {
+ return dir, &DownloadDirPartialError{dir, errors.New("not a directory")}
+ }
+
+ // Check if a .partial file exists. This is created at the beginning of
+ // a download and removed after the zip is extracted.
+ partialPath, err := CachePath(ctx, m, "partial")
+ if err != nil {
+ return dir, err
+ }
+ if _, err := os.Stat(partialPath); err == nil {
+ return dir, &DownloadDirPartialError{dir, errors.New("not completely extracted")}
+ } else if !os.IsNotExist(err) {
+ return dir, err
+ }
+
+ // Check if a .ziphash file exists. It should be created before the
+ // zip is extracted, but if it was deleted (by another program?), we need
+ // to re-calculate it. Note that checkMod will repopulate the ziphash
+ // file if it doesn't exist, but if the module is excluded by checks
+ // through GONOSUMDB or GOPRIVATE, that check and repopulation won't happen.
+ ziphashPath, err := CachePath(ctx, m, "ziphash")
+ if err != nil {
+ return dir, err
+ }
+ if _, err := os.Stat(ziphashPath); os.IsNotExist(err) {
+ return dir, &DownloadDirPartialError{dir, errors.New("ziphash file is missing")}
+ } else if err != nil {
+ return dir, err
+ }
+ return dir, nil
+}
+
+// DownloadDirPartialError is returned by DownloadDir if a module directory
+// exists but was not completely populated.
+//
+// DownloadDirPartialError is equivalent to fs.ErrNotExist.
+type DownloadDirPartialError struct {
+ Dir string
+ Err error
+}
+
+func (e *DownloadDirPartialError) Error() string { return fmt.Sprintf("%s: %v", e.Dir, e.Err) }
+func (e *DownloadDirPartialError) Is(err error) bool { return err == fs.ErrNotExist }
+
+// lockVersion locks a file within the module cache that guards the downloading
+// and extraction of the zipfile for the given module version.
+func lockVersion(ctx context.Context, mod module.Version) (unlock func(), err error) {
+ path, err := CachePath(ctx, mod, "lock")
+ if err != nil {
+ return nil, err
+ }
+ if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil {
+ return nil, err
+ }
+ return lockedfile.MutexAt(path).Lock()
+}
+
+// SideLock locks a file within the module cache that previously guarded
+// edits to files outside the cache, such as go.sum and go.mod files in the
+// user's working directory.
+// If err is nil, the caller MUST eventually call the unlock function.
+func SideLock(ctx context.Context) (unlock func(), err error) {
+ if err := checkCacheDir(ctx); err != nil {
+ return nil, err
+ }
+
+ path := filepath.Join(cfg.GOMODCACHE, "cache", "lock")
+ if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil {
+ return nil, fmt.Errorf("failed to create cache directory: %w", err)
+ }
+
+ return lockedfile.MutexAt(path).Lock()
+}
+
+// A cachingRepo is a cache around an underlying Repo,
+// avoiding redundant calls to ModulePath, Versions, Stat, Latest, and GoMod (but not CheckReuse or Zip).
+// It is also safe for simultaneous use by multiple goroutines
+// (so that it can be returned from Lookup multiple times).
+// It serializes calls to the underlying Repo.
+type cachingRepo struct {
+ path string
+ versionsCache par.ErrCache[string, *Versions]
+ statCache par.ErrCache[string, *RevInfo]
+ latestCache par.ErrCache[struct{}, *RevInfo]
+ gomodCache par.ErrCache[string, []byte]
+
+ once sync.Once
+ initRepo func(context.Context) (Repo, error)
+ r Repo
+}
+
+func newCachingRepo(ctx context.Context, path string, initRepo func(context.Context) (Repo, error)) *cachingRepo {
+ return &cachingRepo{
+ path: path,
+ initRepo: initRepo,
+ }
+}
+
+func (r *cachingRepo) repo(ctx context.Context) Repo {
+ r.once.Do(func() {
+ var err error
+ r.r, err = r.initRepo(ctx)
+ if err != nil {
+ r.r = errRepo{r.path, err}
+ }
+ })
+ return r.r
+}
+
+func (r *cachingRepo) CheckReuse(ctx context.Context, old *codehost.Origin) error {
+ return r.repo(ctx).CheckReuse(ctx, old)
+}
+
+func (r *cachingRepo) ModulePath() string {
+ return r.path
+}
+
+func (r *cachingRepo) Versions(ctx context.Context, prefix string) (*Versions, error) {
+ v, err := r.versionsCache.Do(prefix, func() (*Versions, error) {
+ return r.repo(ctx).Versions(ctx, prefix)
+ })
+
+ if err != nil {
+ return nil, err
+ }
+ return &Versions{
+ Origin: v.Origin,
+ List: append([]string(nil), v.List...),
+ }, nil
+}
+
+type cachedInfo struct {
+ info *RevInfo
+ err error
+}
+
+func (r *cachingRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
+ if gover.IsToolchain(r.path) {
+ // Skip disk cache; the underlying golang.org/toolchain repo is cached instead.
+ return r.repo(ctx).Stat(ctx, rev)
+ }
+ info, err := r.statCache.Do(rev, func() (*RevInfo, error) {
+ file, info, err := readDiskStat(ctx, r.path, rev)
+ if err == nil {
+ return info, err
+ }
+
+ info, err = r.repo(ctx).Stat(ctx, rev)
+ if err == nil {
+ // If we resolved, say, 1234abcde to v0.0.0-20180604122334-1234abcdef78,
+ // then save the information under the proper version, for future use.
+ if info.Version != rev {
+ file, _ = CachePath(ctx, module.Version{Path: r.path, Version: info.Version}, "info")
+ r.statCache.Do(info.Version, func() (*RevInfo, error) {
+ return info, nil
+ })
+ }
+
+ if err := writeDiskStat(ctx, file, info); err != nil {
+ fmt.Fprintf(os.Stderr, "go: writing stat cache: %v\n", err)
+ }
+ }
+ return info, err
+ })
+ if info != nil {
+ copy := *info
+ info = &copy
+ }
+ return info, err
+}
+
+func (r *cachingRepo) Latest(ctx context.Context) (*RevInfo, error) {
+ if gover.IsToolchain(r.path) {
+ // Skip disk cache; the underlying golang.org/toolchain repo is cached instead.
+ return r.repo(ctx).Latest(ctx)
+ }
+ info, err := r.latestCache.Do(struct{}{}, func() (*RevInfo, error) {
+ info, err := r.repo(ctx).Latest(ctx)
+
+ // Save info for likely future Stat call.
+ if err == nil {
+ r.statCache.Do(info.Version, func() (*RevInfo, error) {
+ return info, nil
+ })
+ if file, _, err := readDiskStat(ctx, r.path, info.Version); err != nil {
+ writeDiskStat(ctx, file, info)
+ }
+ }
+
+ return info, err
+ })
+ if info != nil {
+ copy := *info
+ info = &copy
+ }
+ return info, err
+}
+
+func (r *cachingRepo) GoMod(ctx context.Context, version string) ([]byte, error) {
+ if gover.IsToolchain(r.path) {
+ // Skip disk cache; the underlying golang.org/toolchain repo is cached instead.
+ return r.repo(ctx).GoMod(ctx, version)
+ }
+ text, err := r.gomodCache.Do(version, func() ([]byte, error) {
+ file, text, err := readDiskGoMod(ctx, r.path, version)
+ if err == nil {
+ // Note: readDiskGoMod already called checkGoMod.
+ return text, nil
+ }
+
+ text, err = r.repo(ctx).GoMod(ctx, version)
+ if err == nil {
+ if err := checkGoMod(r.path, version, text); err != nil {
+ return text, err
+ }
+ if err := writeDiskGoMod(ctx, file, text); err != nil {
+ fmt.Fprintf(os.Stderr, "go: writing go.mod cache: %v\n", err)
+ }
+ }
+ return text, err
+ })
+ if err != nil {
+ return nil, err
+ }
+ return append([]byte(nil), text...), nil
+}
+
+func (r *cachingRepo) Zip(ctx context.Context, dst io.Writer, version string) error {
+ if gover.IsToolchain(r.path) {
+ return ErrToolchain
+ }
+ return r.repo(ctx).Zip(ctx, dst, version)
+}
+
+// InfoFile is like Lookup(ctx, path).Stat(version) but also returns the name of the file
+// containing the cached information.
+func InfoFile(ctx context.Context, path, version string) (*RevInfo, string, error) {
+ if !gover.ModIsValid(path, version) {
+ return nil, "", fmt.Errorf("invalid version %q", version)
+ }
+
+ if file, info, err := readDiskStat(ctx, path, version); err == nil {
+ return info, file, nil
+ }
+
+ var info *RevInfo
+ var err2info map[error]*RevInfo
+ err := TryProxies(func(proxy string) error {
+ i, err := Lookup(ctx, proxy, path).Stat(ctx, version)
+ if err == nil {
+ info = i
+ } else {
+ if err2info == nil {
+ err2info = make(map[error]*RevInfo)
+ }
+ err2info[err] = info
+ }
+ return err
+ })
+ if err != nil {
+ return err2info[err], "", err
+ }
+
+ // Stat should have populated the disk cache for us.
+ file, err := CachePath(ctx, module.Version{Path: path, Version: version}, "info")
+ if err != nil {
+ return nil, "", err
+ }
+ return info, file, nil
+}
+
+// GoMod is like Lookup(ctx, path).GoMod(rev) but avoids the
+// repository path resolution in Lookup if the result is
+// already cached on local disk.
+func GoMod(ctx context.Context, path, rev string) ([]byte, error) {
+ // Convert commit hash to pseudo-version
+ // to increase cache hit rate.
+ if !gover.ModIsValid(path, rev) {
+ if _, info, err := readDiskStat(ctx, path, rev); err == nil {
+ rev = info.Version
+ } else {
+ if errors.Is(err, statCacheErr) {
+ return nil, err
+ }
+ err := TryProxies(func(proxy string) error {
+ info, err := Lookup(ctx, proxy, path).Stat(ctx, rev)
+ if err == nil {
+ rev = info.Version
+ }
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ _, data, err := readDiskGoMod(ctx, path, rev)
+ if err == nil {
+ return data, nil
+ }
+
+ err = TryProxies(func(proxy string) (err error) {
+ data, err = Lookup(ctx, proxy, path).GoMod(ctx, rev)
+ return err
+ })
+ return data, err
+}
+
+// GoModFile is like GoMod but returns the name of the file containing
+// the cached information.
+func GoModFile(ctx context.Context, path, version string) (string, error) {
+ if !gover.ModIsValid(path, version) {
+ return "", fmt.Errorf("invalid version %q", version)
+ }
+ if _, err := GoMod(ctx, path, version); err != nil {
+ return "", err
+ }
+ // GoMod should have populated the disk cache for us.
+ file, err := CachePath(ctx, module.Version{Path: path, Version: version}, "mod")
+ if err != nil {
+ return "", err
+ }
+ return file, nil
+}
+
+// GoModSum returns the go.sum entry for the module version's go.mod file.
+// (That is, it returns the entry listed in go.sum as "path version/go.mod".)
+func GoModSum(ctx context.Context, path, version string) (string, error) {
+ if !gover.ModIsValid(path, version) {
+ return "", fmt.Errorf("invalid version %q", version)
+ }
+ data, err := GoMod(ctx, path, version)
+ if err != nil {
+ return "", err
+ }
+ sum, err := goModSum(data)
+ if err != nil {
+ return "", err
+ }
+ return sum, nil
+}
+
+var errNotCached = fmt.Errorf("not in cache")
+
+// readDiskStat reads a cached stat result from disk,
+// returning the name of the cache file and the result.
+// If the read fails, the caller can use
+// writeDiskStat(file, info) to write a new cache entry.
+func readDiskStat(ctx context.Context, path, rev string) (file string, info *RevInfo, err error) {
+ if gover.IsToolchain(path) {
+ return "", nil, errNotCached
+ }
+ file, data, err := readDiskCache(ctx, path, rev, "info")
+ if err != nil {
+ // If the cache already contains a pseudo-version with the given hash, we
+ // would previously return that pseudo-version without checking upstream.
+ // However, that produced an unfortunate side-effect: if the author added a
+ // tag to the repository, 'go get' would not pick up the effect of that new
+ // tag on the existing commits, and 'go' commands that referred to those
+ // commits would use the previous name instead of the new one.
+ //
+ // That's especially problematic if the original pseudo-version starts with
+ // v0.0.0-, as was the case for all pseudo-versions during vgo development,
+ // since a v0.0.0- pseudo-version has lower precedence than pretty much any
+ // tagged version.
+ //
+ // In practice, we're only looking up by hash during initial conversion of a
+ // legacy config and during an explicit 'go get', and a little extra latency
+ // for those operations seems worth the benefit of picking up more accurate
+ // versions.
+ //
+ // Fall back to this resolution scheme only if the GOPROXY setting prohibits
+ // us from resolving upstream tags.
+ if cfg.GOPROXY == "off" {
+ if file, info, err := readDiskStatByHash(ctx, path, rev); err == nil {
+ return file, info, nil
+ }
+ }
+ return file, nil, err
+ }
+ info = new(RevInfo)
+ if err := json.Unmarshal(data, info); err != nil {
+ return file, nil, errNotCached
+ }
+ // The disk might have stale .info files that have Name and Short fields set.
+ // We want to canonicalize to .info files with those fields omitted.
+ // Remarshal and update the cache file if needed.
+ data2, err := json.Marshal(info)
+ if err == nil && !bytes.Equal(data2, data) {
+ writeDiskCache(ctx, file, data)
+ }
+ return file, info, nil
+}
+
+// readDiskStatByHash is a fallback for readDiskStat for the case
+// where rev is a commit hash instead of a proper semantic version.
+// In that case, we look for a cached pseudo-version that matches
+// the commit hash. If we find one, we use it.
+// This matters most for converting legacy package management
+// configs, when we are often looking up commits by full hash.
+// Without this check we'd be doing network I/O to the remote repo
+// just to find out about a commit we already know about
+// (and have cached under its pseudo-version).
+func readDiskStatByHash(ctx context.Context, path, rev string) (file string, info *RevInfo, err error) {
+ if gover.IsToolchain(path) {
+ return "", nil, errNotCached
+ }
+ if cfg.GOMODCACHE == "" {
+ // Do not download to current directory.
+ return "", nil, errNotCached
+ }
+
+ if !codehost.AllHex(rev) || len(rev) < 12 {
+ return "", nil, errNotCached
+ }
+ rev = rev[:12]
+ cdir, err := cacheDir(ctx, path)
+ if err != nil {
+ return "", nil, errNotCached
+ }
+ dir, err := os.Open(cdir)
+ if err != nil {
+ return "", nil, errNotCached
+ }
+ names, err := dir.Readdirnames(-1)
+ dir.Close()
+ if err != nil {
+ return "", nil, errNotCached
+ }
+
+ // A given commit hash may map to more than one pseudo-version,
+ // depending on which tags are present on the repository.
+ // Take the highest such version.
+ var maxVersion string
+ suffix := "-" + rev + ".info"
+ err = errNotCached
+ for _, name := range names {
+ if strings.HasSuffix(name, suffix) {
+ v := strings.TrimSuffix(name, ".info")
+ if module.IsPseudoVersion(v) && semver.Compare(v, maxVersion) > 0 {
+ maxVersion = v
+ file, info, err = readDiskStat(ctx, path, strings.TrimSuffix(name, ".info"))
+ }
+ }
+ }
+ return file, info, err
+}
+
+// oldVgoPrefix is the prefix in the old auto-generated cached go.mod files.
+// We stopped trying to auto-generate the go.mod files. Now we use a trivial
+// go.mod with only a module line, and we've dropped the version prefix
+// entirely. If we see a version prefix, that means we're looking at an old copy
+// and should ignore it.
+var oldVgoPrefix = []byte("//vgo 0.0.")
+
+// readDiskGoMod reads a cached go.mod file from disk,
+// returning the name of the cache file and the result.
+// If the read fails, the caller can use
+// writeDiskGoMod(file, data) to write a new cache entry.
+func readDiskGoMod(ctx context.Context, path, rev string) (file string, data []byte, err error) {
+ if gover.IsToolchain(path) {
+ return "", nil, errNotCached
+ }
+ file, data, err = readDiskCache(ctx, path, rev, "mod")
+
+ // If the file has an old auto-conversion prefix, pretend it's not there.
+ if bytes.HasPrefix(data, oldVgoPrefix) {
+ err = errNotCached
+ data = nil
+ }
+
+ if err == nil {
+ if err := checkGoMod(path, rev, data); err != nil {
+ return "", nil, err
+ }
+ }
+
+ return file, data, err
+}
+
+// readDiskCache is the generic "read from a cache file" implementation.
+// It takes the revision and an identifying suffix for the kind of data being cached.
+// It returns the name of the cache file and the content of the file.
+// If the read fails, the caller can use
+// writeDiskCache(file, data) to write a new cache entry.
+func readDiskCache(ctx context.Context, path, rev, suffix string) (file string, data []byte, err error) {
+ if gover.IsToolchain(path) {
+ return "", nil, errNotCached
+ }
+ file, err = CachePath(ctx, module.Version{Path: path, Version: rev}, suffix)
+ if err != nil {
+ return "", nil, errNotCached
+ }
+ data, err = robustio.ReadFile(file)
+ if err != nil {
+ return file, nil, errNotCached
+ }
+ return file, data, nil
+}
+
+// writeDiskStat writes a stat result cache entry.
+// The file name must have been returned by a previous call to readDiskStat.
+func writeDiskStat(ctx context.Context, file string, info *RevInfo) error {
+ if file == "" {
+ return nil
+ }
+
+ if info.Origin != nil {
+ // Clean the origin information, which might have too many
+ // validation criteria, for example if we are saving the result of
+ // m@master as m@pseudo-version.
+ clean := *info
+ info = &clean
+ o := *info.Origin
+ info.Origin = &o
+
+ // Tags never matter if you are starting with a semver version,
+ // as we would be when finding this cache entry.
+ o.TagSum = ""
+ o.TagPrefix = ""
+ // Ref doesn't matter if you have a pseudoversion.
+ if module.IsPseudoVersion(info.Version) {
+ o.Ref = ""
+ }
+ }
+
+ js, err := json.Marshal(info)
+ if err != nil {
+ return err
+ }
+ return writeDiskCache(ctx, file, js)
+}
+
+// writeDiskGoMod writes a go.mod cache entry.
+// The file name must have been returned by a previous call to readDiskGoMod.
+func writeDiskGoMod(ctx context.Context, file string, text []byte) error {
+ return writeDiskCache(ctx, file, text)
+}
+
+// writeDiskCache is the generic "write to a cache file" implementation.
+// The file must have been returned by a previous call to readDiskCache.
+func writeDiskCache(ctx context.Context, file string, data []byte) error {
+ if file == "" {
+ return nil
+ }
+ // Make sure directory for file exists.
+ if err := os.MkdirAll(filepath.Dir(file), 0777); err != nil {
+ return err
+ }
+
+ // Write the file to a temporary location, and then rename it to its final
+ // path to reduce the likelihood of a corrupt file existing at that final path.
+ f, err := tempFile(ctx, filepath.Dir(file), filepath.Base(file), 0666)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ // Only call os.Remove on f.Name() if we failed to rename it: otherwise,
+ // some other process may have created a new file with the same name after
+ // the rename completed.
+ if err != nil {
+ f.Close()
+ os.Remove(f.Name())
+ }
+ }()
+
+ if _, err := f.Write(data); err != nil {
+ return err
+ }
+ if err := f.Close(); err != nil {
+ return err
+ }
+ if err := robustio.Rename(f.Name(), file); err != nil {
+ return err
+ }
+
+ if strings.HasSuffix(file, ".mod") {
+ rewriteVersionList(ctx, filepath.Dir(file))
+ }
+ return nil
+}
+
+// tempFile creates a new temporary file with given permission bits.
+func tempFile(ctx context.Context, dir, prefix string, perm fs.FileMode) (f *os.File, err error) {
+ for i := 0; i < 10000; i++ {
+ name := filepath.Join(dir, prefix+strconv.Itoa(rand.Intn(1000000000))+".tmp")
+ f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm)
+ if os.IsExist(err) {
+ if ctx.Err() != nil {
+ return nil, ctx.Err()
+ }
+ continue
+ }
+ break
+ }
+ return
+}
+
+// rewriteVersionList rewrites the version list in dir
+// after a new *.mod file has been written.
+func rewriteVersionList(ctx context.Context, dir string) (err error) {
+ if filepath.Base(dir) != "@v" {
+ base.Fatalf("go: internal error: misuse of rewriteVersionList")
+ }
+
+ listFile := filepath.Join(dir, "list")
+
+ // Lock listfile when writing to it to try to avoid corruption to the file.
+ // Under rare circumstances, for instance, if the system loses power in the
+ // middle of a write it is possible for corrupt data to be written. This is
+ // not a problem for the go command itself, but may be an issue if the
+ // cache is being served by a GOPROXY HTTP server. This will be corrected
+ // the next time a new version of the module is fetched and the file is rewritten.
+ // TODO(matloob): golang.org/issue/43313 covers adding a go mod verify
+ // command that removes module versions that fail checksums. It should also
+ // remove list files that are detected to be corrupt.
+ f, err := lockedfile.Edit(listFile)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if cerr := f.Close(); cerr != nil && err == nil {
+ err = cerr
+ }
+ }()
+ infos, err := os.ReadDir(dir)
+ if err != nil {
+ return err
+ }
+ var list []string
+ for _, info := range infos {
+ // We look for *.mod files on the theory that if we can't supply
+ // the .mod file then there's no point in listing that version,
+ // since it's unusable. (We can have *.info without *.mod.)
+ // We don't require *.zip files on the theory that for code only
+ // involved in module graph construction, many *.zip files
+ // will never be requested.
+ name := info.Name()
+ if v, found := strings.CutSuffix(name, ".mod"); found {
+ if v != "" && module.CanonicalVersion(v) == v {
+ list = append(list, v)
+ }
+ }
+ }
+ semver.Sort(list)
+
+ var buf bytes.Buffer
+ for _, v := range list {
+ buf.WriteString(v)
+ buf.WriteString("\n")
+ }
+ if fi, err := f.Stat(); err == nil && int(fi.Size()) == buf.Len() {
+ old := make([]byte, buf.Len()+1)
+ if n, err := f.ReadAt(old, 0); err == io.EOF && n == buf.Len() && bytes.Equal(buf.Bytes(), old) {
+ return nil // No edit needed.
+ }
+ }
+ // Remove existing contents, so that when we truncate to the actual size it will zero-fill,
+ // and we will be able to detect (some) incomplete writes as files containing trailing NUL bytes.
+ if err := f.Truncate(0); err != nil {
+ return err
+ }
+ // Reserve the final size and zero-fill.
+ if err := f.Truncate(int64(buf.Len())); err != nil {
+ return err
+ }
+ // Write the actual contents. If this fails partway through,
+ // the remainder of the file should remain as zeroes.
+ if _, err := f.Write(buf.Bytes()); err != nil {
+ f.Truncate(0)
+ return err
+ }
+
+ return nil
+}
+
+var (
+ statCacheOnce sync.Once
+ statCacheErr error
+)
+
+// checkCacheDir checks if the directory specified by GOMODCACHE exists. An
+// error is returned if it does not.
+func checkCacheDir(ctx context.Context) error {
+ if cfg.GOMODCACHE == "" {
+ // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
+ // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
+ return fmt.Errorf("module cache not found: neither GOMODCACHE nor GOPATH is set")
+ }
+ if !filepath.IsAbs(cfg.GOMODCACHE) {
+ return fmt.Errorf("GOMODCACHE entry is relative; must be absolute path: %q.\n", cfg.GOMODCACHE)
+ }
+
+ // os.Stat is slow on Windows, so we only call it once to prevent unnecessary
+ // I/O every time this function is called.
+ statCacheOnce.Do(func() {
+ fi, err := os.Stat(cfg.GOMODCACHE)
+ if err != nil {
+ if !os.IsNotExist(err) {
+ statCacheErr = fmt.Errorf("could not create module cache: %w", err)
+ return
+ }
+ if err := os.MkdirAll(cfg.GOMODCACHE, 0777); err != nil {
+ statCacheErr = fmt.Errorf("could not create module cache: %w", err)
+ return
+ }
+ return
+ }
+ if !fi.IsDir() {
+ statCacheErr = fmt.Errorf("could not create module cache: %q is not a directory", cfg.GOMODCACHE)
+ return
+ }
+ })
+ return statCacheErr
+}
diff --git a/src/cmd/go/internal/modfetch/cache_test.go b/src/cmd/go/internal/modfetch/cache_test.go
new file mode 100644
index 0000000..6aada66
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/cache_test.go
@@ -0,0 +1,27 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modfetch
+
+import (
+ "context"
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+func TestWriteDiskCache(t *testing.T) {
+ ctx := context.Background()
+
+ tmpdir, err := os.MkdirTemp("", "go-writeCache-test-")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ err = writeDiskCache(ctx, filepath.Join(tmpdir, "file"), []byte("data"))
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/src/cmd/go/internal/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go
new file mode 100644
index 0000000..69a3c57
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/codehost/codehost.go
@@ -0,0 +1,376 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package codehost defines the interface implemented by a code hosting source,
+// along with support code for use by implementations.
+package codehost
+
+import (
+ "bytes"
+ "context"
+ "crypto/sha256"
+ "fmt"
+ "io"
+ "io/fs"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "sync"
+ "time"
+
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/lockedfile"
+ "cmd/go/internal/str"
+
+ "golang.org/x/mod/module"
+ "golang.org/x/mod/semver"
+)
+
+// Downloaded size limits.
+const (
+ MaxGoMod = 16 << 20 // maximum size of go.mod file
+ MaxLICENSE = 16 << 20 // maximum size of LICENSE file
+ MaxZipFile = 500 << 20 // maximum size of downloaded zip file
+)
+
+// A Repo represents a code hosting source.
+// Typical implementations include local version control repositories,
+// remote version control servers, and code hosting sites.
+//
+// A Repo must be safe for simultaneous use by multiple goroutines,
+// and callers must not modify returned values, which may be cached and shared.
+type Repo interface {
+ // CheckReuse checks whether the old origin information
+ // remains up to date. If so, whatever cached object it was
+ // taken from can be reused.
+ // The subdir gives subdirectory name where the module root is expected to be found,
+ // "" for the root or "sub/dir" for a subdirectory (no trailing slash).
+ CheckReuse(ctx context.Context, old *Origin, subdir string) error
+
+ // List lists all tags with the given prefix.
+ Tags(ctx context.Context, prefix string) (*Tags, error)
+
+ // Stat returns information about the revision rev.
+ // A revision can be any identifier known to the underlying service:
+ // commit hash, branch, tag, and so on.
+ Stat(ctx context.Context, rev string) (*RevInfo, error)
+
+ // Latest returns the latest revision on the default branch,
+ // whatever that means in the underlying implementation.
+ Latest(ctx context.Context) (*RevInfo, error)
+
+ // ReadFile reads the given file in the file tree corresponding to revision rev.
+ // It should refuse to read more than maxSize bytes.
+ //
+ // If the requested file does not exist it should return an error for which
+ // os.IsNotExist(err) returns true.
+ ReadFile(ctx context.Context, rev, file string, maxSize int64) (data []byte, err error)
+
+ // ReadZip downloads a zip file for the subdir subdirectory
+ // of the given revision to a new file in a given temporary directory.
+ // It should refuse to read more than maxSize bytes.
+ // It returns a ReadCloser for a streamed copy of the zip file.
+ // All files in the zip file are expected to be
+ // nested in a single top-level directory, whose name is not specified.
+ ReadZip(ctx context.Context, rev, subdir string, maxSize int64) (zip io.ReadCloser, err error)
+
+ // RecentTag returns the most recent tag on rev or one of its predecessors
+ // with the given prefix. allowed may be used to filter out unwanted versions.
+ RecentTag(ctx context.Context, rev, prefix string, allowed func(tag string) bool) (tag string, err error)
+
+ // DescendsFrom reports whether rev or any of its ancestors has the given tag.
+ //
+ // DescendsFrom must return true for any tag returned by RecentTag for the
+ // same revision.
+ DescendsFrom(ctx context.Context, rev, tag string) (bool, error)
+}
+
+// An Origin describes the provenance of a given repo method result.
+// It can be passed to CheckReuse (usually in a different go command invocation)
+// to see whether the result remains up-to-date.
+type Origin struct {
+ VCS string `json:",omitempty"` // "git" etc
+ URL string `json:",omitempty"` // URL of repository
+ Subdir string `json:",omitempty"` // subdirectory in repo
+
+ Hash string `json:",omitempty"` // commit hash or ID
+
+ // If TagSum is non-empty, then the resolution of this module version
+ // depends on the set of tags present in the repo, specifically the tags
+ // of the form TagPrefix + a valid semver version.
+ // If the matching repo tags and their commit hashes still hash to TagSum,
+ // the Origin is still valid (at least as far as the tags are concerned).
+ // The exact checksum is up to the Repo implementation; see (*gitRepo).Tags.
+ TagPrefix string `json:",omitempty"`
+ TagSum string `json:",omitempty"`
+
+ // If Ref is non-empty, then the resolution of this module version
+ // depends on Ref resolving to the revision identified by Hash.
+ // If Ref still resolves to Hash, the Origin is still valid (at least as far as Ref is concerned).
+ // For Git, the Ref is a full ref like "refs/heads/main" or "refs/tags/v1.2.3",
+ // and the Hash is the Git object hash the ref maps to.
+ // Other VCS might choose differently, but the idea is that Ref is the name
+ // with a mutable meaning while Hash is a name with an immutable meaning.
+ Ref string `json:",omitempty"`
+
+ // If RepoSum is non-empty, then the resolution of this module version
+ // failed due to the repo being available but the version not being present.
+ // This depends on the entire state of the repo, which RepoSum summarizes.
+ // For Git, this is a hash of all the refs and their hashes.
+ RepoSum string `json:",omitempty"`
+}
+
+// A Tags describes the available tags in a code repository.
+type Tags struct {
+ Origin *Origin
+ List []Tag
+}
+
+// A Tag describes a single tag in a code repository.
+type Tag struct {
+ Name string
+ Hash string // content hash identifying tag's content, if available
+}
+
+// isOriginTag reports whether tag should be preserved
+// in the Tags method's Origin calculation.
+// We can safely ignore tags that are not look like pseudo-versions,
+// because ../coderepo.go's (*codeRepo).Versions ignores them too.
+// We can also ignore non-semver tags, but we have to include semver
+// tags with extra suffixes, because the pseudo-version base finder uses them.
+func isOriginTag(tag string) bool {
+ // modfetch.(*codeRepo).Versions uses Canonical == tag,
+ // but pseudo-version calculation has a weaker condition that
+ // the canonical is a prefix of the tag.
+ // Include those too, so that if any new one appears, we'll invalidate the cache entry.
+ // This will lead to spurious invalidation of version list results,
+ // but tags of this form being created should be fairly rare
+ // (and invalidate pseudo-version results anyway).
+ c := semver.Canonical(tag)
+ return c != "" && strings.HasPrefix(tag, c) && !module.IsPseudoVersion(tag)
+}
+
+// A RevInfo describes a single revision in a source code repository.
+type RevInfo struct {
+ Origin *Origin
+ Name string // complete ID in underlying repository
+ Short string // shortened ID, for use in pseudo-version
+ Version string // version used in lookup
+ Time time.Time // commit time
+ Tags []string // known tags for commit
+}
+
+// UnknownRevisionError is an error equivalent to fs.ErrNotExist, but for a
+// revision rather than a file.
+type UnknownRevisionError struct {
+ Rev string
+}
+
+func (e *UnknownRevisionError) Error() string {
+ return "unknown revision " + e.Rev
+}
+func (UnknownRevisionError) Is(err error) bool {
+ return err == fs.ErrNotExist
+}
+
+// ErrNoCommits is an error equivalent to fs.ErrNotExist indicating that a given
+// repository or module contains no commits.
+var ErrNoCommits error = noCommitsError{}
+
+type noCommitsError struct{}
+
+func (noCommitsError) Error() string {
+ return "no commits"
+}
+func (noCommitsError) Is(err error) bool {
+ return err == fs.ErrNotExist
+}
+
+// AllHex reports whether the revision rev is entirely lower-case hexadecimal digits.
+func AllHex(rev string) bool {
+ for i := 0; i < len(rev); i++ {
+ c := rev[i]
+ if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' {
+ continue
+ }
+ return false
+ }
+ return true
+}
+
+// ShortenSHA1 shortens a SHA1 hash (40 hex digits) to the canonical length
+// used in pseudo-versions (12 hex digits).
+func ShortenSHA1(rev string) string {
+ if AllHex(rev) && len(rev) == 40 {
+ return rev[:12]
+ }
+ return rev
+}
+
+// WorkDir returns the name of the cached work directory to use for the
+// given repository type and name.
+func WorkDir(ctx context.Context, typ, name string) (dir, lockfile string, err error) {
+ if cfg.GOMODCACHE == "" {
+ return "", "", fmt.Errorf("neither GOPATH nor GOMODCACHE are set")
+ }
+
+ // We name the work directory for the SHA256 hash of the type and name.
+ // We intentionally avoid the actual name both because of possible
+ // conflicts with valid file system paths and because we want to ensure
+ // that one checkout is never nested inside another. That nesting has
+ // led to security problems in the past.
+ if strings.Contains(typ, ":") {
+ return "", "", fmt.Errorf("codehost.WorkDir: type cannot contain colon")
+ }
+ key := typ + ":" + name
+ dir = filepath.Join(cfg.GOMODCACHE, "cache/vcs", fmt.Sprintf("%x", sha256.Sum256([]byte(key))))
+
+ xLog, buildX := cfg.BuildXWriter(ctx)
+ if buildX {
+ fmt.Fprintf(xLog, "mkdir -p %s # %s %s\n", filepath.Dir(dir), typ, name)
+ }
+ if err := os.MkdirAll(filepath.Dir(dir), 0777); err != nil {
+ return "", "", err
+ }
+
+ lockfile = dir + ".lock"
+ if buildX {
+ fmt.Fprintf(xLog, "# lock %s\n", lockfile)
+ }
+
+ unlock, err := lockedfile.MutexAt(lockfile).Lock()
+ if err != nil {
+ return "", "", fmt.Errorf("codehost.WorkDir: can't find or create lock file: %v", err)
+ }
+ defer unlock()
+
+ data, err := os.ReadFile(dir + ".info")
+ info, err2 := os.Stat(dir)
+ if err == nil && err2 == nil && info.IsDir() {
+ // Info file and directory both already exist: reuse.
+ have := strings.TrimSuffix(string(data), "\n")
+ if have != key {
+ return "", "", fmt.Errorf("%s exists with wrong content (have %q want %q)", dir+".info", have, key)
+ }
+ if buildX {
+ fmt.Fprintf(xLog, "# %s for %s %s\n", dir, typ, name)
+ }
+ return dir, lockfile, nil
+ }
+
+ // Info file or directory missing. Start from scratch.
+ if xLog != nil {
+ fmt.Fprintf(xLog, "mkdir -p %s # %s %s\n", dir, typ, name)
+ }
+ os.RemoveAll(dir)
+ if err := os.MkdirAll(dir, 0777); err != nil {
+ return "", "", err
+ }
+ if err := os.WriteFile(dir+".info", []byte(key), 0666); err != nil {
+ os.RemoveAll(dir)
+ return "", "", err
+ }
+ return dir, lockfile, nil
+}
+
+type RunError struct {
+ Cmd string
+ Err error
+ Stderr []byte
+ HelpText string
+}
+
+func (e *RunError) Error() string {
+ text := e.Cmd + ": " + e.Err.Error()
+ stderr := bytes.TrimRight(e.Stderr, "\n")
+ if len(stderr) > 0 {
+ text += ":\n\t" + strings.ReplaceAll(string(stderr), "\n", "\n\t")
+ }
+ if len(e.HelpText) > 0 {
+ text += "\n" + e.HelpText
+ }
+ return text
+}
+
+var dirLock sync.Map
+
+// Run runs the command line in the given directory
+// (an empty dir means the current directory).
+// It returns the standard output and, for a non-zero exit,
+// a *RunError indicating the command, exit status, and standard error.
+// Standard error is unavailable for commands that exit successfully.
+func Run(ctx context.Context, dir string, cmdline ...any) ([]byte, error) {
+ return RunWithStdin(ctx, dir, nil, cmdline...)
+}
+
+// bashQuoter escapes characters that have special meaning in double-quoted strings in the bash shell.
+// See https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html.
+var bashQuoter = strings.NewReplacer(`"`, `\"`, `$`, `\$`, "`", "\\`", `\`, `\\`)
+
+func RunWithStdin(ctx context.Context, dir string, stdin io.Reader, cmdline ...any) ([]byte, error) {
+ if dir != "" {
+ muIface, ok := dirLock.Load(dir)
+ if !ok {
+ muIface, _ = dirLock.LoadOrStore(dir, new(sync.Mutex))
+ }
+ mu := muIface.(*sync.Mutex)
+ mu.Lock()
+ defer mu.Unlock()
+ }
+
+ cmd := str.StringList(cmdline...)
+ if os.Getenv("TESTGOVCS") == "panic" {
+ panic(fmt.Sprintf("use of vcs: %v", cmd))
+ }
+ if xLog, ok := cfg.BuildXWriter(ctx); ok {
+ text := new(strings.Builder)
+ if dir != "" {
+ text.WriteString("cd ")
+ text.WriteString(dir)
+ text.WriteString("; ")
+ }
+ for i, arg := range cmd {
+ if i > 0 {
+ text.WriteByte(' ')
+ }
+ switch {
+ case strings.ContainsAny(arg, "'"):
+ // Quote args that could be mistaken for quoted args.
+ text.WriteByte('"')
+ text.WriteString(bashQuoter.Replace(arg))
+ text.WriteByte('"')
+ case strings.ContainsAny(arg, "$`\\*?[\"\t\n\v\f\r \u0085\u00a0"):
+ // Quote args that contain special characters, glob patterns, or spaces.
+ text.WriteByte('\'')
+ text.WriteString(arg)
+ text.WriteByte('\'')
+ default:
+ text.WriteString(arg)
+ }
+ }
+ fmt.Fprintf(xLog, "%s\n", text)
+ start := time.Now()
+ defer func() {
+ fmt.Fprintf(xLog, "%.3fs # %s\n", time.Since(start).Seconds(), text)
+ }()
+ }
+ // TODO: Impose limits on command output size.
+ // TODO: Set environment to get English error messages.
+ var stderr bytes.Buffer
+ var stdout bytes.Buffer
+ c := exec.CommandContext(ctx, cmd[0], cmd[1:]...)
+ c.Cancel = func() error { return c.Process.Signal(os.Interrupt) }
+ c.Dir = dir
+ c.Stdin = stdin
+ c.Stderr = &stderr
+ c.Stdout = &stdout
+ // For Git commands, manually supply GIT_DIR so Git works with safe.bareRepository=explicit set. Noop for other commands.
+ c.Env = append(c.Environ(), "GIT_DIR="+dir)
+ err := c.Run()
+ if err != nil {
+ err = &RunError{Cmd: strings.Join(cmd, " ") + " in " + dir, Stderr: stderr.Bytes(), Err: err}
+ }
+ return stdout.Bytes(), err
+}
diff --git a/src/cmd/go/internal/modfetch/codehost/git.go b/src/cmd/go/internal/modfetch/codehost/git.go
new file mode 100644
index 0000000..7d9e5d8
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/codehost/git.go
@@ -0,0 +1,925 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codehost
+
+import (
+ "bytes"
+ "context"
+ "crypto/sha256"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io"
+ "io/fs"
+ "net/url"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "slices"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/lockedfile"
+ "cmd/go/internal/par"
+ "cmd/go/internal/web"
+
+ "golang.org/x/mod/semver"
+)
+
+// LocalGitRepo is like Repo but accepts both Git remote references
+// and paths to repositories on the local file system.
+func LocalGitRepo(ctx context.Context, remote string) (Repo, error) {
+ return newGitRepoCached(ctx, remote, true)
+}
+
+// A notExistError wraps another error to retain its original text
+// but makes it opaquely equivalent to fs.ErrNotExist.
+type notExistError struct {
+ err error
+}
+
+func (e notExistError) Error() string { return e.err.Error() }
+func (notExistError) Is(err error) bool { return err == fs.ErrNotExist }
+
+const gitWorkDirType = "git3"
+
+var gitRepoCache par.ErrCache[gitCacheKey, Repo]
+
+type gitCacheKey struct {
+ remote string
+ localOK bool
+}
+
+func newGitRepoCached(ctx context.Context, remote string, localOK bool) (Repo, error) {
+ return gitRepoCache.Do(gitCacheKey{remote, localOK}, func() (Repo, error) {
+ return newGitRepo(ctx, remote, localOK)
+ })
+}
+
+func newGitRepo(ctx context.Context, remote string, localOK bool) (Repo, error) {
+ r := &gitRepo{remote: remote}
+ if strings.Contains(remote, "://") {
+ // This is a remote path.
+ var err error
+ r.dir, r.mu.Path, err = WorkDir(ctx, gitWorkDirType, r.remote)
+ if err != nil {
+ return nil, err
+ }
+
+ unlock, err := r.mu.Lock()
+ if err != nil {
+ return nil, err
+ }
+ defer unlock()
+
+ if _, err := os.Stat(filepath.Join(r.dir, "objects")); err != nil {
+ if _, err := Run(ctx, r.dir, "git", "init", "--bare"); err != nil {
+ os.RemoveAll(r.dir)
+ return nil, err
+ }
+ // We could just say git fetch https://whatever later,
+ // but this lets us say git fetch origin instead, which
+ // is a little nicer. More importantly, using a named remote
+ // avoids a problem with Git LFS. See golang.org/issue/25605.
+ if _, err := Run(ctx, r.dir, "git", "remote", "add", "origin", "--", r.remote); err != nil {
+ os.RemoveAll(r.dir)
+ return nil, err
+ }
+ if runtime.GOOS == "windows" {
+ // Git for Windows by default does not support paths longer than
+ // MAX_PATH (260 characters) because that may interfere with navigation
+ // in some Windows programs. However, cmd/go should be able to handle
+ // long paths just fine, and we expect people to use 'go clean' to
+ // manipulate the module cache, so it should be harmless to set here,
+ // and in some cases may be necessary in order to download modules with
+ // long branch names.
+ //
+ // See https://github.com/git-for-windows/git/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path.
+ if _, err := Run(ctx, r.dir, "git", "config", "core.longpaths", "true"); err != nil {
+ os.RemoveAll(r.dir)
+ return nil, err
+ }
+ }
+ }
+ r.remoteURL = r.remote
+ r.remote = "origin"
+ } else {
+ // Local path.
+ // Disallow colon (not in ://) because sometimes
+ // that's rcp-style host:path syntax and sometimes it's not (c:\work).
+ // The go command has always insisted on URL syntax for ssh.
+ if strings.Contains(remote, ":") {
+ return nil, fmt.Errorf("git remote cannot use host:path syntax")
+ }
+ if !localOK {
+ return nil, fmt.Errorf("git remote must not be local directory")
+ }
+ r.local = true
+ info, err := os.Stat(remote)
+ if err != nil {
+ return nil, err
+ }
+ if !info.IsDir() {
+ return nil, fmt.Errorf("%s exists but is not a directory", remote)
+ }
+ r.dir = remote
+ r.mu.Path = r.dir + ".lock"
+ }
+ return r, nil
+}
+
+type gitRepo struct {
+ ctx context.Context
+
+ remote, remoteURL string
+ local bool
+ dir string
+
+ mu lockedfile.Mutex // protects fetchLevel and git repo state
+
+ fetchLevel int
+
+ statCache par.ErrCache[string, *RevInfo]
+
+ refsOnce sync.Once
+ // refs maps branch and tag refs (e.g., "HEAD", "refs/heads/master")
+ // to commits (e.g., "37ffd2e798afde829a34e8955b716ab730b2a6d6")
+ refs map[string]string
+ refsErr error
+
+ localTagsOnce sync.Once
+ localTags sync.Map // map[string]bool
+}
+
+const (
+ // How much have we fetched into the git repo (in this process)?
+ fetchNone = iota // nothing yet
+ fetchSome // shallow fetches of individual hashes
+ fetchAll // "fetch -t origin": get all remote branches and tags
+)
+
+// loadLocalTags loads tag references from the local git cache
+// into the map r.localTags.
+func (r *gitRepo) loadLocalTags(ctx context.Context) {
+ // The git protocol sends all known refs and ls-remote filters them on the client side,
+ // so we might as well record both heads and tags in one shot.
+ // Most of the time we only care about tags but sometimes we care about heads too.
+ out, err := Run(ctx, r.dir, "git", "tag", "-l")
+ if err != nil {
+ return
+ }
+
+ for _, line := range strings.Split(string(out), "\n") {
+ if line != "" {
+ r.localTags.Store(line, true)
+ }
+ }
+}
+
+func (r *gitRepo) CheckReuse(ctx context.Context, old *Origin, subdir string) error {
+ if old == nil {
+ return fmt.Errorf("missing origin")
+ }
+ if old.VCS != "git" || old.URL != r.remoteURL {
+ return fmt.Errorf("origin moved from %v %q to %v %q", old.VCS, old.URL, "git", r.remoteURL)
+ }
+ if old.Subdir != subdir {
+ return fmt.Errorf("origin moved from %v %q %q to %v %q %q", old.VCS, old.URL, old.Subdir, "git", r.remoteURL, subdir)
+ }
+
+ // Note: Can have Hash with no Ref and no TagSum and no RepoSum,
+ // meaning the Hash simply has to remain in the repo.
+ // In that case we assume it does in the absence of any real way to check.
+ // But if neither Hash nor TagSum is present, we have nothing to check,
+ // which we take to mean we didn't record enough information to be sure.
+ if old.Hash == "" && old.TagSum == "" && old.RepoSum == "" {
+ return fmt.Errorf("non-specific origin")
+ }
+
+ r.loadRefs(ctx)
+ if r.refsErr != nil {
+ return r.refsErr
+ }
+
+ if old.Ref != "" {
+ hash, ok := r.refs[old.Ref]
+ if !ok {
+ return fmt.Errorf("ref %q deleted", old.Ref)
+ }
+ if hash != old.Hash {
+ return fmt.Errorf("ref %q moved from %s to %s", old.Ref, old.Hash, hash)
+ }
+ }
+ if old.TagSum != "" {
+ tags, err := r.Tags(ctx, old.TagPrefix)
+ if err != nil {
+ return err
+ }
+ if tags.Origin.TagSum != old.TagSum {
+ return fmt.Errorf("tags changed")
+ }
+ }
+ if old.RepoSum != "" {
+ if r.repoSum(r.refs) != old.RepoSum {
+ return fmt.Errorf("refs changed")
+ }
+ }
+ return nil
+}
+
+// loadRefs loads heads and tags references from the remote into the map r.refs.
+// The result is cached in memory.
+func (r *gitRepo) loadRefs(ctx context.Context) (map[string]string, error) {
+ r.refsOnce.Do(func() {
+ // The git protocol sends all known refs and ls-remote filters them on the client side,
+ // so we might as well record both heads and tags in one shot.
+ // Most of the time we only care about tags but sometimes we care about heads too.
+ release, err := base.AcquireNet()
+ if err != nil {
+ r.refsErr = err
+ return
+ }
+ out, gitErr := Run(ctx, r.dir, "git", "ls-remote", "-q", r.remote)
+ release()
+
+ if gitErr != nil {
+ if rerr, ok := gitErr.(*RunError); ok {
+ if bytes.Contains(rerr.Stderr, []byte("fatal: could not read Username")) {
+ rerr.HelpText = "Confirm the import path was entered correctly.\nIf this is a private repository, see https://golang.org/doc/faq#git_https for additional information."
+ }
+ }
+
+ // If the remote URL doesn't exist at all, ideally we should treat the whole
+ // repository as nonexistent by wrapping the error in a notExistError.
+ // For HTTP and HTTPS, that's easy to detect: we'll try to fetch the URL
+ // ourselves and see what code it serves.
+ if u, err := url.Parse(r.remoteURL); err == nil && (u.Scheme == "http" || u.Scheme == "https") {
+ if _, err := web.GetBytes(u); errors.Is(err, fs.ErrNotExist) {
+ gitErr = notExistError{gitErr}
+ }
+ }
+
+ r.refsErr = gitErr
+ return
+ }
+
+ refs := make(map[string]string)
+ for _, line := range strings.Split(string(out), "\n") {
+ f := strings.Fields(line)
+ if len(f) != 2 {
+ continue
+ }
+ if f[1] == "HEAD" || strings.HasPrefix(f[1], "refs/heads/") || strings.HasPrefix(f[1], "refs/tags/") {
+ refs[f[1]] = f[0]
+ }
+ }
+ for ref, hash := range refs {
+ if k, found := strings.CutSuffix(ref, "^{}"); found { // record unwrapped annotated tag as value of tag
+ refs[k] = hash
+ delete(refs, ref)
+ }
+ }
+ r.refs = refs
+ })
+ return r.refs, r.refsErr
+}
+
+func (r *gitRepo) Tags(ctx context.Context, prefix string) (*Tags, error) {
+ refs, err := r.loadRefs(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ tags := &Tags{
+ Origin: &Origin{
+ VCS: "git",
+ URL: r.remoteURL,
+ TagPrefix: prefix,
+ },
+ List: []Tag{},
+ }
+ for ref, hash := range refs {
+ if !strings.HasPrefix(ref, "refs/tags/") {
+ continue
+ }
+ tag := ref[len("refs/tags/"):]
+ if !strings.HasPrefix(tag, prefix) {
+ continue
+ }
+ tags.List = append(tags.List, Tag{tag, hash})
+ }
+ sort.Slice(tags.List, func(i, j int) bool {
+ return tags.List[i].Name < tags.List[j].Name
+ })
+
+ dir := prefix[:strings.LastIndex(prefix, "/")+1]
+ h := sha256.New()
+ for _, tag := range tags.List {
+ if isOriginTag(strings.TrimPrefix(tag.Name, dir)) {
+ fmt.Fprintf(h, "%q %s\n", tag.Name, tag.Hash)
+ }
+ }
+ tags.Origin.TagSum = "t1:" + base64.StdEncoding.EncodeToString(h.Sum(nil))
+ return tags, nil
+}
+
+// repoSum returns a checksum of the entire repo state,
+// which can be checked (as Origin.RepoSum) to cache
+// the absence of a specific module version.
+// The caller must supply refs, the result of a successful r.loadRefs.
+func (r *gitRepo) repoSum(refs map[string]string) string {
+ var list []string
+ for ref := range refs {
+ list = append(list, ref)
+ }
+ sort.Strings(list)
+ h := sha256.New()
+ for _, ref := range list {
+ fmt.Fprintf(h, "%q %s\n", ref, refs[ref])
+ }
+ return "r1:" + base64.StdEncoding.EncodeToString(h.Sum(nil))
+}
+
+// unknownRevisionInfo returns a RevInfo containing an Origin containing a RepoSum of refs,
+// for use when returning an UnknownRevisionError.
+func (r *gitRepo) unknownRevisionInfo(refs map[string]string) *RevInfo {
+ return &RevInfo{
+ Origin: &Origin{
+ VCS: "git",
+ URL: r.remoteURL,
+ RepoSum: r.repoSum(refs),
+ },
+ }
+}
+
+func (r *gitRepo) Latest(ctx context.Context) (*RevInfo, error) {
+ refs, err := r.loadRefs(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if refs["HEAD"] == "" {
+ return nil, ErrNoCommits
+ }
+ statInfo, err := r.Stat(ctx, refs["HEAD"])
+ if err != nil {
+ return nil, err
+ }
+
+ // Stat may return cached info, so make a copy to modify here.
+ info := new(RevInfo)
+ *info = *statInfo
+ info.Origin = new(Origin)
+ if statInfo.Origin != nil {
+ *info.Origin = *statInfo.Origin
+ }
+ info.Origin.Ref = "HEAD"
+ info.Origin.Hash = refs["HEAD"]
+
+ return info, nil
+}
+
+// findRef finds some ref name for the given hash,
+// for use when the server requires giving a ref instead of a hash.
+// There may be multiple ref names for a given hash,
+// in which case this returns some name - it doesn't matter which.
+func (r *gitRepo) findRef(ctx context.Context, hash string) (ref string, ok bool) {
+ refs, err := r.loadRefs(ctx)
+ if err != nil {
+ return "", false
+ }
+ for ref, h := range refs {
+ if h == hash {
+ return ref, true
+ }
+ }
+ return "", false
+}
+
+// minHashDigits is the minimum number of digits to require
+// before accepting a hex digit sequence as potentially identifying
+// a specific commit in a git repo. (Of course, users can always
+// specify more digits, and many will paste in all 40 digits,
+// but many of git's commands default to printing short hashes
+// as 7 digits.)
+const minHashDigits = 7
+
+// stat stats the given rev in the local repository,
+// or else it fetches more info from the remote repository and tries again.
+func (r *gitRepo) stat(ctx context.Context, rev string) (info *RevInfo, err error) {
+ if r.local {
+ return r.statLocal(ctx, rev, rev)
+ }
+
+ // Fast path: maybe rev is a hash we already have locally.
+ didStatLocal := false
+ if len(rev) >= minHashDigits && len(rev) <= 40 && AllHex(rev) {
+ if info, err := r.statLocal(ctx, rev, rev); err == nil {
+ return info, nil
+ }
+ didStatLocal = true
+ }
+
+ // Maybe rev is a tag we already have locally.
+ // (Note that we're excluding branches, which can be stale.)
+ r.localTagsOnce.Do(func() { r.loadLocalTags(ctx) })
+ if _, ok := r.localTags.Load(rev); ok {
+ return r.statLocal(ctx, rev, "refs/tags/"+rev)
+ }
+
+ // Maybe rev is the name of a tag or branch on the remote server.
+ // Or maybe it's the prefix of a hash of a named ref.
+ // Try to resolve to both a ref (git name) and full (40-hex-digit) commit hash.
+ refs, err := r.loadRefs(ctx)
+ if err != nil {
+ return nil, err
+ }
+ // loadRefs may return an error if git fails, for example segfaults, or
+ // could not load a private repo, but defer checking to the else block
+ // below, in case we already have the rev in question in the local cache.
+ var ref, hash string
+ if refs["refs/tags/"+rev] != "" {
+ ref = "refs/tags/" + rev
+ hash = refs[ref]
+ // Keep rev as is: tags are assumed not to change meaning.
+ } else if refs["refs/heads/"+rev] != "" {
+ ref = "refs/heads/" + rev
+ hash = refs[ref]
+ rev = hash // Replace rev, because meaning of refs/heads/foo can change.
+ } else if rev == "HEAD" && refs["HEAD"] != "" {
+ ref = "HEAD"
+ hash = refs[ref]
+ rev = hash // Replace rev, because meaning of HEAD can change.
+ } else if len(rev) >= minHashDigits && len(rev) <= 40 && AllHex(rev) {
+ // At the least, we have a hash prefix we can look up after the fetch below.
+ // Maybe we can map it to a full hash using the known refs.
+ prefix := rev
+ // Check whether rev is prefix of known ref hash.
+ for k, h := range refs {
+ if strings.HasPrefix(h, prefix) {
+ if hash != "" && hash != h {
+ // Hash is an ambiguous hash prefix.
+ // More information will not change that.
+ return nil, fmt.Errorf("ambiguous revision %s", rev)
+ }
+ if ref == "" || ref > k { // Break ties deterministically when multiple refs point at same hash.
+ ref = k
+ }
+ rev = h
+ hash = h
+ }
+ }
+ if hash == "" && len(rev) == 40 { // Didn't find a ref, but rev is a full hash.
+ hash = rev
+ }
+ } else {
+ return r.unknownRevisionInfo(refs), &UnknownRevisionError{Rev: rev}
+ }
+
+ defer func() {
+ if info != nil {
+ info.Origin.Hash = info.Name
+ // There's a ref = hash below; don't write that hash down as Origin.Ref.
+ if ref != info.Origin.Hash {
+ info.Origin.Ref = ref
+ }
+ }
+ }()
+
+ // Protect r.fetchLevel and the "fetch more and more" sequence.
+ unlock, err := r.mu.Lock()
+ if err != nil {
+ return nil, err
+ }
+ defer unlock()
+
+ // Perhaps r.localTags did not have the ref when we loaded local tags,
+ // but we've since done fetches that pulled down the hash we need
+ // (or already have the hash we need, just without its tag).
+ // Either way, try a local stat before falling back to network I/O.
+ if !didStatLocal {
+ if info, err := r.statLocal(ctx, rev, hash); err == nil {
+ tag, fromTag := strings.CutPrefix(ref, "refs/tags/")
+ if fromTag && !slices.Contains(info.Tags, tag) {
+ // The local repo includes the commit hash we want, but it is missing
+ // the corresponding tag. Add that tag and try again.
+ _, err := Run(ctx, r.dir, "git", "tag", tag, hash)
+ if err != nil {
+ return nil, err
+ }
+ r.localTags.Store(tag, true)
+ return r.statLocal(ctx, rev, ref)
+ }
+ return info, err
+ }
+ }
+
+ // If we know a specific commit we need and its ref, fetch it.
+ // We do NOT fetch arbitrary hashes (when we don't know the ref)
+ // because we want to avoid ever importing a commit that isn't
+ // reachable from refs/tags/* or refs/heads/* or HEAD.
+ // Both Gerrit and GitHub expose every CL/PR as a named ref,
+ // and we don't want those commits masquerading as being real
+ // pseudo-versions in the main repo.
+ if r.fetchLevel <= fetchSome && ref != "" && hash != "" && !r.local {
+ r.fetchLevel = fetchSome
+ var refspec string
+ if ref == "HEAD" {
+ // Fetch the hash but give it a local name (refs/dummy),
+ // because that triggers the fetch behavior of creating any
+ // other known remote tags for the hash. We never use
+ // refs/dummy (it's not refs/tags/dummy) and it will be
+ // overwritten in the next command, and that's fine.
+ ref = hash
+ refspec = hash + ":refs/dummy"
+ } else {
+ // If we do know the ref name, save the mapping locally
+ // so that (if it is a tag) it can show up in localTags
+ // on a future call. Also, some servers refuse to allow
+ // full hashes in ref specs, so prefer a ref name if known.
+ refspec = ref + ":" + ref
+ }
+
+ release, err := base.AcquireNet()
+ if err != nil {
+ return nil, err
+ }
+ // We explicitly set protocol.version=2 for this command to work around
+ // an apparent Git bug introduced in Git 2.21 (commit 61c771),
+ // which causes the handler for protocol version 1 to sometimes miss
+ // tags that point to the requested commit (see https://go.dev/issue/56881).
+ _, err = Run(ctx, r.dir, "git", "fetch", "-f", "-c", "protocol.version=2", "--depth=1", r.remote, refspec)
+ release()
+
+ if err == nil {
+ return r.statLocal(ctx, rev, ref)
+ }
+ // Don't try to be smart about parsing the error.
+ // It's too complex and varies too much by git version.
+ // No matter what went wrong, fall back to a complete fetch.
+ }
+
+ // Last resort.
+ // Fetch all heads and tags and hope the hash we want is in the history.
+ if err := r.fetchRefsLocked(ctx); err != nil {
+ return nil, err
+ }
+
+ return r.statLocal(ctx, rev, rev)
+}
+
+// fetchRefsLocked fetches all heads and tags from the origin, along with the
+// ancestors of those commits.
+//
+// We only fetch heads and tags, not arbitrary other commits: we don't want to
+// pull in off-branch commits (such as rejected GitHub pull requests) that the
+// server may be willing to provide. (See the comments within the stat method
+// for more detail.)
+//
+// fetchRefsLocked requires that r.mu remain locked for the duration of the call.
+func (r *gitRepo) fetchRefsLocked(ctx context.Context) error {
+ if r.fetchLevel < fetchAll {
+ // NOTE: To work around a bug affecting Git clients up to at least 2.23.0
+ // (2019-08-16), we must first expand the set of local refs, and only then
+ // unshallow the repository as a separate fetch operation. (See
+ // golang.org/issue/34266 and
+ // https://github.com/git/git/blob/4c86140027f4a0d2caaa3ab4bd8bfc5ce3c11c8a/transport.c#L1303-L1309.)
+
+ release, err := base.AcquireNet()
+ if err != nil {
+ return err
+ }
+ defer release()
+
+ if _, err := Run(ctx, r.dir, "git", "fetch", "-f", r.remote, "refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil {
+ return err
+ }
+
+ if _, err := os.Stat(filepath.Join(r.dir, "shallow")); err == nil {
+ if _, err := Run(ctx, r.dir, "git", "fetch", "--unshallow", "-f", r.remote); err != nil {
+ return err
+ }
+ }
+
+ r.fetchLevel = fetchAll
+ }
+ return nil
+}
+
+// statLocal returns a new RevInfo describing rev in the local git repository.
+// It uses version as info.Version.
+func (r *gitRepo) statLocal(ctx context.Context, version, rev string) (*RevInfo, error) {
+ out, err := Run(ctx, r.dir, "git", "-c", "log.showsignature=false", "log", "--no-decorate", "-n1", "--format=format:%H %ct %D", rev, "--")
+ if err != nil {
+ // Return info with Origin.RepoSum if possible to allow caching of negative lookup.
+ var info *RevInfo
+ if refs, err := r.loadRefs(ctx); err == nil {
+ info = r.unknownRevisionInfo(refs)
+ }
+ return info, &UnknownRevisionError{Rev: rev}
+ }
+ f := strings.Fields(string(out))
+ if len(f) < 2 {
+ return nil, fmt.Errorf("unexpected response from git log: %q", out)
+ }
+ hash := f[0]
+ if strings.HasPrefix(hash, version) {
+ version = hash // extend to full hash
+ }
+ t, err := strconv.ParseInt(f[1], 10, 64)
+ if err != nil {
+ return nil, fmt.Errorf("invalid time from git log: %q", out)
+ }
+
+ info := &RevInfo{
+ Origin: &Origin{
+ VCS: "git",
+ URL: r.remoteURL,
+ Hash: hash,
+ },
+ Name: hash,
+ Short: ShortenSHA1(hash),
+ Time: time.Unix(t, 0).UTC(),
+ Version: hash,
+ }
+ if !strings.HasPrefix(hash, rev) {
+ info.Origin.Ref = rev
+ }
+
+ // Add tags. Output looks like:
+ // ede458df7cd0fdca520df19a33158086a8a68e81 1523994202 HEAD -> master, tag: v1.2.4-annotated, tag: v1.2.3, origin/master, origin/HEAD
+ for i := 2; i < len(f); i++ {
+ if f[i] == "tag:" {
+ i++
+ if i < len(f) {
+ info.Tags = append(info.Tags, strings.TrimSuffix(f[i], ","))
+ }
+ }
+ }
+ sort.Strings(info.Tags)
+
+ // Used hash as info.Version above.
+ // Use caller's suggested version if it appears in the tag list
+ // (filters out branch names, HEAD).
+ for _, tag := range info.Tags {
+ if version == tag {
+ info.Version = version
+ }
+ }
+
+ return info, nil
+}
+
+func (r *gitRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
+ if rev == "latest" {
+ return r.Latest(ctx)
+ }
+ return r.statCache.Do(rev, func() (*RevInfo, error) {
+ return r.stat(ctx, rev)
+ })
+}
+
+func (r *gitRepo) ReadFile(ctx context.Context, rev, file string, maxSize int64) ([]byte, error) {
+ // TODO: Could use git cat-file --batch.
+ info, err := r.Stat(ctx, rev) // download rev into local git repo
+ if err != nil {
+ return nil, err
+ }
+ out, err := Run(ctx, r.dir, "git", "cat-file", "blob", info.Name+":"+file)
+ if err != nil {
+ return nil, fs.ErrNotExist
+ }
+ return out, nil
+}
+
+func (r *gitRepo) RecentTag(ctx context.Context, rev, prefix string, allowed func(tag string) bool) (tag string, err error) {
+ info, err := r.Stat(ctx, rev)
+ if err != nil {
+ return "", err
+ }
+ rev = info.Name // expand hash prefixes
+
+ // describe sets tag and err using 'git for-each-ref' and reports whether the
+ // result is definitive.
+ describe := func() (definitive bool) {
+ var out []byte
+ out, err = Run(ctx, r.dir, "git", "for-each-ref", "--format", "%(refname)", "refs/tags", "--merged", rev)
+ if err != nil {
+ return true
+ }
+
+ // prefixed tags aren't valid semver tags so compare without prefix, but only tags with correct prefix
+ var highest string
+ for _, line := range strings.Split(string(out), "\n") {
+ line = strings.TrimSpace(line)
+ // git do support lstrip in for-each-ref format, but it was added in v2.13.0. Stripping here
+ // instead gives support for git v2.7.0.
+ if !strings.HasPrefix(line, "refs/tags/") {
+ continue
+ }
+ line = line[len("refs/tags/"):]
+
+ if !strings.HasPrefix(line, prefix) {
+ continue
+ }
+ if !allowed(line) {
+ continue
+ }
+
+ semtag := line[len(prefix):]
+ if semver.Compare(semtag, highest) > 0 {
+ highest = semtag
+ }
+ }
+
+ if highest != "" {
+ tag = prefix + highest
+ }
+
+ return tag != "" && !AllHex(tag)
+ }
+
+ if describe() {
+ return tag, err
+ }
+
+ // Git didn't find a version tag preceding the requested rev.
+ // See whether any plausible tag exists.
+ tags, err := r.Tags(ctx, prefix+"v")
+ if err != nil {
+ return "", err
+ }
+ if len(tags.List) == 0 {
+ return "", nil
+ }
+
+ // There are plausible tags, but we don't know if rev is a descendent of any of them.
+ // Fetch the history to find out.
+
+ unlock, err := r.mu.Lock()
+ if err != nil {
+ return "", err
+ }
+ defer unlock()
+
+ if err := r.fetchRefsLocked(ctx); err != nil {
+ return "", err
+ }
+
+ // If we've reached this point, we have all of the commits that are reachable
+ // from all heads and tags.
+ //
+ // The only refs we should be missing are those that are no longer reachable
+ // (or never were reachable) from any branch or tag, including the master
+ // branch, and we don't want to resolve them anyway (they're probably
+ // unreachable for a reason).
+ //
+ // Try one last time in case some other goroutine fetched rev while we were
+ // waiting on the lock.
+ describe()
+ return tag, err
+}
+
+func (r *gitRepo) DescendsFrom(ctx context.Context, rev, tag string) (bool, error) {
+ // The "--is-ancestor" flag was added to "git merge-base" in version 1.8.0, so
+ // this won't work with Git 1.7.1. According to golang.org/issue/28550, cmd/go
+ // already doesn't work with Git 1.7.1, so at least it's not a regression.
+ //
+ // git merge-base --is-ancestor exits with status 0 if rev is an ancestor, or
+ // 1 if not.
+ _, err := Run(ctx, r.dir, "git", "merge-base", "--is-ancestor", "--", tag, rev)
+
+ // Git reports "is an ancestor" with exit code 0 and "not an ancestor" with
+ // exit code 1.
+ // Unfortunately, if we've already fetched rev with a shallow history, git
+ // merge-base has been observed to report a false-negative, so don't stop yet
+ // even if the exit code is 1!
+ if err == nil {
+ return true, nil
+ }
+
+ // See whether the tag and rev even exist.
+ tags, err := r.Tags(ctx, tag)
+ if err != nil {
+ return false, err
+ }
+ if len(tags.List) == 0 {
+ return false, nil
+ }
+
+ // NOTE: r.stat is very careful not to fetch commits that we shouldn't know
+ // about, like rejected GitHub pull requests, so don't try to short-circuit
+ // that here.
+ if _, err = r.stat(ctx, rev); err != nil {
+ return false, err
+ }
+
+ // Now fetch history so that git can search for a path.
+ unlock, err := r.mu.Lock()
+ if err != nil {
+ return false, err
+ }
+ defer unlock()
+
+ if r.fetchLevel < fetchAll {
+ // Fetch the complete history for all refs and heads. It would be more
+ // efficient to only fetch the history from rev to tag, but that's much more
+ // complicated, and any kind of shallow fetch is fairly likely to trigger
+ // bugs in JGit servers and/or the go command anyway.
+ if err := r.fetchRefsLocked(ctx); err != nil {
+ return false, err
+ }
+ }
+
+ _, err = Run(ctx, r.dir, "git", "merge-base", "--is-ancestor", "--", tag, rev)
+ if err == nil {
+ return true, nil
+ }
+ if ee, ok := err.(*RunError).Err.(*exec.ExitError); ok && ee.ExitCode() == 1 {
+ return false, nil
+ }
+ return false, err
+}
+
+func (r *gitRepo) ReadZip(ctx context.Context, rev, subdir string, maxSize int64) (zip io.ReadCloser, err error) {
+ // TODO: Use maxSize or drop it.
+ args := []string{}
+ if subdir != "" {
+ args = append(args, "--", subdir)
+ }
+ info, err := r.Stat(ctx, rev) // download rev into local git repo
+ if err != nil {
+ return nil, err
+ }
+
+ unlock, err := r.mu.Lock()
+ if err != nil {
+ return nil, err
+ }
+ defer unlock()
+
+ if err := ensureGitAttributes(r.dir); err != nil {
+ return nil, err
+ }
+
+ // Incredibly, git produces different archives depending on whether
+ // it is running on a Windows system or not, in an attempt to normalize
+ // text file line endings. Setting -c core.autocrlf=input means only
+ // translate files on the way into the repo, not on the way out (archive).
+ // The -c core.eol=lf should be unnecessary but set it anyway.
+ archive, err := Run(ctx, r.dir, "git", "-c", "core.autocrlf=input", "-c", "core.eol=lf", "archive", "--format=zip", "--prefix=prefix/", info.Name, args)
+ if err != nil {
+ if bytes.Contains(err.(*RunError).Stderr, []byte("did not match any files")) {
+ return nil, fs.ErrNotExist
+ }
+ return nil, err
+ }
+
+ return io.NopCloser(bytes.NewReader(archive)), nil
+}
+
+// ensureGitAttributes makes sure export-subst and export-ignore features are
+// disabled for this repo. This is intended to be run prior to running git
+// archive so that zip files are generated that produce consistent ziphashes
+// for a given revision, independent of variables such as git version and the
+// size of the repo.
+//
+// See: https://github.com/golang/go/issues/27153
+func ensureGitAttributes(repoDir string) (err error) {
+ const attr = "\n* -export-subst -export-ignore\n"
+
+ d := repoDir + "/info"
+ p := d + "/attributes"
+
+ if err := os.MkdirAll(d, 0755); err != nil {
+ return err
+ }
+
+ f, err := os.OpenFile(p, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ closeErr := f.Close()
+ if closeErr != nil {
+ err = closeErr
+ }
+ }()
+
+ b, err := io.ReadAll(f)
+ if err != nil {
+ return err
+ }
+ if !bytes.HasSuffix(b, []byte(attr)) {
+ _, err := f.WriteString(attr)
+ return err
+ }
+
+ return nil
+}
diff --git a/src/cmd/go/internal/modfetch/codehost/git_test.go b/src/cmd/go/internal/modfetch/codehost/git_test.go
new file mode 100644
index 0000000..dba9935
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/codehost/git_test.go
@@ -0,0 +1,795 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codehost
+
+import (
+ "archive/zip"
+ "bytes"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/vcweb/vcstest"
+ "context"
+ "flag"
+ "internal/testenv"
+ "io"
+ "io/fs"
+ "log"
+ "os"
+ "path"
+ "path/filepath"
+ "reflect"
+ "runtime"
+ "strings"
+ "sync"
+ "testing"
+ "time"
+)
+
+func TestMain(m *testing.M) {
+ flag.Parse()
+ if err := testMain(m); err != nil {
+ log.Fatal(err)
+ }
+}
+
+var gitrepo1, hgrepo1, vgotest1 string
+
+var altRepos = func() []string {
+ return []string{
+ "localGitRepo",
+ hgrepo1,
+ }
+}
+
+// TODO: Convert gitrepo1 to svn, bzr, fossil and add tests.
+// For now, at least the hgrepo1 tests check the general vcs.go logic.
+
+// localGitRepo is like gitrepo1 but allows archive access
+// (although that doesn't really matter after CL 120041),
+// and has a file:// URL instead of http:// or https://
+// (which might still matter).
+var localGitRepo string
+
+// localGitURL initializes the repo in localGitRepo and returns its URL.
+func localGitURL(t testing.TB) string {
+ testenv.MustHaveExecPath(t, "git")
+ if runtime.GOOS == "android" && strings.HasSuffix(testenv.Builder(), "-corellium") {
+ testenv.SkipFlaky(t, 59940)
+ }
+
+ localGitURLOnce.Do(func() {
+ // Clone gitrepo1 into a local directory.
+ // If we use a file:// URL to access the local directory,
+ // then git starts up all the usual protocol machinery,
+ // which will let us test remote git archive invocations.
+ _, localGitURLErr = Run(context.Background(), "", "git", "clone", "--mirror", gitrepo1, localGitRepo)
+ if localGitURLErr != nil {
+ return
+ }
+ _, localGitURLErr = Run(context.Background(), localGitRepo, "git", "config", "daemon.uploadarch", "true")
+ })
+
+ if localGitURLErr != nil {
+ t.Fatal(localGitURLErr)
+ }
+ // Convert absolute path to file URL. LocalGitRepo will not accept
+ // Windows absolute paths because they look like a host:path remote.
+ // TODO(golang.org/issue/32456): use url.FromFilePath when implemented.
+ if strings.HasPrefix(localGitRepo, "/") {
+ return "file://" + localGitRepo
+ } else {
+ return "file:///" + filepath.ToSlash(localGitRepo)
+ }
+}
+
+var (
+ localGitURLOnce sync.Once
+ localGitURLErr error
+)
+
+func testMain(m *testing.M) (err error) {
+ cfg.BuildX = testing.Verbose()
+
+ srv, err := vcstest.NewServer()
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if closeErr := srv.Close(); err == nil {
+ err = closeErr
+ }
+ }()
+
+ gitrepo1 = srv.HTTP.URL + "/git/gitrepo1"
+ hgrepo1 = srv.HTTP.URL + "/hg/hgrepo1"
+ vgotest1 = srv.HTTP.URL + "/git/vgotest1"
+
+ dir, err := os.MkdirTemp("", "gitrepo-test-")
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if rmErr := os.RemoveAll(dir); err == nil {
+ err = rmErr
+ }
+ }()
+
+ localGitRepo = filepath.Join(dir, "gitrepo2")
+
+ // Redirect the module cache to a fresh directory to avoid crosstalk, and make
+ // it read/write so that the test can still clean it up easily when done.
+ cfg.GOMODCACHE = filepath.Join(dir, "modcache")
+ cfg.ModCacheRW = true
+
+ m.Run()
+ return nil
+}
+
+func testContext(t testing.TB) context.Context {
+ w := newTestWriter(t)
+ return cfg.WithBuildXWriter(context.Background(), w)
+}
+
+// A testWriter is an io.Writer that writes to a test's log.
+//
+// The writer batches written data until the last byte of a write is a newline
+// character, then flushes the batched data as a single call to Logf.
+// Any remaining unflushed data is logged during Cleanup.
+type testWriter struct {
+ t testing.TB
+
+ mu sync.Mutex
+ buf bytes.Buffer
+}
+
+func newTestWriter(t testing.TB) *testWriter {
+ w := &testWriter{t: t}
+
+ t.Cleanup(func() {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ if b := w.buf.Bytes(); len(b) > 0 {
+ w.t.Logf("%s", b)
+ w.buf.Reset()
+ }
+ })
+
+ return w
+}
+
+func (w *testWriter) Write(p []byte) (int, error) {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ n, err := w.buf.Write(p)
+ if b := w.buf.Bytes(); len(b) > 0 && b[len(b)-1] == '\n' {
+ w.t.Logf("%s", b)
+ w.buf.Reset()
+ }
+ return n, err
+}
+
+func testRepo(ctx context.Context, t *testing.T, remote string) (Repo, error) {
+ if remote == "localGitRepo" {
+ return LocalGitRepo(ctx, localGitURL(t))
+ }
+ vcsName := "git"
+ for _, k := range []string{"hg"} {
+ if strings.Contains(remote, "/"+k+"/") {
+ vcsName = k
+ }
+ }
+ if testing.Short() && vcsName == "hg" {
+ t.Skipf("skipping hg test in short mode: hg is slow")
+ }
+ testenv.MustHaveExecPath(t, vcsName)
+ if runtime.GOOS == "android" && strings.HasSuffix(testenv.Builder(), "-corellium") {
+ testenv.SkipFlaky(t, 59940)
+ }
+ return NewRepo(ctx, vcsName, remote)
+}
+
+func TestTags(t *testing.T) {
+ t.Parallel()
+
+ type tagsTest struct {
+ repo string
+ prefix string
+ tags []Tag
+ }
+
+ runTest := func(tt tagsTest) func(*testing.T) {
+ return func(t *testing.T) {
+ t.Parallel()
+ ctx := testContext(t)
+
+ r, err := testRepo(ctx, t, tt.repo)
+ if err != nil {
+ t.Fatal(err)
+ }
+ tags, err := r.Tags(ctx, tt.prefix)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if tags == nil || !reflect.DeepEqual(tags.List, tt.tags) {
+ t.Errorf("Tags(%q): incorrect tags\nhave %v\nwant %v", tt.prefix, tags, tt.tags)
+ }
+ }
+ }
+
+ for _, tt := range []tagsTest{
+ {gitrepo1, "xxx", []Tag{}},
+ {gitrepo1, "", []Tag{
+ {"v1.2.3", "ede458df7cd0fdca520df19a33158086a8a68e81"},
+ {"v1.2.4-annotated", "ede458df7cd0fdca520df19a33158086a8a68e81"},
+ {"v2.0.1", "76a00fb249b7f93091bc2c89a789dab1fc1bc26f"},
+ {"v2.0.2", "9d02800338b8a55be062c838d1f02e0c5780b9eb"},
+ {"v2.3", "76a00fb249b7f93091bc2c89a789dab1fc1bc26f"},
+ }},
+ {gitrepo1, "v", []Tag{
+ {"v1.2.3", "ede458df7cd0fdca520df19a33158086a8a68e81"},
+ {"v1.2.4-annotated", "ede458df7cd0fdca520df19a33158086a8a68e81"},
+ {"v2.0.1", "76a00fb249b7f93091bc2c89a789dab1fc1bc26f"},
+ {"v2.0.2", "9d02800338b8a55be062c838d1f02e0c5780b9eb"},
+ {"v2.3", "76a00fb249b7f93091bc2c89a789dab1fc1bc26f"},
+ }},
+ {gitrepo1, "v1", []Tag{
+ {"v1.2.3", "ede458df7cd0fdca520df19a33158086a8a68e81"},
+ {"v1.2.4-annotated", "ede458df7cd0fdca520df19a33158086a8a68e81"},
+ }},
+ {gitrepo1, "2", []Tag{}},
+ } {
+ t.Run(path.Base(tt.repo)+"/"+tt.prefix, runTest(tt))
+ if tt.repo == gitrepo1 {
+ // Clear hashes.
+ clearTags := []Tag{}
+ for _, tag := range tt.tags {
+ clearTags = append(clearTags, Tag{tag.Name, ""})
+ }
+ tags := tt.tags
+ for _, tt.repo = range altRepos() {
+ if strings.Contains(tt.repo, "Git") {
+ tt.tags = tags
+ } else {
+ tt.tags = clearTags
+ }
+ t.Run(path.Base(tt.repo)+"/"+tt.prefix, runTest(tt))
+ }
+ }
+ }
+}
+
+func TestLatest(t *testing.T) {
+ t.Parallel()
+
+ type latestTest struct {
+ repo string
+ info *RevInfo
+ }
+ runTest := func(tt latestTest) func(*testing.T) {
+ return func(t *testing.T) {
+ t.Parallel()
+ ctx := testContext(t)
+
+ r, err := testRepo(ctx, t, tt.repo)
+ if err != nil {
+ t.Fatal(err)
+ }
+ info, err := r.Latest(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(info, tt.info) {
+ t.Errorf("Latest: incorrect info\nhave %+v (origin %+v)\nwant %+v (origin %+v)", info, info.Origin, tt.info, tt.info.Origin)
+ }
+ }
+ }
+
+ for _, tt := range []latestTest{
+ {
+ gitrepo1,
+ &RevInfo{
+ Origin: &Origin{
+ VCS: "git",
+ URL: gitrepo1,
+ Ref: "HEAD",
+ Hash: "ede458df7cd0fdca520df19a33158086a8a68e81",
+ },
+ Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
+ Short: "ede458df7cd0",
+ Version: "ede458df7cd0fdca520df19a33158086a8a68e81",
+ Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
+ Tags: []string{"v1.2.3", "v1.2.4-annotated"},
+ },
+ },
+ {
+ hgrepo1,
+ &RevInfo{
+ Origin: &Origin{
+ VCS: "hg",
+ URL: hgrepo1,
+ Hash: "18518c07eb8ed5c80221e997e518cccaa8c0c287",
+ },
+ Name: "18518c07eb8ed5c80221e997e518cccaa8c0c287",
+ Short: "18518c07eb8e",
+ Version: "18518c07eb8ed5c80221e997e518cccaa8c0c287",
+ Time: time.Date(2018, 6, 27, 16, 16, 30, 0, time.UTC),
+ },
+ },
+ } {
+ t.Run(path.Base(tt.repo), runTest(tt))
+ if tt.repo == gitrepo1 {
+ tt.repo = "localGitRepo"
+ info := *tt.info
+ tt.info = &info
+ o := *info.Origin
+ info.Origin = &o
+ o.URL = localGitURL(t)
+ t.Run(path.Base(tt.repo), runTest(tt))
+ }
+ }
+}
+
+func TestReadFile(t *testing.T) {
+ t.Parallel()
+
+ type readFileTest struct {
+ repo string
+ rev string
+ file string
+ err string
+ data string
+ }
+ runTest := func(tt readFileTest) func(*testing.T) {
+ return func(t *testing.T) {
+ t.Parallel()
+ ctx := testContext(t)
+
+ r, err := testRepo(ctx, t, tt.repo)
+ if err != nil {
+ t.Fatal(err)
+ }
+ data, err := r.ReadFile(ctx, tt.rev, tt.file, 100)
+ if err != nil {
+ if tt.err == "" {
+ t.Fatalf("ReadFile: unexpected error %v", err)
+ }
+ if !strings.Contains(err.Error(), tt.err) {
+ t.Fatalf("ReadFile: wrong error %q, want %q", err, tt.err)
+ }
+ if len(data) != 0 {
+ t.Errorf("ReadFile: non-empty data %q with error %v", data, err)
+ }
+ return
+ }
+ if tt.err != "" {
+ t.Fatalf("ReadFile: no error, wanted %v", tt.err)
+ }
+ if string(data) != tt.data {
+ t.Errorf("ReadFile: incorrect data\nhave %q\nwant %q", data, tt.data)
+ }
+ }
+ }
+
+ for _, tt := range []readFileTest{
+ {
+ repo: gitrepo1,
+ rev: "latest",
+ file: "README",
+ data: "",
+ },
+ {
+ repo: gitrepo1,
+ rev: "v2",
+ file: "another.txt",
+ data: "another\n",
+ },
+ {
+ repo: gitrepo1,
+ rev: "v2.3.4",
+ file: "another.txt",
+ err: fs.ErrNotExist.Error(),
+ },
+ } {
+ t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.file, runTest(tt))
+ if tt.repo == gitrepo1 {
+ for _, tt.repo = range altRepos() {
+ t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.file, runTest(tt))
+ }
+ }
+ }
+}
+
+type zipFile struct {
+ name string
+ size int64
+}
+
+func TestReadZip(t *testing.T) {
+ t.Parallel()
+
+ type readZipTest struct {
+ repo string
+ rev string
+ subdir string
+ err string
+ files map[string]uint64
+ }
+ runTest := func(tt readZipTest) func(*testing.T) {
+ return func(t *testing.T) {
+ t.Parallel()
+ ctx := testContext(t)
+
+ r, err := testRepo(ctx, t, tt.repo)
+ if err != nil {
+ t.Fatal(err)
+ }
+ rc, err := r.ReadZip(ctx, tt.rev, tt.subdir, 100000)
+ if err != nil {
+ if tt.err == "" {
+ t.Fatalf("ReadZip: unexpected error %v", err)
+ }
+ if !strings.Contains(err.Error(), tt.err) {
+ t.Fatalf("ReadZip: wrong error %q, want %q", err, tt.err)
+ }
+ if rc != nil {
+ t.Errorf("ReadZip: non-nil io.ReadCloser with error %v", err)
+ }
+ return
+ }
+ defer rc.Close()
+ if tt.err != "" {
+ t.Fatalf("ReadZip: no error, wanted %v", tt.err)
+ }
+ zipdata, err := io.ReadAll(rc)
+ if err != nil {
+ t.Fatal(err)
+ }
+ z, err := zip.NewReader(bytes.NewReader(zipdata), int64(len(zipdata)))
+ if err != nil {
+ t.Fatalf("ReadZip: cannot read zip file: %v", err)
+ }
+ have := make(map[string]bool)
+ for _, f := range z.File {
+ size, ok := tt.files[f.Name]
+ if !ok {
+ t.Errorf("ReadZip: unexpected file %s", f.Name)
+ continue
+ }
+ have[f.Name] = true
+ if size != ^uint64(0) && f.UncompressedSize64 != size {
+ t.Errorf("ReadZip: file %s has unexpected size %d != %d", f.Name, f.UncompressedSize64, size)
+ }
+ }
+ for name := range tt.files {
+ if !have[name] {
+ t.Errorf("ReadZip: missing file %s", name)
+ }
+ }
+ }
+ }
+
+ for _, tt := range []readZipTest{
+ {
+ repo: gitrepo1,
+ rev: "v2.3.4",
+ subdir: "",
+ files: map[string]uint64{
+ "prefix/": 0,
+ "prefix/README": 0,
+ "prefix/v2": 3,
+ },
+ },
+ {
+ repo: hgrepo1,
+ rev: "v2.3.4",
+ subdir: "",
+ files: map[string]uint64{
+ "prefix/.hg_archival.txt": ^uint64(0),
+ "prefix/README": 0,
+ "prefix/v2": 3,
+ },
+ },
+
+ {
+ repo: gitrepo1,
+ rev: "v2",
+ subdir: "",
+ files: map[string]uint64{
+ "prefix/": 0,
+ "prefix/README": 0,
+ "prefix/v2": 3,
+ "prefix/another.txt": 8,
+ "prefix/foo.txt": 13,
+ },
+ },
+ {
+ repo: hgrepo1,
+ rev: "v2",
+ subdir: "",
+ files: map[string]uint64{
+ "prefix/.hg_archival.txt": ^uint64(0),
+ "prefix/README": 0,
+ "prefix/v2": 3,
+ "prefix/another.txt": 8,
+ "prefix/foo.txt": 13,
+ },
+ },
+
+ {
+ repo: gitrepo1,
+ rev: "v3",
+ subdir: "",
+ files: map[string]uint64{
+ "prefix/": 0,
+ "prefix/v3/": 0,
+ "prefix/v3/sub/": 0,
+ "prefix/v3/sub/dir/": 0,
+ "prefix/v3/sub/dir/file.txt": 16,
+ "prefix/README": 0,
+ },
+ },
+ {
+ repo: hgrepo1,
+ rev: "v3",
+ subdir: "",
+ files: map[string]uint64{
+ "prefix/.hg_archival.txt": ^uint64(0),
+ "prefix/.hgtags": 405,
+ "prefix/v3/sub/dir/file.txt": 16,
+ "prefix/README": 0,
+ },
+ },
+
+ {
+ repo: gitrepo1,
+ rev: "v3",
+ subdir: "v3/sub/dir",
+ files: map[string]uint64{
+ "prefix/": 0,
+ "prefix/v3/": 0,
+ "prefix/v3/sub/": 0,
+ "prefix/v3/sub/dir/": 0,
+ "prefix/v3/sub/dir/file.txt": 16,
+ },
+ },
+ {
+ repo: hgrepo1,
+ rev: "v3",
+ subdir: "v3/sub/dir",
+ files: map[string]uint64{
+ "prefix/v3/sub/dir/file.txt": 16,
+ },
+ },
+
+ {
+ repo: gitrepo1,
+ rev: "v3",
+ subdir: "v3/sub",
+ files: map[string]uint64{
+ "prefix/": 0,
+ "prefix/v3/": 0,
+ "prefix/v3/sub/": 0,
+ "prefix/v3/sub/dir/": 0,
+ "prefix/v3/sub/dir/file.txt": 16,
+ },
+ },
+ {
+ repo: hgrepo1,
+ rev: "v3",
+ subdir: "v3/sub",
+ files: map[string]uint64{
+ "prefix/v3/sub/dir/file.txt": 16,
+ },
+ },
+
+ {
+ repo: gitrepo1,
+ rev: "aaaaaaaaab",
+ subdir: "",
+ err: "unknown revision",
+ },
+ {
+ repo: hgrepo1,
+ rev: "aaaaaaaaab",
+ subdir: "",
+ err: "unknown revision",
+ },
+
+ {
+ repo: vgotest1,
+ rev: "submod/v1.0.4",
+ subdir: "submod",
+ files: map[string]uint64{
+ "prefix/": 0,
+ "prefix/submod/": 0,
+ "prefix/submod/go.mod": 53,
+ "prefix/submod/pkg/": 0,
+ "prefix/submod/pkg/p.go": 31,
+ },
+ },
+ } {
+ t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.subdir, runTest(tt))
+ if tt.repo == gitrepo1 {
+ tt.repo = "localGitRepo"
+ t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.subdir, runTest(tt))
+ }
+ }
+}
+
+var hgmap = map[string]string{
+ "HEAD": "41964ddce1180313bdc01d0a39a2813344d6261d", // not tip due to bad hgrepo1 conversion
+ "9d02800338b8a55be062c838d1f02e0c5780b9eb": "8f49ee7a6ddcdec6f0112d9dca48d4a2e4c3c09e",
+ "76a00fb249b7f93091bc2c89a789dab1fc1bc26f": "88fde824ec8b41a76baa16b7e84212cee9f3edd0",
+ "ede458df7cd0fdca520df19a33158086a8a68e81": "41964ddce1180313bdc01d0a39a2813344d6261d",
+ "97f6aa59c81c623494825b43d39e445566e429a4": "c0cbbfb24c7c3c50c35c7b88e7db777da4ff625d",
+}
+
+func TestStat(t *testing.T) {
+ t.Parallel()
+
+ type statTest struct {
+ repo string
+ rev string
+ err string
+ info *RevInfo
+ }
+ runTest := func(tt statTest) func(*testing.T) {
+ return func(t *testing.T) {
+ t.Parallel()
+ ctx := testContext(t)
+
+ r, err := testRepo(ctx, t, tt.repo)
+ if err != nil {
+ t.Fatal(err)
+ }
+ info, err := r.Stat(ctx, tt.rev)
+ if err != nil {
+ if tt.err == "" {
+ t.Fatalf("Stat: unexpected error %v", err)
+ }
+ if !strings.Contains(err.Error(), tt.err) {
+ t.Fatalf("Stat: wrong error %q, want %q", err, tt.err)
+ }
+ if info != nil && info.Origin == nil {
+ t.Errorf("Stat: non-nil info with nil Origin with error %q", err)
+ }
+ return
+ }
+ info.Origin = nil // TestLatest and ../../../testdata/script/reuse_git.txt test Origin well enough
+ if !reflect.DeepEqual(info, tt.info) {
+ t.Errorf("Stat: incorrect info\nhave %+v\nwant %+v", *info, *tt.info)
+ }
+ }
+ }
+
+ for _, tt := range []statTest{
+ {
+ repo: gitrepo1,
+ rev: "HEAD",
+ info: &RevInfo{
+ Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
+ Short: "ede458df7cd0",
+ Version: "ede458df7cd0fdca520df19a33158086a8a68e81",
+ Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
+ Tags: []string{"v1.2.3", "v1.2.4-annotated"},
+ },
+ },
+ {
+ repo: gitrepo1,
+ rev: "v2", // branch
+ info: &RevInfo{
+ Name: "9d02800338b8a55be062c838d1f02e0c5780b9eb",
+ Short: "9d02800338b8",
+ Version: "9d02800338b8a55be062c838d1f02e0c5780b9eb",
+ Time: time.Date(2018, 4, 17, 20, 00, 32, 0, time.UTC),
+ Tags: []string{"v2.0.2"},
+ },
+ },
+ {
+ repo: gitrepo1,
+ rev: "v2.3.4", // badly-named branch (semver should be a tag)
+ info: &RevInfo{
+ Name: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f",
+ Short: "76a00fb249b7",
+ Version: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f",
+ Time: time.Date(2018, 4, 17, 19, 45, 48, 0, time.UTC),
+ Tags: []string{"v2.0.1", "v2.3"},
+ },
+ },
+ {
+ repo: gitrepo1,
+ rev: "v2.3", // badly-named tag (we only respect full semver v2.3.0)
+ info: &RevInfo{
+ Name: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f",
+ Short: "76a00fb249b7",
+ Version: "v2.3",
+ Time: time.Date(2018, 4, 17, 19, 45, 48, 0, time.UTC),
+ Tags: []string{"v2.0.1", "v2.3"},
+ },
+ },
+ {
+ repo: gitrepo1,
+ rev: "v1.2.3", // tag
+ info: &RevInfo{
+ Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
+ Short: "ede458df7cd0",
+ Version: "v1.2.3",
+ Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
+ Tags: []string{"v1.2.3", "v1.2.4-annotated"},
+ },
+ },
+ {
+ repo: gitrepo1,
+ rev: "ede458df", // hash prefix in refs
+ info: &RevInfo{
+ Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
+ Short: "ede458df7cd0",
+ Version: "ede458df7cd0fdca520df19a33158086a8a68e81",
+ Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
+ Tags: []string{"v1.2.3", "v1.2.4-annotated"},
+ },
+ },
+ {
+ repo: gitrepo1,
+ rev: "97f6aa59", // hash prefix not in refs
+ info: &RevInfo{
+ Name: "97f6aa59c81c623494825b43d39e445566e429a4",
+ Short: "97f6aa59c81c",
+ Version: "97f6aa59c81c623494825b43d39e445566e429a4",
+ Time: time.Date(2018, 4, 17, 20, 0, 19, 0, time.UTC),
+ },
+ },
+ {
+ repo: gitrepo1,
+ rev: "v1.2.4-annotated", // annotated tag uses unwrapped commit hash
+ info: &RevInfo{
+ Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
+ Short: "ede458df7cd0",
+ Version: "v1.2.4-annotated",
+ Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
+ Tags: []string{"v1.2.3", "v1.2.4-annotated"},
+ },
+ },
+ {
+ repo: gitrepo1,
+ rev: "aaaaaaaaab",
+ err: "unknown revision",
+ },
+ } {
+ t.Run(path.Base(tt.repo)+"/"+tt.rev, runTest(tt))
+ if tt.repo == gitrepo1 {
+ for _, tt.repo = range altRepos() {
+ old := tt
+ var m map[string]string
+ if tt.repo == hgrepo1 {
+ m = hgmap
+ }
+ if tt.info != nil {
+ info := *tt.info
+ tt.info = &info
+ tt.info.Name = remap(tt.info.Name, m)
+ tt.info.Version = remap(tt.info.Version, m)
+ tt.info.Short = remap(tt.info.Short, m)
+ }
+ tt.rev = remap(tt.rev, m)
+ t.Run(path.Base(tt.repo)+"/"+tt.rev, runTest(tt))
+ tt = old
+ }
+ }
+ }
+}
+
+func remap(name string, m map[string]string) string {
+ if m[name] != "" {
+ return m[name]
+ }
+ if AllHex(name) {
+ for k, v := range m {
+ if strings.HasPrefix(k, name) {
+ return v[:len(name)]
+ }
+ }
+ }
+ return name
+}
diff --git a/src/cmd/go/internal/modfetch/codehost/shell.go b/src/cmd/go/internal/modfetch/codehost/shell.go
new file mode 100644
index 0000000..eaa0195
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/codehost/shell.go
@@ -0,0 +1,141 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build ignore
+
+// Interactive debugging shell for codehost.Repo implementations.
+
+package main
+
+import (
+ "archive/zip"
+ "bufio"
+ "bytes"
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "strings"
+ "time"
+
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/modfetch/codehost"
+)
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "usage: go run shell.go vcs remote\n")
+ os.Exit(2)
+}
+
+func main() {
+ cfg.GOMODCACHE = "/tmp/vcswork"
+ log.SetFlags(0)
+ log.SetPrefix("shell: ")
+ flag.Usage = usage
+ flag.Parse()
+ if flag.NArg() != 2 {
+ usage()
+ }
+
+ repo, err := codehost.NewRepo(flag.Arg(0), flag.Arg(1))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ b := bufio.NewReader(os.Stdin)
+ for {
+ fmt.Fprintf(os.Stderr, ">>> ")
+ line, err := b.ReadString('\n')
+ if err != nil {
+ log.Fatal(err)
+ }
+ f := strings.Fields(line)
+ if len(f) == 0 {
+ continue
+ }
+ switch f[0] {
+ default:
+ fmt.Fprintf(os.Stderr, "?unknown command\n")
+ continue
+ case "tags":
+ prefix := ""
+ if len(f) == 2 {
+ prefix = f[1]
+ }
+ if len(f) > 2 {
+ fmt.Fprintf(os.Stderr, "?usage: tags [prefix]\n")
+ continue
+ }
+ tags, err := repo.Tags(prefix)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "?%s\n", err)
+ continue
+ }
+ for _, tag := range tags {
+ fmt.Printf("%s\n", tag)
+ }
+
+ case "stat":
+ if len(f) != 2 {
+ fmt.Fprintf(os.Stderr, "?usage: stat rev\n")
+ continue
+ }
+ info, err := repo.Stat(f[1])
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "?%s\n", err)
+ continue
+ }
+ fmt.Printf("name=%s short=%s version=%s time=%s\n", info.Name, info.Short, info.Version, info.Time.UTC().Format(time.RFC3339))
+
+ case "read":
+ if len(f) != 3 {
+ fmt.Fprintf(os.Stderr, "?usage: read rev file\n")
+ continue
+ }
+ data, err := repo.ReadFile(f[1], f[2], 10<<20)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "?%s\n", err)
+ continue
+ }
+ os.Stdout.Write(data)
+
+ case "zip":
+ if len(f) != 4 {
+ fmt.Fprintf(os.Stderr, "?usage: zip rev subdir output\n")
+ continue
+ }
+ subdir := f[2]
+ if subdir == "-" {
+ subdir = ""
+ }
+ rc, err := repo.ReadZip(f[1], subdir, 10<<20)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "?%s\n", err)
+ continue
+ }
+ data, err := io.ReadAll(rc)
+ rc.Close()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "?%s\n", err)
+ continue
+ }
+
+ if f[3] != "-" {
+ if err := os.WriteFile(f[3], data, 0666); err != nil {
+ fmt.Fprintf(os.Stderr, "?%s\n", err)
+ continue
+ }
+ }
+ z, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "?%s\n", err)
+ continue
+ }
+ for _, f := range z.File {
+ fmt.Printf("%s %d\n", f.Name, f.UncompressedSize64)
+ }
+ }
+ }
+}
diff --git a/src/cmd/go/internal/modfetch/codehost/svn.go b/src/cmd/go/internal/modfetch/codehost/svn.go
new file mode 100644
index 0000000..9c1c100
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/codehost/svn.go
@@ -0,0 +1,168 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codehost
+
+import (
+ "archive/zip"
+ "context"
+ "encoding/xml"
+ "fmt"
+ "io"
+ "os"
+ "path"
+ "path/filepath"
+ "strconv"
+ "time"
+
+ "cmd/go/internal/base"
+)
+
+func svnParseStat(rev, out string) (*RevInfo, error) {
+ var log struct {
+ Logentry struct {
+ Revision int64 `xml:"revision,attr"`
+ Date string `xml:"date"`
+ } `xml:"logentry"`
+ }
+ if err := xml.Unmarshal([]byte(out), &log); err != nil {
+ return nil, vcsErrorf("unexpected response from svn log --xml: %v\n%s", err, out)
+ }
+
+ t, err := time.Parse(time.RFC3339, log.Logentry.Date)
+ if err != nil {
+ return nil, vcsErrorf("unexpected response from svn log --xml: %v\n%s", err, out)
+ }
+
+ info := &RevInfo{
+ Name: strconv.FormatInt(log.Logentry.Revision, 10),
+ Short: fmt.Sprintf("%012d", log.Logentry.Revision),
+ Time: t.UTC(),
+ Version: rev,
+ }
+ return info, nil
+}
+
+func svnReadZip(ctx context.Context, dst io.Writer, workDir, rev, subdir, remote string) (err error) {
+ // The subversion CLI doesn't provide a command to write the repository
+ // directly to an archive, so we need to export it to the local filesystem
+ // instead. Unfortunately, the local filesystem might apply arbitrary
+ // normalization to the filenames, so we need to obtain those directly.
+ //
+ // 'svn export' prints the filenames as they are written, but from reading the
+ // svn source code (as of revision 1868933), those filenames are encoded using
+ // the system locale rather than preserved byte-for-byte from the origin. For
+ // our purposes, that won't do, but we don't want to go mucking around with
+ // the user's locale settings either — that could impact error messages, and
+ // we don't know what locales the user has available or what LC_* variables
+ // their platform supports.
+ //
+ // Instead, we'll do a two-pass export: first we'll run 'svn list' to get the
+ // canonical filenames, then we'll 'svn export' and look for those filenames
+ // in the local filesystem. (If there is an encoding problem at that point, we
+ // would probably reject the resulting module anyway.)
+
+ remotePath := remote
+ if subdir != "" {
+ remotePath += "/" + subdir
+ }
+
+ release, err := base.AcquireNet()
+ if err != nil {
+ return err
+ }
+ out, err := Run(ctx, workDir, []string{
+ "svn", "list",
+ "--non-interactive",
+ "--xml",
+ "--incremental",
+ "--recursive",
+ "--revision", rev,
+ "--", remotePath,
+ })
+ release()
+ if err != nil {
+ return err
+ }
+
+ type listEntry struct {
+ Kind string `xml:"kind,attr"`
+ Name string `xml:"name"`
+ Size int64 `xml:"size"`
+ }
+ var list struct {
+ Entries []listEntry `xml:"entry"`
+ }
+ if err := xml.Unmarshal(out, &list); err != nil {
+ return vcsErrorf("unexpected response from svn list --xml: %v\n%s", err, out)
+ }
+
+ exportDir := filepath.Join(workDir, "export")
+ // Remove any existing contents from a previous (failed) run.
+ if err := os.RemoveAll(exportDir); err != nil {
+ return err
+ }
+ defer os.RemoveAll(exportDir) // best-effort
+
+ release, err = base.AcquireNet()
+ if err != nil {
+ return err
+ }
+ _, err = Run(ctx, workDir, []string{
+ "svn", "export",
+ "--non-interactive",
+ "--quiet",
+
+ // Suppress any platform- or host-dependent transformations.
+ "--native-eol", "LF",
+ "--ignore-externals",
+ "--ignore-keywords",
+
+ "--revision", rev,
+ "--", remotePath,
+ exportDir,
+ })
+ release()
+ if err != nil {
+ return err
+ }
+
+ // Scrape the exported files out of the filesystem and encode them in the zipfile.
+
+ // “All files in the zip file are expected to be
+ // nested in a single top-level directory, whose name is not specified.”
+ // We'll (arbitrarily) choose the base of the remote path.
+ basePath := path.Join(path.Base(remote), subdir)
+
+ zw := zip.NewWriter(dst)
+ for _, e := range list.Entries {
+ if e.Kind != "file" {
+ continue
+ }
+
+ zf, err := zw.Create(path.Join(basePath, e.Name))
+ if err != nil {
+ return err
+ }
+
+ f, err := os.Open(filepath.Join(exportDir, e.Name))
+ if err != nil {
+ if os.IsNotExist(err) {
+ return vcsErrorf("file reported by 'svn list', but not written by 'svn export': %s", e.Name)
+ }
+ return fmt.Errorf("error opening file created by 'svn export': %v", err)
+ }
+
+ n, err := io.Copy(zf, f)
+ f.Close()
+ if err != nil {
+ return err
+ }
+ if n != e.Size {
+ return vcsErrorf("file size differs between 'svn list' and 'svn export': file %s listed as %v bytes, but exported as %v bytes", e.Name, e.Size, n)
+ }
+ }
+
+ return zw.Close()
+}
diff --git a/src/cmd/go/internal/modfetch/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go
new file mode 100644
index 0000000..5bd1005
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/codehost/vcs.go
@@ -0,0 +1,644 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codehost
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "internal/lazyregexp"
+ "io"
+ "io/fs"
+ "os"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/lockedfile"
+ "cmd/go/internal/par"
+ "cmd/go/internal/str"
+)
+
+// A VCSError indicates an error using a version control system.
+// The implication of a VCSError is that we know definitively where
+// to get the code, but we can't access it due to the error.
+// The caller should report this error instead of continuing to probe
+// other possible module paths.
+//
+// TODO(golang.org/issue/31730): See if we can invert this. (Return a
+// distinguished error for “repo not found” and treat everything else
+// as terminal.)
+type VCSError struct {
+ Err error
+}
+
+func (e *VCSError) Error() string { return e.Err.Error() }
+
+func (e *VCSError) Unwrap() error { return e.Err }
+
+func vcsErrorf(format string, a ...any) error {
+ return &VCSError{Err: fmt.Errorf(format, a...)}
+}
+
+type vcsCacheKey struct {
+ vcs string
+ remote string
+}
+
+func NewRepo(ctx context.Context, vcs, remote string) (Repo, error) {
+ return vcsRepoCache.Do(vcsCacheKey{vcs, remote}, func() (Repo, error) {
+ repo, err := newVCSRepo(ctx, vcs, remote)
+ if err != nil {
+ return nil, &VCSError{err}
+ }
+ return repo, nil
+ })
+}
+
+var vcsRepoCache par.ErrCache[vcsCacheKey, Repo]
+
+type vcsRepo struct {
+ mu lockedfile.Mutex // protects all commands, so we don't have to decide which are safe on a per-VCS basis
+
+ remote string
+ cmd *vcsCmd
+ dir string
+
+ tagsOnce sync.Once
+ tags map[string]bool
+
+ branchesOnce sync.Once
+ branches map[string]bool
+
+ fetchOnce sync.Once
+ fetchErr error
+}
+
+func newVCSRepo(ctx context.Context, vcs, remote string) (Repo, error) {
+ if vcs == "git" {
+ return newGitRepo(ctx, remote, false)
+ }
+ cmd := vcsCmds[vcs]
+ if cmd == nil {
+ return nil, fmt.Errorf("unknown vcs: %s %s", vcs, remote)
+ }
+ if !strings.Contains(remote, "://") {
+ return nil, fmt.Errorf("invalid vcs remote: %s %s", vcs, remote)
+ }
+
+ r := &vcsRepo{remote: remote, cmd: cmd}
+ var err error
+ r.dir, r.mu.Path, err = WorkDir(ctx, vcsWorkDirType+vcs, r.remote)
+ if err != nil {
+ return nil, err
+ }
+
+ if cmd.init == nil {
+ return r, nil
+ }
+
+ unlock, err := r.mu.Lock()
+ if err != nil {
+ return nil, err
+ }
+ defer unlock()
+
+ if _, err := os.Stat(filepath.Join(r.dir, "."+vcs)); err != nil {
+ release, err := base.AcquireNet()
+ if err != nil {
+ return nil, err
+ }
+ _, err = Run(ctx, r.dir, cmd.init(r.remote))
+ release()
+
+ if err != nil {
+ os.RemoveAll(r.dir)
+ return nil, err
+ }
+ }
+ return r, nil
+}
+
+const vcsWorkDirType = "vcs1."
+
+type vcsCmd struct {
+ vcs string // vcs name "hg"
+ init func(remote string) []string // cmd to init repo to track remote
+ tags func(remote string) []string // cmd to list local tags
+ tagRE *lazyregexp.Regexp // regexp to extract tag names from output of tags cmd
+ branches func(remote string) []string // cmd to list local branches
+ branchRE *lazyregexp.Regexp // regexp to extract branch names from output of tags cmd
+ badLocalRevRE *lazyregexp.Regexp // regexp of names that must not be served out of local cache without doing fetch first
+ statLocal func(rev, remote string) []string // cmd to stat local rev
+ parseStat func(rev, out string) (*RevInfo, error) // cmd to parse output of statLocal
+ fetch []string // cmd to fetch everything from remote
+ latest string // name of latest commit on remote (tip, HEAD, etc)
+ readFile func(rev, file, remote string) []string // cmd to read rev's file
+ readZip func(rev, subdir, remote, target string) []string // cmd to read rev's subdir as zip file
+ doReadZip func(ctx context.Context, dst io.Writer, workDir, rev, subdir, remote string) error // arbitrary function to read rev's subdir as zip file
+}
+
+var re = lazyregexp.New
+
+var vcsCmds = map[string]*vcsCmd{
+ "hg": {
+ vcs: "hg",
+ init: func(remote string) []string {
+ return []string{"hg", "clone", "-U", "--", remote, "."}
+ },
+ tags: func(remote string) []string {
+ return []string{"hg", "tags", "-q"}
+ },
+ tagRE: re(`(?m)^[^\n]+$`),
+ branches: func(remote string) []string {
+ return []string{"hg", "branches", "-c", "-q"}
+ },
+ branchRE: re(`(?m)^[^\n]+$`),
+ badLocalRevRE: re(`(?m)^(tip)$`),
+ statLocal: func(rev, remote string) []string {
+ return []string{"hg", "log", "-l1", "-r", rev, "--template", "{node} {date|hgdate} {tags}"}
+ },
+ parseStat: hgParseStat,
+ fetch: []string{"hg", "pull", "-f"},
+ latest: "tip",
+ readFile: func(rev, file, remote string) []string {
+ return []string{"hg", "cat", "-r", rev, file}
+ },
+ readZip: func(rev, subdir, remote, target string) []string {
+ pattern := []string{}
+ if subdir != "" {
+ pattern = []string{"-I", subdir + "/**"}
+ }
+ return str.StringList("hg", "archive", "-t", "zip", "--no-decode", "-r", rev, "--prefix=prefix/", pattern, "--", target)
+ },
+ },
+
+ "svn": {
+ vcs: "svn",
+ init: nil, // no local checkout
+ tags: func(remote string) []string {
+ return []string{"svn", "list", "--", strings.TrimSuffix(remote, "/trunk") + "/tags"}
+ },
+ tagRE: re(`(?m)^(.*?)/?$`),
+ statLocal: func(rev, remote string) []string {
+ suffix := "@" + rev
+ if rev == "latest" {
+ suffix = ""
+ }
+ return []string{"svn", "log", "-l1", "--xml", "--", remote + suffix}
+ },
+ parseStat: svnParseStat,
+ latest: "latest",
+ readFile: func(rev, file, remote string) []string {
+ return []string{"svn", "cat", "--", remote + "/" + file + "@" + rev}
+ },
+ doReadZip: svnReadZip,
+ },
+
+ "bzr": {
+ vcs: "bzr",
+ init: func(remote string) []string {
+ return []string{"bzr", "branch", "--use-existing-dir", "--", remote, "."}
+ },
+ fetch: []string{
+ "bzr", "pull", "--overwrite-tags",
+ },
+ tags: func(remote string) []string {
+ return []string{"bzr", "tags"}
+ },
+ tagRE: re(`(?m)^\S+`),
+ badLocalRevRE: re(`^revno:-`),
+ statLocal: func(rev, remote string) []string {
+ return []string{"bzr", "log", "-l1", "--long", "--show-ids", "-r", rev}
+ },
+ parseStat: bzrParseStat,
+ latest: "revno:-1",
+ readFile: func(rev, file, remote string) []string {
+ return []string{"bzr", "cat", "-r", rev, file}
+ },
+ readZip: func(rev, subdir, remote, target string) []string {
+ extra := []string{}
+ if subdir != "" {
+ extra = []string{"./" + subdir}
+ }
+ return str.StringList("bzr", "export", "--format=zip", "-r", rev, "--root=prefix/", "--", target, extra)
+ },
+ },
+
+ "fossil": {
+ vcs: "fossil",
+ init: func(remote string) []string {
+ return []string{"fossil", "clone", "--", remote, ".fossil"}
+ },
+ fetch: []string{"fossil", "pull", "-R", ".fossil"},
+ tags: func(remote string) []string {
+ return []string{"fossil", "tag", "-R", ".fossil", "list"}
+ },
+ tagRE: re(`XXXTODO`),
+ statLocal: func(rev, remote string) []string {
+ return []string{"fossil", "info", "-R", ".fossil", rev}
+ },
+ parseStat: fossilParseStat,
+ latest: "trunk",
+ readFile: func(rev, file, remote string) []string {
+ return []string{"fossil", "cat", "-R", ".fossil", "-r", rev, file}
+ },
+ readZip: func(rev, subdir, remote, target string) []string {
+ extra := []string{}
+ if subdir != "" && !strings.ContainsAny(subdir, "*?[],") {
+ extra = []string{"--include", subdir}
+ }
+ // Note that vcsRepo.ReadZip below rewrites this command
+ // to run in a different directory, to work around a fossil bug.
+ return str.StringList("fossil", "zip", "-R", ".fossil", "--name", "prefix", extra, "--", rev, target)
+ },
+ },
+}
+
+func (r *vcsRepo) loadTags(ctx context.Context) {
+ out, err := Run(ctx, r.dir, r.cmd.tags(r.remote))
+ if err != nil {
+ return
+ }
+
+ // Run tag-listing command and extract tags.
+ r.tags = make(map[string]bool)
+ for _, tag := range r.cmd.tagRE.FindAllString(string(out), -1) {
+ if r.cmd.badLocalRevRE != nil && r.cmd.badLocalRevRE.MatchString(tag) {
+ continue
+ }
+ r.tags[tag] = true
+ }
+}
+
+func (r *vcsRepo) loadBranches(ctx context.Context) {
+ if r.cmd.branches == nil {
+ return
+ }
+
+ out, err := Run(ctx, r.dir, r.cmd.branches(r.remote))
+ if err != nil {
+ return
+ }
+
+ r.branches = make(map[string]bool)
+ for _, branch := range r.cmd.branchRE.FindAllString(string(out), -1) {
+ if r.cmd.badLocalRevRE != nil && r.cmd.badLocalRevRE.MatchString(branch) {
+ continue
+ }
+ r.branches[branch] = true
+ }
+}
+
+func (r *vcsRepo) CheckReuse(ctx context.Context, old *Origin, subdir string) error {
+ return fmt.Errorf("vcs %s: CheckReuse: %w", r.cmd.vcs, errors.ErrUnsupported)
+}
+
+func (r *vcsRepo) Tags(ctx context.Context, prefix string) (*Tags, error) {
+ unlock, err := r.mu.Lock()
+ if err != nil {
+ return nil, err
+ }
+ defer unlock()
+
+ r.tagsOnce.Do(func() { r.loadTags(ctx) })
+ tags := &Tags{
+ // None of the other VCS provide a reasonable way to compute TagSum
+ // without downloading the whole repo, so we only include VCS and URL
+ // in the Origin.
+ Origin: &Origin{
+ VCS: r.cmd.vcs,
+ URL: r.remote,
+ },
+ List: []Tag{},
+ }
+ for tag := range r.tags {
+ if strings.HasPrefix(tag, prefix) {
+ tags.List = append(tags.List, Tag{tag, ""})
+ }
+ }
+ sort.Slice(tags.List, func(i, j int) bool {
+ return tags.List[i].Name < tags.List[j].Name
+ })
+ return tags, nil
+}
+
+func (r *vcsRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
+ unlock, err := r.mu.Lock()
+ if err != nil {
+ return nil, err
+ }
+ defer unlock()
+
+ if rev == "latest" {
+ rev = r.cmd.latest
+ }
+ r.branchesOnce.Do(func() { r.loadBranches(ctx) })
+ revOK := (r.cmd.badLocalRevRE == nil || !r.cmd.badLocalRevRE.MatchString(rev)) && !r.branches[rev]
+ if revOK {
+ if info, err := r.statLocal(ctx, rev); err == nil {
+ return info, nil
+ }
+ }
+
+ r.fetchOnce.Do(func() { r.fetch(ctx) })
+ if r.fetchErr != nil {
+ return nil, r.fetchErr
+ }
+ info, err := r.statLocal(ctx, rev)
+ if err != nil {
+ return nil, err
+ }
+ if !revOK {
+ info.Version = info.Name
+ }
+ return info, nil
+}
+
+func (r *vcsRepo) fetch(ctx context.Context) {
+ if len(r.cmd.fetch) > 0 {
+ release, err := base.AcquireNet()
+ if err != nil {
+ r.fetchErr = err
+ return
+ }
+ _, r.fetchErr = Run(ctx, r.dir, r.cmd.fetch)
+ release()
+ }
+}
+
+func (r *vcsRepo) statLocal(ctx context.Context, rev string) (*RevInfo, error) {
+ out, err := Run(ctx, r.dir, r.cmd.statLocal(rev, r.remote))
+ if err != nil {
+ return nil, &UnknownRevisionError{Rev: rev}
+ }
+ info, err := r.cmd.parseStat(rev, string(out))
+ if err != nil {
+ return nil, err
+ }
+ if info.Origin == nil {
+ info.Origin = new(Origin)
+ }
+ info.Origin.VCS = r.cmd.vcs
+ info.Origin.URL = r.remote
+ return info, nil
+}
+
+func (r *vcsRepo) Latest(ctx context.Context) (*RevInfo, error) {
+ return r.Stat(ctx, "latest")
+}
+
+func (r *vcsRepo) ReadFile(ctx context.Context, rev, file string, maxSize int64) ([]byte, error) {
+ if rev == "latest" {
+ rev = r.cmd.latest
+ }
+ _, err := r.Stat(ctx, rev) // download rev into local repo
+ if err != nil {
+ return nil, err
+ }
+
+ // r.Stat acquires r.mu, so lock after that.
+ unlock, err := r.mu.Lock()
+ if err != nil {
+ return nil, err
+ }
+ defer unlock()
+
+ out, err := Run(ctx, r.dir, r.cmd.readFile(rev, file, r.remote))
+ if err != nil {
+ return nil, fs.ErrNotExist
+ }
+ return out, nil
+}
+
+func (r *vcsRepo) RecentTag(ctx context.Context, rev, prefix string, allowed func(string) bool) (tag string, err error) {
+ // We don't technically need to lock here since we're returning an error
+ // uncondititonally, but doing so anyway will help to avoid baking in
+ // lock-inversion bugs.
+ unlock, err := r.mu.Lock()
+ if err != nil {
+ return "", err
+ }
+ defer unlock()
+
+ return "", vcsErrorf("vcs %s: RecentTag: %w", r.cmd.vcs, errors.ErrUnsupported)
+}
+
+func (r *vcsRepo) DescendsFrom(ctx context.Context, rev, tag string) (bool, error) {
+ unlock, err := r.mu.Lock()
+ if err != nil {
+ return false, err
+ }
+ defer unlock()
+
+ return false, vcsErrorf("vcs %s: DescendsFrom: %w", r.cmd.vcs, errors.ErrUnsupported)
+}
+
+func (r *vcsRepo) ReadZip(ctx context.Context, rev, subdir string, maxSize int64) (zip io.ReadCloser, err error) {
+ if r.cmd.readZip == nil && r.cmd.doReadZip == nil {
+ return nil, vcsErrorf("vcs %s: ReadZip: %w", r.cmd.vcs, errors.ErrUnsupported)
+ }
+
+ unlock, err := r.mu.Lock()
+ if err != nil {
+ return nil, err
+ }
+ defer unlock()
+
+ if rev == "latest" {
+ rev = r.cmd.latest
+ }
+ f, err := os.CreateTemp("", "go-readzip-*.zip")
+ if err != nil {
+ return nil, err
+ }
+ if r.cmd.doReadZip != nil {
+ lw := &limitedWriter{
+ W: f,
+ N: maxSize,
+ ErrLimitReached: errors.New("ReadZip: encoded file exceeds allowed size"),
+ }
+ err = r.cmd.doReadZip(ctx, lw, r.dir, rev, subdir, r.remote)
+ if err == nil {
+ _, err = f.Seek(0, io.SeekStart)
+ }
+ } else if r.cmd.vcs == "fossil" {
+ // If you run
+ // fossil zip -R .fossil --name prefix trunk /tmp/x.zip
+ // fossil fails with "unable to create directory /tmp" [sic].
+ // Change the command to run in /tmp instead,
+ // replacing the -R argument with an absolute path.
+ args := r.cmd.readZip(rev, subdir, r.remote, filepath.Base(f.Name()))
+ for i := range args {
+ if args[i] == ".fossil" {
+ args[i] = filepath.Join(r.dir, ".fossil")
+ }
+ }
+ _, err = Run(ctx, filepath.Dir(f.Name()), args)
+ } else {
+ _, err = Run(ctx, r.dir, r.cmd.readZip(rev, subdir, r.remote, f.Name()))
+ }
+ if err != nil {
+ f.Close()
+ os.Remove(f.Name())
+ return nil, err
+ }
+ return &deleteCloser{f}, nil
+}
+
+// deleteCloser is a file that gets deleted on Close.
+type deleteCloser struct {
+ *os.File
+}
+
+func (d *deleteCloser) Close() error {
+ defer os.Remove(d.File.Name())
+ return d.File.Close()
+}
+
+func hgParseStat(rev, out string) (*RevInfo, error) {
+ f := strings.Fields(out)
+ if len(f) < 3 {
+ return nil, vcsErrorf("unexpected response from hg log: %q", out)
+ }
+ hash := f[0]
+ version := rev
+ if strings.HasPrefix(hash, version) {
+ version = hash // extend to full hash
+ }
+ t, err := strconv.ParseInt(f[1], 10, 64)
+ if err != nil {
+ return nil, vcsErrorf("invalid time from hg log: %q", out)
+ }
+
+ var tags []string
+ for _, tag := range f[3:] {
+ if tag != "tip" {
+ tags = append(tags, tag)
+ }
+ }
+ sort.Strings(tags)
+
+ info := &RevInfo{
+ Origin: &Origin{
+ Hash: hash,
+ },
+ Name: hash,
+ Short: ShortenSHA1(hash),
+ Time: time.Unix(t, 0).UTC(),
+ Version: version,
+ Tags: tags,
+ }
+ return info, nil
+}
+
+func bzrParseStat(rev, out string) (*RevInfo, error) {
+ var revno int64
+ var tm time.Time
+ for _, line := range strings.Split(out, "\n") {
+ if line == "" || line[0] == ' ' || line[0] == '\t' {
+ // End of header, start of commit message.
+ break
+ }
+ if line[0] == '-' {
+ continue
+ }
+ before, after, found := strings.Cut(line, ":")
+ if !found {
+ // End of header, start of commit message.
+ break
+ }
+ key, val := before, strings.TrimSpace(after)
+ switch key {
+ case "revno":
+ if j := strings.Index(val, " "); j >= 0 {
+ val = val[:j]
+ }
+ i, err := strconv.ParseInt(val, 10, 64)
+ if err != nil {
+ return nil, vcsErrorf("unexpected revno from bzr log: %q", line)
+ }
+ revno = i
+ case "timestamp":
+ j := strings.Index(val, " ")
+ if j < 0 {
+ return nil, vcsErrorf("unexpected timestamp from bzr log: %q", line)
+ }
+ t, err := time.Parse("2006-01-02 15:04:05 -0700", val[j+1:])
+ if err != nil {
+ return nil, vcsErrorf("unexpected timestamp from bzr log: %q", line)
+ }
+ tm = t.UTC()
+ }
+ }
+ if revno == 0 || tm.IsZero() {
+ return nil, vcsErrorf("unexpected response from bzr log: %q", out)
+ }
+
+ info := &RevInfo{
+ Name: strconv.FormatInt(revno, 10),
+ Short: fmt.Sprintf("%012d", revno),
+ Time: tm,
+ Version: rev,
+ }
+ return info, nil
+}
+
+func fossilParseStat(rev, out string) (*RevInfo, error) {
+ for _, line := range strings.Split(out, "\n") {
+ if strings.HasPrefix(line, "uuid:") || strings.HasPrefix(line, "hash:") {
+ f := strings.Fields(line)
+ if len(f) != 5 || len(f[1]) != 40 || f[4] != "UTC" {
+ return nil, vcsErrorf("unexpected response from fossil info: %q", line)
+ }
+ t, err := time.Parse(time.DateTime, f[2]+" "+f[3])
+ if err != nil {
+ return nil, vcsErrorf("unexpected response from fossil info: %q", line)
+ }
+ hash := f[1]
+ version := rev
+ if strings.HasPrefix(hash, version) {
+ version = hash // extend to full hash
+ }
+ info := &RevInfo{
+ Origin: &Origin{
+ Hash: hash,
+ },
+ Name: hash,
+ Short: ShortenSHA1(hash),
+ Time: t,
+ Version: version,
+ }
+ return info, nil
+ }
+ }
+ return nil, vcsErrorf("unexpected response from fossil info: %q", out)
+}
+
+type limitedWriter struct {
+ W io.Writer
+ N int64
+ ErrLimitReached error
+}
+
+func (l *limitedWriter) Write(p []byte) (n int, err error) {
+ if l.N > 0 {
+ max := len(p)
+ if l.N < int64(max) {
+ max = int(l.N)
+ }
+ n, err = l.W.Write(p[:max])
+ l.N -= int64(n)
+ if err != nil || n >= len(p) {
+ return n, err
+ }
+ }
+
+ return n, l.ErrLimitReached
+}
diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go
new file mode 100644
index 0000000..75c34e9
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/coderepo.go
@@ -0,0 +1,1215 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modfetch
+
+import (
+ "archive/zip"
+ "bytes"
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "io/fs"
+ "os"
+ "path"
+ "path/filepath"
+ "sort"
+ "strings"
+ "time"
+
+ "cmd/go/internal/gover"
+ "cmd/go/internal/modfetch/codehost"
+
+ "golang.org/x/mod/modfile"
+ "golang.org/x/mod/module"
+ "golang.org/x/mod/semver"
+ modzip "golang.org/x/mod/zip"
+)
+
+// A codeRepo implements modfetch.Repo using an underlying codehost.Repo.
+type codeRepo struct {
+ modPath string
+
+ // code is the repository containing this module.
+ code codehost.Repo
+ // codeRoot is the import path at the root of code.
+ codeRoot string
+ // codeDir is the directory (relative to root) at which we expect to find the module.
+ // If pathMajor is non-empty and codeRoot is not the full modPath,
+ // then we look in both codeDir and codeDir/pathMajor[1:].
+ codeDir string
+
+ // pathMajor is the suffix of modPath that indicates its major version,
+ // or the empty string if modPath is at major version 0 or 1.
+ //
+ // pathMajor is typically of the form "/vN", but possibly ".vN", or
+ // ".vN-unstable" for modules resolved using gopkg.in.
+ pathMajor string
+ // pathPrefix is the prefix of modPath that excludes pathMajor.
+ // It is used only for logging.
+ pathPrefix string
+
+ // pseudoMajor is the major version prefix to require when generating
+ // pseudo-versions for this module, derived from the module path. pseudoMajor
+ // is empty if the module path does not include a version suffix (that is,
+ // accepts either v0 or v1).
+ pseudoMajor string
+}
+
+// newCodeRepo returns a Repo that reads the source code for the module with the
+// given path, from the repo stored in code, with the root of the repo
+// containing the path given by codeRoot.
+func newCodeRepo(code codehost.Repo, codeRoot, path string) (Repo, error) {
+ if !hasPathPrefix(path, codeRoot) {
+ return nil, fmt.Errorf("mismatched repo: found %s for %s", codeRoot, path)
+ }
+ pathPrefix, pathMajor, ok := module.SplitPathVersion(path)
+ if !ok {
+ return nil, fmt.Errorf("invalid module path %q", path)
+ }
+ if codeRoot == path {
+ pathPrefix = path
+ }
+ pseudoMajor := module.PathMajorPrefix(pathMajor)
+
+ // Compute codeDir = bar, the subdirectory within the repo
+ // corresponding to the module root.
+ //
+ // At this point we might have:
+ // path = github.com/rsc/foo/bar/v2
+ // codeRoot = github.com/rsc/foo
+ // pathPrefix = github.com/rsc/foo/bar
+ // pathMajor = /v2
+ // pseudoMajor = v2
+ //
+ // which gives
+ // codeDir = bar
+ //
+ // We know that pathPrefix is a prefix of path, and codeRoot is a prefix of
+ // path, but codeRoot may or may not be a prefix of pathPrefix, because
+ // codeRoot may be the entire path (in which case codeDir should be empty).
+ // That occurs in two situations.
+ //
+ // One is when a go-import meta tag resolves the complete module path,
+ // including the pathMajor suffix:
+ // path = nanomsg.org/go/mangos/v2
+ // codeRoot = nanomsg.org/go/mangos/v2
+ // pathPrefix = nanomsg.org/go/mangos
+ // pathMajor = /v2
+ // pseudoMajor = v2
+ //
+ // The other is similar: for gopkg.in only, the major version is encoded
+ // with a dot rather than a slash, and thus can't be in a subdirectory.
+ // path = gopkg.in/yaml.v2
+ // codeRoot = gopkg.in/yaml.v2
+ // pathPrefix = gopkg.in/yaml
+ // pathMajor = .v2
+ // pseudoMajor = v2
+ //
+ codeDir := ""
+ if codeRoot != path {
+ if !hasPathPrefix(pathPrefix, codeRoot) {
+ return nil, fmt.Errorf("repository rooted at %s cannot contain module %s", codeRoot, path)
+ }
+ codeDir = strings.Trim(pathPrefix[len(codeRoot):], "/")
+ }
+
+ r := &codeRepo{
+ modPath: path,
+ code: code,
+ codeRoot: codeRoot,
+ codeDir: codeDir,
+ pathPrefix: pathPrefix,
+ pathMajor: pathMajor,
+ pseudoMajor: pseudoMajor,
+ }
+
+ return r, nil
+}
+
+func (r *codeRepo) ModulePath() string {
+ return r.modPath
+}
+
+func (r *codeRepo) CheckReuse(ctx context.Context, old *codehost.Origin) error {
+ return r.code.CheckReuse(ctx, old, r.codeDir)
+}
+
+func (r *codeRepo) Versions(ctx context.Context, prefix string) (*Versions, error) {
+ // Special case: gopkg.in/macaroon-bakery.v2-unstable
+ // does not use the v2 tags (those are for macaroon-bakery.v2).
+ // It has no possible tags at all.
+ if strings.HasPrefix(r.modPath, "gopkg.in/") && strings.HasSuffix(r.modPath, "-unstable") {
+ return &Versions{}, nil
+ }
+
+ p := prefix
+ if r.codeDir != "" {
+ p = r.codeDir + "/" + p
+ }
+ tags, err := r.code.Tags(ctx, p)
+ if err != nil {
+ return nil, &module.ModuleError{
+ Path: r.modPath,
+ Err: err,
+ }
+ }
+ if tags.Origin != nil {
+ tags.Origin.Subdir = r.codeDir
+ }
+
+ var list, incompatible []string
+ for _, tag := range tags.List {
+ if !strings.HasPrefix(tag.Name, p) {
+ continue
+ }
+ v := tag.Name
+ if r.codeDir != "" {
+ v = v[len(r.codeDir)+1:]
+ }
+ // Note: ./codehost/codehost.go's isOriginTag knows about these conditions too.
+ // If these are relaxed, isOriginTag will need to be relaxed as well.
+ if v == "" || v != semver.Canonical(v) {
+ // Ignore non-canonical tags: Stat rewrites those to canonical
+ // pseudo-versions. Note that we compare against semver.Canonical here
+ // instead of module.CanonicalVersion: revToRev strips "+incompatible"
+ // suffixes before looking up tags, so a tag like "v2.0.0+incompatible"
+ // would not resolve at all. (The Go version string "v2.0.0+incompatible"
+ // refers to the "v2.0.0" version tag, which we handle below.)
+ continue
+ }
+ if module.IsPseudoVersion(v) {
+ // Ignore tags that look like pseudo-versions: Stat rewrites those
+ // unambiguously to the underlying commit, and tagToVersion drops them.
+ continue
+ }
+
+ if err := module.CheckPathMajor(v, r.pathMajor); err != nil {
+ if r.codeDir == "" && r.pathMajor == "" && semver.Major(v) > "v1" {
+ incompatible = append(incompatible, v)
+ }
+ continue
+ }
+
+ list = append(list, v)
+ }
+ semver.Sort(list)
+ semver.Sort(incompatible)
+
+ return r.appendIncompatibleVersions(ctx, tags.Origin, list, incompatible)
+}
+
+// appendIncompatibleVersions appends "+incompatible" versions to list if
+// appropriate, returning the final list.
+//
+// The incompatible list contains candidate versions without the '+incompatible'
+// prefix.
+//
+// Both list and incompatible must be sorted in semantic order.
+func (r *codeRepo) appendIncompatibleVersions(ctx context.Context, origin *codehost.Origin, list, incompatible []string) (*Versions, error) {
+ versions := &Versions{
+ Origin: origin,
+ List: list,
+ }
+ if len(incompatible) == 0 || r.pathMajor != "" {
+ // No +incompatible versions are possible, so no need to check them.
+ return versions, nil
+ }
+
+ versionHasGoMod := func(v string) (bool, error) {
+ _, err := r.code.ReadFile(ctx, v, "go.mod", codehost.MaxGoMod)
+ if err == nil {
+ return true, nil
+ }
+ if !os.IsNotExist(err) {
+ return false, &module.ModuleError{
+ Path: r.modPath,
+ Err: err,
+ }
+ }
+ return false, nil
+ }
+
+ if len(list) > 0 {
+ ok, err := versionHasGoMod(list[len(list)-1])
+ if err != nil {
+ return nil, err
+ }
+ if ok {
+ // The latest compatible version has a go.mod file, so assume that all
+ // subsequent versions do as well, and do not include any +incompatible
+ // versions. Even if we are wrong, the author clearly intends module
+ // consumers to be on the v0/v1 line instead of a higher +incompatible
+ // version. (See https://golang.org/issue/34189.)
+ //
+ // We know of at least two examples where this behavior is desired
+ // (github.com/russross/blackfriday@v2.0.0 and
+ // github.com/libp2p/go-libp2p@v6.0.23), and (as of 2019-10-29) have no
+ // concrete examples for which it is undesired.
+ return versions, nil
+ }
+ }
+
+ var (
+ lastMajor string
+ lastMajorHasGoMod bool
+ )
+ for i, v := range incompatible {
+ major := semver.Major(v)
+
+ if major != lastMajor {
+ rem := incompatible[i:]
+ j := sort.Search(len(rem), func(j int) bool {
+ return semver.Major(rem[j]) != major
+ })
+ latestAtMajor := rem[j-1]
+
+ var err error
+ lastMajor = major
+ lastMajorHasGoMod, err = versionHasGoMod(latestAtMajor)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if lastMajorHasGoMod {
+ // The latest release of this major version has a go.mod file, so it is
+ // not allowed as +incompatible. It would be confusing to include some
+ // minor versions of this major version as +incompatible but require
+ // semantic import versioning for others, so drop all +incompatible
+ // versions for this major version.
+ //
+ // If we're wrong about a minor version in the middle, users will still be
+ // able to 'go get' specific tags for that version explicitly — they just
+ // won't appear in 'go list' or as the results for queries with inequality
+ // bounds.
+ continue
+ }
+ versions.List = append(versions.List, v+"+incompatible")
+ }
+
+ return versions, nil
+}
+
+func (r *codeRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
+ if rev == "latest" {
+ return r.Latest(ctx)
+ }
+ codeRev := r.revToRev(rev)
+ info, err := r.code.Stat(ctx, codeRev)
+ if err != nil {
+ // Note: info may be non-nil to supply Origin for caching error.
+ var revInfo *RevInfo
+ if info != nil {
+ revInfo = &RevInfo{
+ Origin: info.Origin,
+ Version: rev,
+ }
+ }
+ return revInfo, &module.ModuleError{
+ Path: r.modPath,
+ Err: &module.InvalidVersionError{
+ Version: rev,
+ Err: err,
+ },
+ }
+ }
+ return r.convert(ctx, info, rev)
+}
+
+func (r *codeRepo) Latest(ctx context.Context) (*RevInfo, error) {
+ info, err := r.code.Latest(ctx)
+ if err != nil {
+ if info != nil {
+ return &RevInfo{Origin: info.Origin}, err
+ }
+ return nil, err
+ }
+ return r.convert(ctx, info, "")
+}
+
+// convert converts a version as reported by the code host to a version as
+// interpreted by the module system.
+//
+// If statVers is a valid module version, it is used for the Version field.
+// Otherwise, the Version is derived from the passed-in info and recent tags.
+func (r *codeRepo) convert(ctx context.Context, info *codehost.RevInfo, statVers string) (revInfo *RevInfo, err error) {
+ defer func() {
+ if info.Origin == nil {
+ return
+ }
+ if revInfo == nil {
+ revInfo = new(RevInfo)
+ } else if revInfo.Origin != nil {
+ panic("internal error: RevInfo Origin unexpectedly already populated")
+ }
+
+ origin := *info.Origin
+ revInfo.Origin = &origin
+ origin.Subdir = r.codeDir
+
+ v := revInfo.Version
+ if module.IsPseudoVersion(v) && (v != statVers || !strings.HasPrefix(v, "v0.0.0-")) {
+ // Add tags that are relevant to pseudo-version calculation to origin.
+ prefix := r.codeDir
+ if prefix != "" {
+ prefix += "/"
+ }
+ if r.pathMajor != "" { // "/v2" or "/.v2"
+ prefix += r.pathMajor[1:] + "." // += "v2."
+ }
+ tags, tagsErr := r.code.Tags(ctx, prefix)
+ if tagsErr != nil {
+ revInfo.Origin = nil
+ if err == nil {
+ err = tagsErr
+ }
+ } else {
+ origin.TagPrefix = tags.Origin.TagPrefix
+ origin.TagSum = tags.Origin.TagSum
+ }
+ }
+ }()
+
+ // If this is a plain tag (no dir/ prefix)
+ // and the module path is unversioned,
+ // and if the underlying file tree has no go.mod,
+ // then allow using the tag with a +incompatible suffix.
+ //
+ // (If the version is +incompatible, then the go.mod file must not exist:
+ // +incompatible is not an ongoing opt-out from semantic import versioning.)
+ incompatibleOk := map[string]bool{}
+ canUseIncompatible := func(v string) bool {
+ if r.codeDir != "" || r.pathMajor != "" {
+ // A non-empty codeDir indicates a module within a subdirectory,
+ // which necessarily has a go.mod file indicating the module boundary.
+ // A non-empty pathMajor indicates a module path with a major-version
+ // suffix, which must match.
+ return false
+ }
+
+ ok, seen := incompatibleOk[""]
+ if !seen {
+ _, errGoMod := r.code.ReadFile(ctx, info.Name, "go.mod", codehost.MaxGoMod)
+ ok = (errGoMod != nil)
+ incompatibleOk[""] = ok
+ }
+ if !ok {
+ // A go.mod file exists at the repo root.
+ return false
+ }
+
+ // Per https://go.dev/issue/51324, previous versions of the 'go' command
+ // didn't always check for go.mod files in subdirectories, so if the user
+ // requests a +incompatible version explicitly, we should continue to allow
+ // it. Otherwise, if vN/go.mod exists, expect that release tags for that
+ // major version are intended for the vN module.
+ if v != "" && !strings.HasSuffix(statVers, "+incompatible") {
+ major := semver.Major(v)
+ ok, seen = incompatibleOk[major]
+ if !seen {
+ _, errGoModSub := r.code.ReadFile(ctx, info.Name, path.Join(major, "go.mod"), codehost.MaxGoMod)
+ ok = (errGoModSub != nil)
+ incompatibleOk[major] = ok
+ }
+ if !ok {
+ return false
+ }
+ }
+
+ return true
+ }
+
+ // checkCanonical verifies that the canonical version v is compatible with the
+ // module path represented by r, adding a "+incompatible" suffix if needed.
+ //
+ // If statVers is also canonical, checkCanonical also verifies that v is
+ // either statVers or statVers with the added "+incompatible" suffix.
+ checkCanonical := func(v string) (*RevInfo, error) {
+ // If r.codeDir is non-empty, then the go.mod file must exist: the module
+ // author — not the module consumer, — gets to decide how to carve up the repo
+ // into modules.
+ //
+ // Conversely, if the go.mod file exists, the module author — not the module
+ // consumer — gets to determine the module's path
+ //
+ // r.findDir verifies both of these conditions. Execute it now so that
+ // r.Stat will correctly return a notExistError if the go.mod location or
+ // declared module path doesn't match.
+ _, _, _, err := r.findDir(ctx, v)
+ if err != nil {
+ // TODO: It would be nice to return an error like "not a module".
+ // Right now we return "missing go.mod", which is a little confusing.
+ return nil, &module.ModuleError{
+ Path: r.modPath,
+ Err: &module.InvalidVersionError{
+ Version: v,
+ Err: notExistError{err: err},
+ },
+ }
+ }
+
+ invalidf := func(format string, args ...any) error {
+ return &module.ModuleError{
+ Path: r.modPath,
+ Err: &module.InvalidVersionError{
+ Version: v,
+ Err: fmt.Errorf(format, args...),
+ },
+ }
+ }
+
+ // Add the +incompatible suffix if needed or requested explicitly, and
+ // verify that its presence or absence is appropriate for this version
+ // (which depends on whether it has an explicit go.mod file).
+
+ if v == strings.TrimSuffix(statVers, "+incompatible") {
+ v = statVers
+ }
+ base := strings.TrimSuffix(v, "+incompatible")
+ var errIncompatible error
+ if !module.MatchPathMajor(base, r.pathMajor) {
+ if canUseIncompatible(base) {
+ v = base + "+incompatible"
+ } else {
+ if r.pathMajor != "" {
+ errIncompatible = invalidf("module path includes a major version suffix, so major version must match")
+ } else {
+ errIncompatible = invalidf("module contains a go.mod file, so module path must match major version (%q)", path.Join(r.pathPrefix, semver.Major(v)))
+ }
+ }
+ } else if strings.HasSuffix(v, "+incompatible") {
+ errIncompatible = invalidf("+incompatible suffix not allowed: major version %s is compatible", semver.Major(v))
+ }
+
+ if statVers != "" && statVers == module.CanonicalVersion(statVers) {
+ // Since the caller-requested version is canonical, it would be very
+ // confusing to resolve it to anything but itself, possibly with a
+ // "+incompatible" suffix. Error out explicitly.
+ if statBase := strings.TrimSuffix(statVers, "+incompatible"); statBase != base {
+ return nil, &module.ModuleError{
+ Path: r.modPath,
+ Err: &module.InvalidVersionError{
+ Version: statVers,
+ Err: fmt.Errorf("resolves to version %v (%s is not a tag)", v, statBase),
+ },
+ }
+ }
+ }
+
+ if errIncompatible != nil {
+ return nil, errIncompatible
+ }
+
+ return &RevInfo{
+ Name: info.Name,
+ Short: info.Short,
+ Time: info.Time,
+ Version: v,
+ }, nil
+ }
+
+ // Determine version.
+
+ if module.IsPseudoVersion(statVers) {
+ // Validate the go.mod location and major version before
+ // we check for an ancestor tagged with the pseude-version base.
+ //
+ // We can rule out an invalid subdirectory or major version with only
+ // shallow commit information, but checking the pseudo-version base may
+ // require downloading a (potentially more expensive) full history.
+ revInfo, err = checkCanonical(statVers)
+ if err != nil {
+ return revInfo, err
+ }
+ if err := r.validatePseudoVersion(ctx, info, statVers); err != nil {
+ return nil, err
+ }
+ return revInfo, nil
+ }
+
+ // statVers is not a pseudo-version, so we need to either resolve it to a
+ // canonical version or verify that it is already a canonical tag
+ // (not a branch).
+
+ // Derive or verify a version from a code repo tag.
+ // Tag must have a prefix matching codeDir.
+ tagPrefix := ""
+ if r.codeDir != "" {
+ tagPrefix = r.codeDir + "/"
+ }
+
+ isRetracted, err := r.retractedVersions(ctx)
+ if err != nil {
+ isRetracted = func(string) bool { return false }
+ }
+
+ // tagToVersion returns the version obtained by trimming tagPrefix from tag.
+ // If the tag is invalid, retracted, or a pseudo-version, tagToVersion returns
+ // an empty version.
+ tagToVersion := func(tag string) (v string, tagIsCanonical bool) {
+ if !strings.HasPrefix(tag, tagPrefix) {
+ return "", false
+ }
+ trimmed := tag[len(tagPrefix):]
+ // Tags that look like pseudo-versions would be confusing. Ignore them.
+ if module.IsPseudoVersion(tag) {
+ return "", false
+ }
+
+ v = semver.Canonical(trimmed) // Not module.Canonical: we don't want to pick up an explicit "+incompatible" suffix from the tag.
+ if v == "" || !strings.HasPrefix(trimmed, v) {
+ return "", false // Invalid or incomplete version (just vX or vX.Y).
+ }
+ if v == trimmed {
+ tagIsCanonical = true
+ }
+ return v, tagIsCanonical
+ }
+
+ // If the VCS gave us a valid version, use that.
+ if v, tagIsCanonical := tagToVersion(info.Version); tagIsCanonical {
+ if info, err := checkCanonical(v); err == nil {
+ return info, err
+ }
+ }
+
+ // Look through the tags on the revision for either a usable canonical version
+ // or an appropriate base for a pseudo-version.
+ var (
+ highestCanonical string
+ pseudoBase string
+ )
+ for _, pathTag := range info.Tags {
+ v, tagIsCanonical := tagToVersion(pathTag)
+ if statVers != "" && semver.Compare(v, statVers) == 0 {
+ // The tag is equivalent to the version requested by the user.
+ if tagIsCanonical {
+ // This tag is the canonical form of the requested version,
+ // not some other form with extra build metadata.
+ // Use this tag so that the resolved version will match exactly.
+ // (If it isn't actually allowed, we'll error out in checkCanonical.)
+ return checkCanonical(v)
+ } else {
+ // The user explicitly requested something equivalent to this tag. We
+ // can't use the version from the tag directly: since the tag is not
+ // canonical, it could be ambiguous. For example, tags v0.0.1+a and
+ // v0.0.1+b might both exist and refer to different revisions.
+ //
+ // The tag is otherwise valid for the module, so we can at least use it as
+ // the base of an unambiguous pseudo-version.
+ //
+ // If multiple tags match, tagToVersion will canonicalize them to the same
+ // base version.
+ pseudoBase = v
+ }
+ }
+ // Save the highest non-retracted canonical tag for the revision.
+ // If we don't find a better match, we'll use it as the canonical version.
+ if tagIsCanonical && semver.Compare(highestCanonical, v) < 0 && !isRetracted(v) {
+ if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible(v) {
+ highestCanonical = v
+ }
+ }
+ }
+
+ // If we found a valid canonical tag for the revision, return it.
+ // Even if we found a good pseudo-version base, a canonical version is better.
+ if highestCanonical != "" {
+ return checkCanonical(highestCanonical)
+ }
+
+ // Find the highest tagged version in the revision's history, subject to
+ // major version and +incompatible constraints. Use that version as the
+ // pseudo-version base so that the pseudo-version sorts higher. Ignore
+ // retracted versions.
+ tagAllowed := func(tag string) bool {
+ v, _ := tagToVersion(tag)
+ if v == "" {
+ return false
+ }
+ if !module.MatchPathMajor(v, r.pathMajor) && !canUseIncompatible(v) {
+ return false
+ }
+ return !isRetracted(v)
+ }
+ if pseudoBase == "" {
+ tag, err := r.code.RecentTag(ctx, info.Name, tagPrefix, tagAllowed)
+ if err != nil && !errors.Is(err, errors.ErrUnsupported) {
+ return nil, err
+ }
+ if tag != "" {
+ pseudoBase, _ = tagToVersion(tag)
+ }
+ }
+
+ return checkCanonical(module.PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short))
+}
+
+// validatePseudoVersion checks that version has a major version compatible with
+// r.modPath and encodes a base version and commit metadata that agrees with
+// info.
+//
+// Note that verifying a nontrivial base version in particular may be somewhat
+// expensive: in order to do so, r.code.DescendsFrom will need to fetch at least
+// enough of the commit history to find a path between version and its base.
+// Fortunately, many pseudo-versions — such as those for untagged repositories —
+// have trivial bases!
+func (r *codeRepo) validatePseudoVersion(ctx context.Context, info *codehost.RevInfo, version string) (err error) {
+ defer func() {
+ if err != nil {
+ if _, ok := err.(*module.ModuleError); !ok {
+ if _, ok := err.(*module.InvalidVersionError); !ok {
+ err = &module.InvalidVersionError{Version: version, Pseudo: true, Err: err}
+ }
+ err = &module.ModuleError{Path: r.modPath, Err: err}
+ }
+ }
+ }()
+
+ rev, err := module.PseudoVersionRev(version)
+ if err != nil {
+ return err
+ }
+ if rev != info.Short {
+ switch {
+ case strings.HasPrefix(rev, info.Short):
+ return fmt.Errorf("revision is longer than canonical (expected %s)", info.Short)
+ case strings.HasPrefix(info.Short, rev):
+ return fmt.Errorf("revision is shorter than canonical (expected %s)", info.Short)
+ default:
+ return fmt.Errorf("does not match short name of revision (expected %s)", info.Short)
+ }
+ }
+
+ t, err := module.PseudoVersionTime(version)
+ if err != nil {
+ return err
+ }
+ if !t.Equal(info.Time.Truncate(time.Second)) {
+ return fmt.Errorf("does not match version-control timestamp (expected %s)", info.Time.UTC().Format(module.PseudoVersionTimestampFormat))
+ }
+
+ tagPrefix := ""
+ if r.codeDir != "" {
+ tagPrefix = r.codeDir + "/"
+ }
+
+ // A pseudo-version should have a precedence just above its parent revisions,
+ // and no higher. Otherwise, it would be possible for library authors to "pin"
+ // dependency versions (and bypass the usual minimum version selection) by
+ // naming an extremely high pseudo-version rather than an accurate one.
+ //
+ // Moreover, if we allow a pseudo-version to use any arbitrary pre-release
+ // tag, we end up with infinitely many possible names for each commit. Each
+ // name consumes resources in the module cache and proxies, so we want to
+ // restrict them to a finite set under control of the module author.
+ //
+ // We address both of these issues by requiring the tag upon which the
+ // pseudo-version is based to refer to some ancestor of the revision. We
+ // prefer the highest such tag when constructing a new pseudo-version, but do
+ // not enforce that property when resolving existing pseudo-versions: we don't
+ // know when the parent tags were added, and the highest-tagged parent may not
+ // have existed when the pseudo-version was first resolved.
+ base, err := module.PseudoVersionBase(strings.TrimSuffix(version, "+incompatible"))
+ if err != nil {
+ return err
+ }
+ if base == "" {
+ if r.pseudoMajor == "" && semver.Major(version) == "v1" {
+ return fmt.Errorf("major version without preceding tag must be v0, not v1")
+ }
+ return nil
+ } else {
+ for _, tag := range info.Tags {
+ versionOnly := strings.TrimPrefix(tag, tagPrefix)
+ if versionOnly == base {
+ // The base version is canonical, so if the version from the tag is
+ // literally equal (not just equivalent), then the tag is canonical too.
+ //
+ // We allow pseudo-versions to be derived from non-canonical tags on the
+ // same commit, so that tags like "v1.1.0+some-metadata" resolve as
+ // close as possible to the canonical version ("v1.1.0") while still
+ // enforcing a total ordering ("v1.1.1-0.[…]" with a unique suffix).
+ //
+ // However, canonical tags already have a total ordering, so there is no
+ // reason not to use the canonical tag directly, and we know that the
+ // canonical tag must already exist because the pseudo-version is
+ // derived from it. In that case, referring to the revision by a
+ // pseudo-version derived from its own canonical tag is just confusing.
+ return fmt.Errorf("tag (%s) found on revision %s is already canonical, so should not be replaced with a pseudo-version derived from that tag", tag, rev)
+ }
+ }
+ }
+
+ tags, err := r.code.Tags(ctx, tagPrefix+base)
+ if err != nil {
+ return err
+ }
+
+ var lastTag string // Prefer to log some real tag rather than a canonically-equivalent base.
+ ancestorFound := false
+ for _, tag := range tags.List {
+ versionOnly := strings.TrimPrefix(tag.Name, tagPrefix)
+ if semver.Compare(versionOnly, base) == 0 {
+ lastTag = tag.Name
+ ancestorFound, err = r.code.DescendsFrom(ctx, info.Name, tag.Name)
+ if ancestorFound {
+ break
+ }
+ }
+ }
+
+ if lastTag == "" {
+ return fmt.Errorf("preceding tag (%s) not found", base)
+ }
+
+ if !ancestorFound {
+ if err != nil {
+ return err
+ }
+ rev, err := module.PseudoVersionRev(version)
+ if err != nil {
+ return fmt.Errorf("not a descendent of preceding tag (%s)", lastTag)
+ }
+ return fmt.Errorf("revision %s is not a descendent of preceding tag (%s)", rev, lastTag)
+ }
+ return nil
+}
+
+func (r *codeRepo) revToRev(rev string) string {
+ if semver.IsValid(rev) {
+ if module.IsPseudoVersion(rev) {
+ r, _ := module.PseudoVersionRev(rev)
+ return r
+ }
+ if semver.Build(rev) == "+incompatible" {
+ rev = rev[:len(rev)-len("+incompatible")]
+ }
+ if r.codeDir == "" {
+ return rev
+ }
+ return r.codeDir + "/" + rev
+ }
+ return rev
+}
+
+func (r *codeRepo) versionToRev(version string) (rev string, err error) {
+ if !semver.IsValid(version) {
+ return "", &module.ModuleError{
+ Path: r.modPath,
+ Err: &module.InvalidVersionError{
+ Version: version,
+ Err: errors.New("syntax error"),
+ },
+ }
+ }
+ return r.revToRev(version), nil
+}
+
+// findDir locates the directory within the repo containing the module.
+//
+// If r.pathMajor is non-empty, this can be either r.codeDir or — if a go.mod
+// file exists — r.codeDir/r.pathMajor[1:].
+func (r *codeRepo) findDir(ctx context.Context, version string) (rev, dir string, gomod []byte, err error) {
+ rev, err = r.versionToRev(version)
+ if err != nil {
+ return "", "", nil, err
+ }
+
+ // Load info about go.mod but delay consideration
+ // (except I/O error) until we rule out v2/go.mod.
+ file1 := path.Join(r.codeDir, "go.mod")
+ gomod1, err1 := r.code.ReadFile(ctx, rev, file1, codehost.MaxGoMod)
+ if err1 != nil && !os.IsNotExist(err1) {
+ return "", "", nil, fmt.Errorf("reading %s/%s at revision %s: %v", r.codeRoot, file1, rev, err1)
+ }
+ mpath1 := modfile.ModulePath(gomod1)
+ found1 := err1 == nil && (isMajor(mpath1, r.pathMajor) || r.canReplaceMismatchedVersionDueToBug(mpath1))
+
+ var file2 string
+ if r.pathMajor != "" && r.codeRoot != r.modPath && !strings.HasPrefix(r.pathMajor, ".") {
+ // Suppose pathMajor is "/v2".
+ // Either go.mod should claim v2 and v2/go.mod should not exist,
+ // or v2/go.mod should exist and claim v2. Not both.
+ // Note that we don't check the full path, just the major suffix,
+ // because of replacement modules. This might be a fork of
+ // the real module, found at a different path, usable only in
+ // a replace directive.
+ dir2 := path.Join(r.codeDir, r.pathMajor[1:])
+ file2 = path.Join(dir2, "go.mod")
+ gomod2, err2 := r.code.ReadFile(ctx, rev, file2, codehost.MaxGoMod)
+ if err2 != nil && !os.IsNotExist(err2) {
+ return "", "", nil, fmt.Errorf("reading %s/%s at revision %s: %v", r.codeRoot, file2, rev, err2)
+ }
+ mpath2 := modfile.ModulePath(gomod2)
+ found2 := err2 == nil && isMajor(mpath2, r.pathMajor)
+
+ if found1 && found2 {
+ return "", "", nil, fmt.Errorf("%s/%s and ...%s/go.mod both have ...%s module paths at revision %s", r.pathPrefix, file1, r.pathMajor, r.pathMajor, rev)
+ }
+ if found2 {
+ return rev, dir2, gomod2, nil
+ }
+ if err2 == nil {
+ if mpath2 == "" {
+ return "", "", nil, fmt.Errorf("%s/%s is missing module path at revision %s", r.codeRoot, file2, rev)
+ }
+ return "", "", nil, fmt.Errorf("%s/%s has non-...%s module path %q at revision %s", r.codeRoot, file2, r.pathMajor, mpath2, rev)
+ }
+ }
+
+ // Not v2/go.mod, so it's either go.mod or nothing. Which is it?
+ if found1 {
+ // Explicit go.mod with matching major version ok.
+ return rev, r.codeDir, gomod1, nil
+ }
+ if err1 == nil {
+ // Explicit go.mod with non-matching major version disallowed.
+ suffix := ""
+ if file2 != "" {
+ suffix = fmt.Sprintf(" (and ...%s/go.mod does not exist)", r.pathMajor)
+ }
+ if mpath1 == "" {
+ return "", "", nil, fmt.Errorf("%s is missing module path%s at revision %s", file1, suffix, rev)
+ }
+ if r.pathMajor != "" { // ".v1", ".v2" for gopkg.in
+ return "", "", nil, fmt.Errorf("%s has non-...%s module path %q%s at revision %s", file1, r.pathMajor, mpath1, suffix, rev)
+ }
+ if _, _, ok := module.SplitPathVersion(mpath1); !ok {
+ return "", "", nil, fmt.Errorf("%s has malformed module path %q%s at revision %s", file1, mpath1, suffix, rev)
+ }
+ return "", "", nil, fmt.Errorf("%s has post-%s module path %q%s at revision %s", file1, semver.Major(version), mpath1, suffix, rev)
+ }
+
+ if r.codeDir == "" && (r.pathMajor == "" || strings.HasPrefix(r.pathMajor, ".")) {
+ // Implicit go.mod at root of repo OK for v0/v1 and for gopkg.in.
+ return rev, "", nil, nil
+ }
+
+ // Implicit go.mod below root of repo or at v2+ disallowed.
+ // Be clear about possibility of using either location for v2+.
+ if file2 != "" {
+ return "", "", nil, fmt.Errorf("missing %s/go.mod and ...%s/go.mod at revision %s", r.pathPrefix, r.pathMajor, rev)
+ }
+ return "", "", nil, fmt.Errorf("missing %s/go.mod at revision %s", r.pathPrefix, rev)
+}
+
+// isMajor reports whether the versions allowed for mpath are compatible with
+// the major version(s) implied by pathMajor, or false if mpath has an invalid
+// version suffix.
+func isMajor(mpath, pathMajor string) bool {
+ if mpath == "" {
+ // If we don't have a path, we don't know what version(s) it is compatible with.
+ return false
+ }
+ _, mpathMajor, ok := module.SplitPathVersion(mpath)
+ if !ok {
+ // An invalid module path is not compatible with any version.
+ return false
+ }
+ if pathMajor == "" {
+ // All of the valid versions for a gopkg.in module that requires major
+ // version v0 or v1 are compatible with the "v0 or v1" implied by an empty
+ // pathMajor.
+ switch module.PathMajorPrefix(mpathMajor) {
+ case "", "v0", "v1":
+ return true
+ default:
+ return false
+ }
+ }
+ if mpathMajor == "" {
+ // Even if pathMajor is ".v0" or ".v1", we can't be sure that a module
+ // without a suffix is tagged appropriately. Besides, we don't expect clones
+ // of non-gopkg.in modules to have gopkg.in paths, so a non-empty,
+ // non-gopkg.in mpath is probably the wrong module for any such pathMajor
+ // anyway.
+ return false
+ }
+ // If both pathMajor and mpathMajor are non-empty, then we only care that they
+ // have the same major-version validation rules. A clone fetched via a /v2
+ // path might replace a module with path gopkg.in/foo.v2-unstable, and that's
+ // ok.
+ return pathMajor[1:] == mpathMajor[1:]
+}
+
+// canReplaceMismatchedVersionDueToBug reports whether versions of r
+// could replace versions of mpath with otherwise-mismatched major versions
+// due to a historical bug in the Go command (golang.org/issue/34254).
+func (r *codeRepo) canReplaceMismatchedVersionDueToBug(mpath string) bool {
+ // The bug caused us to erroneously accept unversioned paths as replacements
+ // for versioned gopkg.in paths.
+ unversioned := r.pathMajor == ""
+ replacingGopkgIn := strings.HasPrefix(mpath, "gopkg.in/")
+ return unversioned && replacingGopkgIn
+}
+
+func (r *codeRepo) GoMod(ctx context.Context, version string) (data []byte, err error) {
+ if version != module.CanonicalVersion(version) {
+ return nil, fmt.Errorf("version %s is not canonical", version)
+ }
+
+ if module.IsPseudoVersion(version) {
+ // findDir ignores the metadata encoded in a pseudo-version,
+ // only using the revision at the end.
+ // Invoke Stat to verify the metadata explicitly so we don't return
+ // a bogus file for an invalid version.
+ _, err := r.Stat(ctx, version)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ rev, dir, gomod, err := r.findDir(ctx, version)
+ if err != nil {
+ return nil, err
+ }
+ if gomod != nil {
+ return gomod, nil
+ }
+ data, err = r.code.ReadFile(ctx, rev, path.Join(dir, "go.mod"), codehost.MaxGoMod)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return LegacyGoMod(r.modPath), nil
+ }
+ return nil, err
+ }
+ return data, nil
+}
+
+// LegacyGoMod generates a fake go.mod file for a module that doesn't have one.
+// The go.mod file contains a module directive and nothing else: no go version,
+// no requirements.
+//
+// We used to try to build a go.mod reflecting pre-existing
+// package management metadata files, but the conversion
+// was inherently imperfect (because those files don't have
+// exactly the same semantics as go.mod) and, when done
+// for dependencies in the middle of a build, impossible to
+// correct. So we stopped.
+func LegacyGoMod(modPath string) []byte {
+ return fmt.Appendf(nil, "module %s\n", modfile.AutoQuote(modPath))
+}
+
+func (r *codeRepo) modPrefix(rev string) string {
+ return r.modPath + "@" + rev
+}
+
+func (r *codeRepo) retractedVersions(ctx context.Context) (func(string) bool, error) {
+ vs, err := r.Versions(ctx, "")
+ if err != nil {
+ return nil, err
+ }
+ versions := vs.List
+
+ for i, v := range versions {
+ if strings.HasSuffix(v, "+incompatible") {
+ // We're looking for the latest release tag that may list retractions in a
+ // go.mod file. +incompatible versions necessarily do not, and they start
+ // at major version 2 — which is higher than any version that could
+ // validly contain a go.mod file.
+ versions = versions[:i]
+ break
+ }
+ }
+ if len(versions) == 0 {
+ return func(string) bool { return false }, nil
+ }
+
+ var highest string
+ for i := len(versions) - 1; i >= 0; i-- {
+ v := versions[i]
+ if semver.Prerelease(v) == "" {
+ highest = v
+ break
+ }
+ }
+ if highest == "" {
+ highest = versions[len(versions)-1]
+ }
+
+ data, err := r.GoMod(ctx, highest)
+ if err != nil {
+ return nil, err
+ }
+ f, err := modfile.ParseLax("go.mod", data, nil)
+ if err != nil {
+ return nil, err
+ }
+ retractions := make([]modfile.VersionInterval, 0, len(f.Retract))
+ for _, r := range f.Retract {
+ retractions = append(retractions, r.VersionInterval)
+ }
+
+ return func(v string) bool {
+ for _, r := range retractions {
+ if semver.Compare(r.Low, v) <= 0 && semver.Compare(v, r.High) <= 0 {
+ return true
+ }
+ }
+ return false
+ }, nil
+}
+
+func (r *codeRepo) Zip(ctx context.Context, dst io.Writer, version string) error {
+ if version != module.CanonicalVersion(version) {
+ return fmt.Errorf("version %s is not canonical", version)
+ }
+
+ if module.IsPseudoVersion(version) {
+ // findDir ignores the metadata encoded in a pseudo-version,
+ // only using the revision at the end.
+ // Invoke Stat to verify the metadata explicitly so we don't return
+ // a bogus file for an invalid version.
+ _, err := r.Stat(ctx, version)
+ if err != nil {
+ return err
+ }
+ }
+
+ rev, subdir, _, err := r.findDir(ctx, version)
+ if err != nil {
+ return err
+ }
+
+ if gomod, err := r.code.ReadFile(ctx, rev, filepath.Join(subdir, "go.mod"), codehost.MaxGoMod); err == nil {
+ goVers := gover.GoModLookup(gomod, "go")
+ if gover.Compare(goVers, gover.Local()) > 0 {
+ return &gover.TooNewError{What: r.ModulePath() + "@" + version, GoVersion: goVers}
+ }
+ } else if !errors.Is(err, fs.ErrNotExist) {
+ return err
+ }
+
+ dl, err := r.code.ReadZip(ctx, rev, subdir, codehost.MaxZipFile)
+ if err != nil {
+ return err
+ }
+ defer dl.Close()
+ subdir = strings.Trim(subdir, "/")
+
+ // Spool to local file.
+ f, err := os.CreateTemp("", "go-codehost-")
+ if err != nil {
+ dl.Close()
+ return err
+ }
+ defer os.Remove(f.Name())
+ defer f.Close()
+ maxSize := int64(codehost.MaxZipFile)
+ lr := &io.LimitedReader{R: dl, N: maxSize + 1}
+ if _, err := io.Copy(f, lr); err != nil {
+ dl.Close()
+ return err
+ }
+ dl.Close()
+ if lr.N <= 0 {
+ return fmt.Errorf("downloaded zip file too large")
+ }
+ size := (maxSize + 1) - lr.N
+ if _, err := f.Seek(0, 0); err != nil {
+ return err
+ }
+
+ // Translate from zip file we have to zip file we want.
+ zr, err := zip.NewReader(f, size)
+ if err != nil {
+ return err
+ }
+
+ var files []modzip.File
+ if subdir != "" {
+ subdir += "/"
+ }
+ haveLICENSE := false
+ topPrefix := ""
+ for _, zf := range zr.File {
+ if topPrefix == "" {
+ i := strings.Index(zf.Name, "/")
+ if i < 0 {
+ return fmt.Errorf("missing top-level directory prefix")
+ }
+ topPrefix = zf.Name[:i+1]
+ }
+ var name string
+ var found bool
+ if name, found = strings.CutPrefix(zf.Name, topPrefix); !found {
+ return fmt.Errorf("zip file contains more than one top-level directory")
+ }
+
+ if name, found = strings.CutPrefix(name, subdir); !found {
+ continue
+ }
+
+ if name == "" || strings.HasSuffix(name, "/") {
+ continue
+ }
+ files = append(files, zipFile{name: name, f: zf})
+ if name == "LICENSE" {
+ haveLICENSE = true
+ }
+ }
+
+ if !haveLICENSE && subdir != "" {
+ data, err := r.code.ReadFile(ctx, rev, "LICENSE", codehost.MaxLICENSE)
+ if err == nil {
+ files = append(files, dataFile{name: "LICENSE", data: data})
+ }
+ }
+
+ return modzip.Create(dst, module.Version{Path: r.modPath, Version: version}, files)
+}
+
+type zipFile struct {
+ name string
+ f *zip.File
+}
+
+func (f zipFile) Path() string { return f.name }
+func (f zipFile) Lstat() (fs.FileInfo, error) { return f.f.FileInfo(), nil }
+func (f zipFile) Open() (io.ReadCloser, error) { return f.f.Open() }
+
+type dataFile struct {
+ name string
+ data []byte
+}
+
+func (f dataFile) Path() string { return f.name }
+func (f dataFile) Lstat() (fs.FileInfo, error) { return dataFileInfo{f}, nil }
+func (f dataFile) Open() (io.ReadCloser, error) {
+ return io.NopCloser(bytes.NewReader(f.data)), nil
+}
+
+type dataFileInfo struct {
+ f dataFile
+}
+
+func (fi dataFileInfo) Name() string { return path.Base(fi.f.name) }
+func (fi dataFileInfo) Size() int64 { return int64(len(fi.f.data)) }
+func (fi dataFileInfo) Mode() fs.FileMode { return 0644 }
+func (fi dataFileInfo) ModTime() time.Time { return time.Time{} }
+func (fi dataFileInfo) IsDir() bool { return false }
+func (fi dataFileInfo) Sys() any { return nil }
+
+func (fi dataFileInfo) String() string {
+ return fs.FormatFileInfo(fi)
+}
+
+// hasPathPrefix reports whether the path s begins with the
+// elements in prefix.
+func hasPathPrefix(s, prefix string) bool {
+ switch {
+ default:
+ return false
+ case len(s) == len(prefix):
+ return s == prefix
+ case len(s) > len(prefix):
+ if prefix != "" && prefix[len(prefix)-1] == '/' {
+ return strings.HasPrefix(s, prefix)
+ }
+ return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
+ }
+}
diff --git a/src/cmd/go/internal/modfetch/coderepo_test.go b/src/cmd/go/internal/modfetch/coderepo_test.go
new file mode 100644
index 0000000..aad7872
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/coderepo_test.go
@@ -0,0 +1,965 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modfetch
+
+import (
+ "archive/zip"
+ "context"
+ "crypto/sha256"
+ "encoding/hex"
+ "flag"
+ "hash"
+ "internal/testenv"
+ "io"
+ "log"
+ "os"
+ "path/filepath"
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/modfetch/codehost"
+ "cmd/go/internal/vcweb/vcstest"
+
+ "golang.org/x/mod/sumdb/dirhash"
+)
+
+func TestMain(m *testing.M) {
+ flag.Parse()
+ if err := testMain(m); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func testMain(m *testing.M) (err error) {
+
+ cfg.GOPROXY = "direct"
+
+ // The sum database is populated using a released version of the go command,
+ // but this test may include fixes for additional modules that previously
+ // could not be fetched. Since this test isn't executing any of the resolved
+ // code, bypass the sum database.
+ cfg.GOSUMDB = "off"
+
+ dir, err := os.MkdirTemp("", "gitrepo-test-")
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if rmErr := os.RemoveAll(dir); err == nil {
+ err = rmErr
+ }
+ }()
+
+ cfg.GOMODCACHE = filepath.Join(dir, "modcache")
+ if err := os.Mkdir(cfg.GOMODCACHE, 0755); err != nil {
+ return err
+ }
+
+ srv, err := vcstest.NewServer()
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if closeErr := srv.Close(); err == nil {
+ err = closeErr
+ }
+ }()
+
+ m.Run()
+ return nil
+}
+
+const (
+ vgotest1git = "github.com/rsc/vgotest1"
+ vgotest1hg = "vcs-test.golang.org/hg/vgotest1.hg"
+)
+
+var altVgotests = map[string]string{
+ "hg": vgotest1hg,
+}
+
+type codeRepoTest struct {
+ vcs string
+ path string
+ mpath string
+ rev string
+ err string
+ version string
+ name string
+ short string
+ time time.Time
+ gomod string
+ gomodErr string
+ zip []string
+ zipErr string
+ zipSum string
+ zipFileHash string
+}
+
+var codeRepoTests = []codeRepoTest{
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1",
+ rev: "v0.0.0",
+ version: "v0.0.0",
+ name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
+ short: "80d85c5d4d17",
+ time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
+ zip: []string{
+ "LICENSE",
+ "README.md",
+ "pkg/p.go",
+ },
+ zipSum: "h1:zVEjciLdlk/TPWCOyZo7k24T+tOKRQC+u8MKq/xS80I=",
+ zipFileHash: "738a00ddbfe8c329dce6b48e1f23c8e22a92db50f3cfb2653caa0d62676bc09c",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1",
+ rev: "v0.0.0-20180219231006-80d85c5d4d17",
+ version: "v0.0.0-20180219231006-80d85c5d4d17",
+ name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
+ short: "80d85c5d4d17",
+ time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
+ zip: []string{
+ "LICENSE",
+ "README.md",
+ "pkg/p.go",
+ },
+ zipSum: "h1:nOznk2xKsLGkTnXe0q9t1Ewt9jxK+oadtafSUqHM3Ec=",
+ zipFileHash: "bacb08f391e29d2eaaef8281b5c129ee6d890e608ee65877e0003c0181a766c8",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1",
+ rev: "v0.0.1-0.20180219231006-80d85c5d4d17",
+ err: `github.com/rsc/vgotest1@v0.0.1-0.20180219231006-80d85c5d4d17: invalid pseudo-version: tag (v0.0.0) found on revision 80d85c5d4d17 is already canonical, so should not be replaced with a pseudo-version derived from that tag`,
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1",
+ rev: "v1.0.0",
+ version: "v1.0.0",
+ name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
+ short: "80d85c5d4d17",
+ time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
+ zip: []string{
+ "LICENSE",
+ "README.md",
+ "pkg/p.go",
+ },
+ zipSum: "h1:e040hOoWGeuJLawDjK9DW6med+cz9FxMFYDMOVG8ctQ=",
+ zipFileHash: "74caab65cfbea427c341fa815f3bb0378681d8f0e3cf62a7f207014263ec7be3",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/v2",
+ rev: "v2.0.0",
+ version: "v2.0.0",
+ name: "45f53230a74ad275c7127e117ac46914c8126160",
+ short: "45f53230a74a",
+ time: time.Date(2018, 7, 19, 1, 21, 27, 0, time.UTC),
+ err: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1",
+ rev: "80d85c5",
+ version: "v1.0.0",
+ name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
+ short: "80d85c5d4d17",
+ time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
+ zip: []string{
+ "LICENSE",
+ "README.md",
+ "pkg/p.go",
+ },
+ zipSum: "h1:e040hOoWGeuJLawDjK9DW6med+cz9FxMFYDMOVG8ctQ=",
+ zipFileHash: "74caab65cfbea427c341fa815f3bb0378681d8f0e3cf62a7f207014263ec7be3",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1",
+ rev: "mytag",
+ version: "v1.0.0",
+ name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
+ short: "80d85c5d4d17",
+ time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
+ zip: []string{
+ "LICENSE",
+ "README.md",
+ "pkg/p.go",
+ },
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/v2",
+ rev: "45f53230a",
+ version: "v2.0.0",
+ name: "45f53230a74ad275c7127e117ac46914c8126160",
+ short: "45f53230a74a",
+ time: time.Date(2018, 7, 19, 1, 21, 27, 0, time.UTC),
+ err: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/v54321",
+ rev: "80d85c5",
+ version: "v54321.0.0-20180219231006-80d85c5d4d17",
+ name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
+ short: "80d85c5d4d17",
+ time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
+ err: "missing github.com/rsc/vgotest1/go.mod and .../v54321/go.mod at revision 80d85c5d4d17",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/submod",
+ rev: "v1.0.0",
+ err: "unknown revision submod/v1.0.0",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/submod",
+ rev: "v1.0.3",
+ err: "unknown revision submod/v1.0.3",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/submod",
+ rev: "v1.0.4",
+ version: "v1.0.4",
+ name: "8afe2b2efed96e0880ecd2a69b98a53b8c2738b6",
+ short: "8afe2b2efed9",
+ time: time.Date(2018, 2, 19, 23, 12, 7, 0, time.UTC),
+ gomod: "module \"github.com/vgotest1/submod\" // submod/go.mod\n",
+ zip: []string{
+ "go.mod",
+ "pkg/p.go",
+ "LICENSE",
+ },
+ zipSum: "h1:iMsJ/9uQsk6MnZNnJK311f11QiSlmN92Q2aSjCywuJY=",
+ zipFileHash: "95801bfa69c5197ae809af512946d22f22850068527cd78100ae3f176bc8043b",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1",
+ rev: "v1.1.0",
+ version: "v1.1.0",
+ name: "b769f2de407a4db81af9c5de0a06016d60d2ea09",
+ short: "b769f2de407a",
+ time: time.Date(2018, 2, 19, 23, 13, 36, 0, time.UTC),
+ gomod: "module \"github.com/rsc/vgotest1\" // root go.mod\nrequire \"github.com/rsc/vgotest1/submod\" v1.0.5\n",
+ zip: []string{
+ "LICENSE",
+ "README.md",
+ "go.mod",
+ "pkg/p.go",
+ },
+ zipSum: "h1:M69k7q+8bQ+QUpHov45Z/NoR8rj3DsQJUnXLWvf01+Q=",
+ zipFileHash: "58af45fb248d320ea471f568e006379e2b8d71d6d1663f9b19b2e00fd9ac9265",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/v2",
+ rev: "v2.0.1",
+ version: "v2.0.1",
+ name: "ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9",
+ short: "ea65f87c8f52",
+ time: time.Date(2018, 2, 19, 23, 14, 23, 0, time.UTC),
+ gomod: "module \"github.com/rsc/vgotest1/v2\" // root go.mod\n",
+ zipSum: "h1:QmgYy/zt+uoWhDpcsgrSVzYFvKtBEjl5zT/FRz9GTzA=",
+ zipFileHash: "1aedf1546d322a0121879ddfd6d0e8bfbd916d2cafbeb538ddb440e04b04b9ef",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/v2",
+ rev: "v2.0.3",
+ version: "v2.0.3",
+ name: "f18795870fb14388a21ef3ebc1d75911c8694f31",
+ short: "f18795870fb1",
+ time: time.Date(2018, 2, 19, 23, 16, 4, 0, time.UTC),
+ err: "github.com/rsc/vgotest1/v2/go.mod has non-.../v2 module path \"github.com/rsc/vgotest\" at revision v2.0.3",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/v2",
+ rev: "v2.0.4",
+ version: "v2.0.4",
+ name: "1f863feb76bc7029b78b21c5375644838962f88d",
+ short: "1f863feb76bc",
+ time: time.Date(2018, 2, 20, 0, 3, 38, 0, time.UTC),
+ err: "github.com/rsc/vgotest1/go.mod and .../v2/go.mod both have .../v2 module paths at revision v2.0.4",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/v2",
+ rev: "v2.0.5",
+ version: "v2.0.5",
+ name: "2f615117ce481c8efef46e0cc0b4b4dccfac8fea",
+ short: "2f615117ce48",
+ time: time.Date(2018, 2, 20, 0, 3, 59, 0, time.UTC),
+ gomod: "module \"github.com/rsc/vgotest1/v2\" // v2/go.mod\n",
+ zipSum: "h1:RIEb9q1SUSEQOzMn0zfl/LQxGFWlhWEAdeEguf1MLGU=",
+ zipFileHash: "7d92c2c328c5e9b0694101353705d5843746ec1d93a1e986d0da54c8a14dfe6d",
+ },
+ {
+ // redirect to github
+ vcs: "git",
+ path: "rsc.io/quote",
+ rev: "v1.0.0",
+ version: "v1.0.0",
+ name: "f488df80bcdbd3e5bafdc24ad7d1e79e83edd7e6",
+ short: "f488df80bcdb",
+ time: time.Date(2018, 2, 14, 0, 45, 20, 0, time.UTC),
+ gomod: "module \"rsc.io/quote\"\n",
+ zipSum: "h1:haUSojyo3j2M9g7CEUFG8Na09dtn7QKxvPGaPVQdGwM=",
+ zipFileHash: "5c08ba2c09a364f93704aaa780e7504346102c6ef4fe1333a11f09904a732078",
+ },
+ {
+ // redirect to static hosting proxy
+ vcs: "mod",
+ path: "swtch.com/testmod",
+ rev: "v1.0.0",
+ version: "v1.0.0",
+ // NO name or short - we intentionally ignore those in the proxy protocol
+ time: time.Date(1972, 7, 18, 12, 34, 56, 0, time.UTC),
+ gomod: "module \"swtch.com/testmod\"\n",
+ },
+ {
+ // redirect to googlesource
+ vcs: "git",
+ path: "golang.org/x/text",
+ rev: "4e4a3210bb",
+ version: "v0.3.1-0.20180208041248-4e4a3210bb54",
+ name: "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1",
+ short: "4e4a3210bb54",
+ time: time.Date(2018, 2, 8, 4, 12, 48, 0, time.UTC),
+ zipSum: "h1:Yxu6pHX9X2RECiuw/Q5/4uvajuaowck8zOFKXgbfNBk=",
+ zipFileHash: "ac2c165a5c10aa5a7545dea60a08e019270b982fa6c8bdcb5943931de64922fe",
+ },
+ {
+ vcs: "git",
+ path: "github.com/pkg/errors",
+ rev: "v0.8.0",
+ version: "v0.8.0",
+ name: "645ef00459ed84a119197bfb8d8205042c6df63d",
+ short: "645ef00459ed",
+ time: time.Date(2016, 9, 29, 1, 48, 1, 0, time.UTC),
+ zipSum: "h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=",
+ zipFileHash: "e4fa69ba057356614edbc1da881a7d3ebb688505be49f65965686bcb859e2fae",
+ },
+ {
+ // package in subdirectory - custom domain
+ // In general we can't reject these definitively in Lookup,
+ // but gopkg.in is special.
+ vcs: "git",
+ path: "gopkg.in/yaml.v2/abc",
+ err: "invalid module path \"gopkg.in/yaml.v2/abc\"",
+ },
+ {
+ // package in subdirectory - github
+ // Because it's a package, Stat should fail entirely.
+ vcs: "git",
+ path: "github.com/rsc/quote/buggy",
+ rev: "c4d4236f",
+ err: "missing github.com/rsc/quote/buggy/go.mod at revision c4d4236f9242",
+ },
+ {
+ vcs: "git",
+ path: "gopkg.in/yaml.v2",
+ rev: "d670f940",
+ version: "v2.0.0",
+ name: "d670f9405373e636a5a2765eea47fac0c9bc91a4",
+ short: "d670f9405373",
+ time: time.Date(2018, 1, 9, 11, 43, 31, 0, time.UTC),
+ gomod: "module gopkg.in/yaml.v2\n",
+ zipSum: "h1:uUkhRGrsEyx/laRdeS6YIQKIys8pg+lRSRdVMTYjivs=",
+ zipFileHash: "7b0a141b1b0b49772ab4eecfd11dfd6609a94a5e868cab04a3abb1861ffaa877",
+ },
+ {
+ vcs: "git",
+ path: "gopkg.in/check.v1",
+ rev: "20d25e280405",
+ version: "v1.0.0-20161208181325-20d25e280405",
+ name: "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec",
+ short: "20d25e280405",
+ time: time.Date(2016, 12, 8, 18, 13, 25, 0, time.UTC),
+ gomod: "module gopkg.in/check.v1\n",
+ zipSum: "h1:829vOVxxusYHC+IqBtkX5mbKtsY9fheQiQn0MZRVLfQ=",
+ zipFileHash: "9e7cb3f4f1e66d722306442b0dbe1f6f43d74d1736d54c510537bdfb1d6f432f",
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/go/mod/gitrepo1",
+ rev: "master",
+ version: "v1.2.4-annotated",
+ name: "ede458df7cd0fdca520df19a33158086a8a68e81",
+ short: "ede458df7cd0",
+ time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
+ gomod: "module vcs-test.golang.org/go/mod/gitrepo1\n",
+ zipSum: "h1:YJYZRsM9BHFTlVr8YADjT0cJH8uFIDtoc5NLiVqZEx8=",
+ zipFileHash: "c15e49d58b7a4c37966cbe5bc01a0330cd5f2927e990e1839bda1d407766d9c5",
+ },
+ {
+ vcs: "git",
+ path: "gopkg.in/natefinch/lumberjack.v2",
+ // This repo has a v2.1 tag.
+ // We only allow semver references to tags that are fully qualified, as in v2.1.0.
+ // Because we can't record v2.1.0 (the actual tag is v2.1), we record a pseudo-version
+ // instead, same as if the tag were any other non-version-looking string.
+ // We use a v2 pseudo-version here because of the .v2 in the path, not because
+ // of the v2 in the rev.
+ rev: "v2.1", // non-canonical semantic version turns into pseudo-version
+ version: "v2.0.0-20170531160350-a96e63847dc3",
+ name: "a96e63847dc3c67d17befa69c303767e2f84e54f",
+ short: "a96e63847dc3",
+ time: time.Date(2017, 5, 31, 16, 3, 50, 0, time.UTC),
+ gomod: "module gopkg.in/natefinch/lumberjack.v2\n",
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/go/v2module/v2",
+ rev: "v2.0.0",
+ version: "v2.0.0",
+ name: "203b91c896acd173aa719e4cdcb7d463c4b090fa",
+ short: "203b91c896ac",
+ time: time.Date(2019, 4, 3, 15, 52, 15, 0, time.UTC),
+ gomod: "module vcs-test.golang.org/go/v2module/v2\n\ngo 1.12\n",
+ zipSum: "h1:JItBZ+gwA5WvtZEGEbuDL4lUttGtLrs53lmdurq3bOg=",
+ zipFileHash: "9ea9ae1673cffcc44b7fdd3cc89953d68c102449b46c982dbf085e4f2e394da5",
+ },
+ {
+ // Git branch with a semver name, +incompatible version, and no go.mod file.
+ vcs: "git",
+ path: "vcs-test.golang.org/go/mod/gitrepo1",
+ rev: "v2.3.4+incompatible",
+ err: `resolves to version v2.0.1+incompatible (v2.3.4 is not a tag)`,
+ },
+ {
+ // Git branch with a semver name, matching go.mod file, and compatible version.
+ vcs: "git",
+ path: "vcs-test.golang.org/git/semver-branch.git",
+ rev: "v1.0.0",
+ err: `resolves to version v0.1.1-0.20220202191944-09c4d8f6938c (v1.0.0 is not a tag)`,
+ },
+ {
+ // Git branch with a semver name, matching go.mod file, and disallowed +incompatible version.
+ // The version/tag mismatch takes precedence over the +incompatible mismatched.
+ vcs: "git",
+ path: "vcs-test.golang.org/git/semver-branch.git",
+ rev: "v2.0.0+incompatible",
+ err: `resolves to version v0.1.0 (v2.0.0 is not a tag)`,
+ },
+ {
+ // Git branch with a semver name, matching go.mod file, and mismatched version.
+ // The version/tag mismatch takes precedence over the +incompatible mismatched.
+ vcs: "git",
+ path: "vcs-test.golang.org/git/semver-branch.git",
+ rev: "v2.0.0",
+ err: `resolves to version v0.1.0 (v2.0.0 is not a tag)`,
+ },
+ {
+ // v3.0.0-devel is the same as tag v4.0.0-beta.1, but v4.0.0-beta.1 would
+ // not be allowed because it is incompatible and a go.mod file exists.
+ // The error message should refer to a valid pseudo-version, not the
+ // unusable semver tag.
+ vcs: "git",
+ path: "vcs-test.golang.org/git/semver-branch.git",
+ rev: "v3.0.0-devel",
+ err: `resolves to version v0.1.1-0.20220203155313-d59622f6e4d7 (v3.0.0-devel is not a tag)`,
+ },
+
+ // If v2/go.mod exists, then we should prefer to match the "v2"
+ // pseudo-versions to the nested module, and resolve the module in the parent
+ // directory to only compatible versions.
+ //
+ // However (https://go.dev/issue/51324), previous versions of the 'go' command
+ // didn't always do so, so if the user explicitly requests a +incompatible
+ // version (as would be present in an existing go.mod file), we should
+ // continue to allow it.
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/v2sub.git",
+ rev: "80beb17a1603",
+ version: "v0.0.0-20220222205507-80beb17a1603",
+ name: "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5",
+ short: "80beb17a1603",
+ time: time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC),
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/v2sub.git",
+ rev: "v2.0.0",
+ err: `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`,
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/v2sub.git",
+ rev: "v2.0.1-0.20220222205507-80beb17a1603",
+ err: `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`,
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/v2sub.git",
+ rev: "v2.0.0+incompatible",
+ version: "v2.0.0+incompatible",
+ name: "5fcd3eaeeb391d399f562fd45a50dac9fc34ae8b",
+ short: "5fcd3eaeeb39",
+ time: time.Date(2022, 2, 22, 20, 53, 33, 0, time.UTC),
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/v2sub.git",
+ rev: "v2.0.1-0.20220222205507-80beb17a1603+incompatible",
+ version: "v2.0.1-0.20220222205507-80beb17a1603+incompatible",
+ name: "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5",
+ short: "80beb17a1603",
+ time: time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC),
+ },
+
+ // A version tag with explicit build metadata is valid but not canonical.
+ // It should resolve to a pseudo-version based on the same tag.
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/odd-tags.git",
+ rev: "v0.1.0+build-metadata",
+ version: "v0.1.1-0.20220223184835-9d863d525bbf",
+ name: "9d863d525bbfcc8eda09364738c4032393711a56",
+ short: "9d863d525bbf",
+ time: time.Date(2022, 2, 23, 18, 48, 35, 0, time.UTC),
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/odd-tags.git",
+ rev: "9d863d525bbf",
+ version: "v0.1.1-0.20220223184835-9d863d525bbf",
+ name: "9d863d525bbfcc8eda09364738c4032393711a56",
+ short: "9d863d525bbf",
+ time: time.Date(2022, 2, 23, 18, 48, 35, 0, time.UTC),
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/odd-tags.git",
+ rev: "latest",
+ version: "v0.1.1-0.20220223184835-9d863d525bbf",
+ name: "9d863d525bbfcc8eda09364738c4032393711a56",
+ short: "9d863d525bbf",
+ time: time.Date(2022, 2, 23, 18, 48, 35, 0, time.UTC),
+ },
+
+ // A version tag with an erroneous "+incompatible" suffix should resolve using
+ // only the prefix before the "+incompatible" suffix, not the "+incompatible"
+ // tag itself. (Otherwise, we would potentially have two different commits
+ // both named "v2.0.0+incompatible".) However, the tag is still valid semver
+ // and can still be used as the base for an unambiguous pseudo-version.
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/odd-tags.git",
+ rev: "v2.0.0+incompatible",
+ err: `unknown revision v2.0.0`,
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/odd-tags.git",
+ rev: "12d19af20458",
+ version: "v2.0.1-0.20220223184802-12d19af20458+incompatible",
+ name: "12d19af204585b0db3d2a876ceddf5b9323f5a4a",
+ short: "12d19af20458",
+ time: time.Date(2022, 2, 23, 18, 48, 2, 0, time.UTC),
+ },
+
+ // Similarly, a pseudo-version must resolve to the named commit, even if a tag
+ // matching that pseudo-version is present on a *different* commit.
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/odd-tags.git",
+ rev: "v3.0.0-20220223184802-12d19af20458",
+ version: "v3.0.0-20220223184802-12d19af20458+incompatible",
+ name: "12d19af204585b0db3d2a876ceddf5b9323f5a4a",
+ short: "12d19af20458",
+ time: time.Date(2022, 2, 23, 18, 48, 2, 0, time.UTC),
+ },
+}
+
+func TestCodeRepo(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+ tmpdir := t.TempDir()
+
+ for _, tt := range codeRepoTests {
+ f := func(tt codeRepoTest) func(t *testing.T) {
+ return func(t *testing.T) {
+ if strings.Contains(tt.path, "gopkg.in") {
+ testenv.SkipFlaky(t, 54503)
+ }
+
+ t.Parallel()
+ if tt.vcs != "mod" {
+ testenv.MustHaveExecPath(t, tt.vcs)
+ }
+ ctx := context.Background()
+
+ repo := Lookup(ctx, "direct", tt.path)
+
+ if tt.mpath == "" {
+ tt.mpath = tt.path
+ }
+ if mpath := repo.ModulePath(); mpath != tt.mpath {
+ t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath)
+ }
+
+ info, err := repo.Stat(ctx, tt.rev)
+ if err != nil {
+ if tt.err != "" {
+ if !strings.Contains(err.Error(), tt.err) {
+ t.Fatalf("repoStat(%q): %v, wanted %q", tt.rev, err, tt.err)
+ }
+ return
+ }
+ t.Fatalf("repo.Stat(%q): %v", tt.rev, err)
+ }
+ if tt.err != "" {
+ t.Errorf("repo.Stat(%q): success, wanted error", tt.rev)
+ }
+ if info.Version != tt.version {
+ t.Errorf("info.Version = %q, want %q", info.Version, tt.version)
+ }
+ if info.Name != tt.name {
+ t.Errorf("info.Name = %q, want %q", info.Name, tt.name)
+ }
+ if info.Short != tt.short {
+ t.Errorf("info.Short = %q, want %q", info.Short, tt.short)
+ }
+ if !info.Time.Equal(tt.time) {
+ t.Errorf("info.Time = %v, want %v", info.Time, tt.time)
+ }
+
+ if tt.gomod != "" || tt.gomodErr != "" {
+ data, err := repo.GoMod(ctx, tt.version)
+ if err != nil && tt.gomodErr == "" {
+ t.Errorf("repo.GoMod(%q): %v", tt.version, err)
+ } else if err != nil && tt.gomodErr != "" {
+ if err.Error() != tt.gomodErr {
+ t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomodErr)
+ }
+ } else if tt.gomodErr != "" {
+ t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomodErr)
+ } else if string(data) != tt.gomod {
+ t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod)
+ }
+ }
+
+ needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "")
+ if tt.zip != nil || tt.zipErr != "" || needHash {
+ f, err := os.CreateTemp(tmpdir, tt.version+".zip.")
+ if err != nil {
+ t.Fatalf("os.CreateTemp: %v", err)
+ }
+ zipfile := f.Name()
+ defer func() {
+ f.Close()
+ os.Remove(zipfile)
+ }()
+
+ var w io.Writer
+ var h hash.Hash
+ if needHash {
+ h = sha256.New()
+ w = io.MultiWriter(f, h)
+ } else {
+ w = f
+ }
+ err = repo.Zip(ctx, w, tt.version)
+ f.Close()
+ if err != nil {
+ if tt.zipErr != "" {
+ if err.Error() == tt.zipErr {
+ return
+ }
+ t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.zipErr)
+ }
+ t.Fatalf("repo.Zip(%q): %v", tt.version, err)
+ }
+ if tt.zipErr != "" {
+ t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.zipErr)
+ }
+
+ if tt.zip != nil {
+ prefix := tt.path + "@" + tt.version + "/"
+ z, err := zip.OpenReader(zipfile)
+ if err != nil {
+ t.Fatalf("open zip %s: %v", zipfile, err)
+ }
+ var names []string
+ for _, file := range z.File {
+ if !strings.HasPrefix(file.Name, prefix) {
+ t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix)
+ continue
+ }
+ names = append(names, file.Name[len(prefix):])
+ }
+ z.Close()
+ if !reflect.DeepEqual(names, tt.zip) {
+ t.Fatalf("zip = %v\nwant %v\n", names, tt.zip)
+ }
+ }
+
+ if needHash {
+ sum, err := dirhash.HashZip(zipfile, dirhash.Hash1)
+ if err != nil {
+ t.Errorf("repo.Zip(%q): %v", tt.version, err)
+ } else if sum != tt.zipSum {
+ t.Errorf("repo.Zip(%q): got file with sum %q, want %q", tt.version, sum, tt.zipSum)
+ } else if zipFileHash := hex.EncodeToString(h.Sum(nil)); zipFileHash != tt.zipFileHash {
+ t.Errorf("repo.Zip(%q): got file with hash %q, want %q (but content has correct sum)", tt.version, zipFileHash, tt.zipFileHash)
+ }
+ }
+ }
+ }
+ }
+ t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt))
+ if strings.HasPrefix(tt.path, vgotest1git) {
+ for vcs, alt := range altVgotests {
+ altTest := tt
+ altTest.vcs = vcs
+ altTest.path = alt + strings.TrimPrefix(altTest.path, vgotest1git)
+ if strings.HasPrefix(altTest.mpath, vgotest1git) {
+ altTest.mpath = alt + strings.TrimPrefix(altTest.mpath, vgotest1git)
+ }
+ var m map[string]string
+ if alt == vgotest1hg {
+ m = hgmap
+ }
+ altTest.version = remap(altTest.version, m)
+ altTest.name = remap(altTest.name, m)
+ altTest.short = remap(altTest.short, m)
+ altTest.rev = remap(altTest.rev, m)
+ altTest.err = remap(altTest.err, m)
+ altTest.gomodErr = remap(altTest.gomodErr, m)
+ altTest.zipErr = remap(altTest.zipErr, m)
+ altTest.zipSum = ""
+ altTest.zipFileHash = ""
+ t.Run(strings.ReplaceAll(altTest.path, "/", "_")+"/"+altTest.rev, f(altTest))
+ }
+ }
+ }
+}
+
+var hgmap = map[string]string{
+ "github.com/rsc/vgotest1": "vcs-test.golang.org/hg/vgotest1.hg",
+ "f18795870fb14388a21ef3ebc1d75911c8694f31": "a9ad6d1d14eb544f459f446210c7eb3b009807c6",
+ "ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9": "f1fc0f22021b638d073d31c752847e7bf385def7",
+ "b769f2de407a4db81af9c5de0a06016d60d2ea09": "92c7eb888b4fac17f1c6bd2e1060a1b881a3b832",
+ "8afe2b2efed96e0880ecd2a69b98a53b8c2738b6": "4e58084d459ae7e79c8c2264d0e8e9a92eb5cd44",
+ "2f615117ce481c8efef46e0cc0b4b4dccfac8fea": "879ea98f7743c8eff54f59a918f3a24123d1cf46",
+ "80d85c5d4d17598a0e9055e7c175a32b415d6128": "e125018e286a4b09061079a81e7b537070b7ff71",
+ "1f863feb76bc7029b78b21c5375644838962f88d": "bf63880162304a9337477f3858f5b7e255c75459",
+ "45f53230a74ad275c7127e117ac46914c8126160": "814fce58e83abd5bf2a13892e0b0e1198abefcd4",
+}
+
+func remap(name string, m map[string]string) string {
+ if m[name] != "" {
+ return m[name]
+ }
+ if codehost.AllHex(name) {
+ for k, v := range m {
+ if strings.HasPrefix(k, name) {
+ return v[:len(name)]
+ }
+ }
+ }
+ for k, v := range m {
+ name = strings.ReplaceAll(name, k, v)
+ if codehost.AllHex(k) {
+ name = strings.ReplaceAll(name, k[:12], v[:12])
+ }
+ }
+ return name
+}
+
+var codeRepoVersionsTests = []struct {
+ vcs string
+ path string
+ prefix string
+ versions []string
+}{
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1",
+ versions: []string{"v0.0.0", "v0.0.1", "v1.0.0", "v1.0.1", "v1.0.2", "v1.0.3", "v1.1.0"},
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1",
+ prefix: "v1.0",
+ versions: []string{"v1.0.0", "v1.0.1", "v1.0.2", "v1.0.3"},
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/v2",
+ versions: []string{"v2.0.0", "v2.0.1", "v2.0.2", "v2.0.3", "v2.0.4", "v2.0.5", "v2.0.6"},
+ },
+ {
+ vcs: "mod",
+ path: "swtch.com/testmod",
+ versions: []string{"v1.0.0", "v1.1.1"},
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/odd-tags.git",
+ versions: nil,
+ },
+}
+
+func TestCodeRepoVersions(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ for _, tt := range codeRepoVersionsTests {
+ tt := tt
+ t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) {
+ if strings.Contains(tt.path, "gopkg.in") {
+ testenv.SkipFlaky(t, 54503)
+ }
+
+ t.Parallel()
+ if tt.vcs != "mod" {
+ testenv.MustHaveExecPath(t, tt.vcs)
+ }
+ ctx := context.Background()
+
+ repo := Lookup(ctx, "direct", tt.path)
+ list, err := repo.Versions(ctx, tt.prefix)
+ if err != nil {
+ t.Fatalf("Versions(%q): %v", tt.prefix, err)
+ }
+ if !reflect.DeepEqual(list.List, tt.versions) {
+ t.Fatalf("Versions(%q):\nhave %v\nwant %v", tt.prefix, list, tt.versions)
+ }
+ })
+ }
+}
+
+var latestTests = []struct {
+ vcs string
+ path string
+ version string
+ err string
+}{
+ {
+ vcs: "git",
+ path: "github.com/rsc/empty",
+ err: "no commits",
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1",
+ err: `github.com/rsc/vgotest1@v0.0.0-20180219223237-a08abb797a67: invalid version: go.mod has post-v0 module path "github.com/vgotest1/v2" at revision a08abb797a67`,
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/v2",
+ err: `github.com/rsc/vgotest1/v2@v2.0.0-20180219223237-a08abb797a67: invalid version: github.com/rsc/vgotest1/go.mod and .../v2/go.mod both have .../v2 module paths at revision a08abb797a67`,
+ },
+ {
+ vcs: "git",
+ path: "github.com/rsc/vgotest1/subdir",
+ err: "github.com/rsc/vgotest1/subdir@v0.0.0-20180219223237-a08abb797a67: invalid version: missing github.com/rsc/vgotest1/subdir/go.mod at revision a08abb797a67",
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/commit-after-tag.git",
+ version: "v1.0.1-0.20190715211727-b325d8217783",
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/no-tags.git",
+ version: "v0.0.0-20190715212047-e706ba1d9f6d",
+ },
+ {
+ vcs: "mod",
+ path: "swtch.com/testmod",
+ version: "v1.1.1",
+ },
+}
+
+func TestLatest(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ for _, tt := range latestTests {
+ name := strings.ReplaceAll(tt.path, "/", "_")
+ t.Run(name, func(t *testing.T) {
+ tt := tt
+ t.Parallel()
+ if tt.vcs != "mod" {
+ testenv.MustHaveExecPath(t, tt.vcs)
+ }
+ ctx := context.Background()
+
+ repo := Lookup(ctx, "direct", tt.path)
+ info, err := repo.Latest(ctx)
+ if err != nil {
+ if tt.err != "" {
+ if err.Error() == tt.err {
+ return
+ }
+ t.Fatalf("Latest(): %v, want %q", err, tt.err)
+ }
+ t.Fatalf("Latest(): %v", err)
+ }
+ if tt.err != "" {
+ t.Fatalf("Latest() = %v, want error %q", info.Version, tt.err)
+ }
+ if info.Version != tt.version {
+ t.Fatalf("Latest() = %v, want %v", info.Version, tt.version)
+ }
+ })
+ }
+}
+
+// fixedTagsRepo is a fake codehost.Repo that returns a fixed list of tags
+type fixedTagsRepo struct {
+ tags []string
+ codehost.Repo
+}
+
+func (ch *fixedTagsRepo) Tags(ctx context.Context, prefix string) (*codehost.Tags, error) {
+ tags := &codehost.Tags{}
+ for _, t := range ch.tags {
+ tags.List = append(tags.List, codehost.Tag{Name: t})
+ }
+ return tags, nil
+}
+
+func TestNonCanonicalSemver(t *testing.T) {
+ t.Parallel()
+ ctx := context.Background()
+
+ root := "golang.org/x/issue24476"
+ ch := &fixedTagsRepo{
+ tags: []string{
+ "", "huh?", "1.0.1",
+ // what about "version 1 dot dogcow"?
+ "v1.🐕.🐄",
+ "v1", "v0.1",
+ // and one normal one that should pass through
+ "v1.0.1",
+ },
+ }
+
+ cr, err := newCodeRepo(ch, root, root)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ v, err := cr.Versions(ctx, "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(v.List) != 1 || v.List[0] != "v1.0.1" {
+ t.Fatal("unexpected versions returned:", v)
+ }
+}
diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go
new file mode 100644
index 0000000..eeab6da
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/fetch.go
@@ -0,0 +1,1002 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modfetch
+
+import (
+ "archive/zip"
+ "bytes"
+ "context"
+ "crypto/sha256"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io"
+ "io/fs"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+ "sync"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/fsys"
+ "cmd/go/internal/gover"
+ "cmd/go/internal/lockedfile"
+ "cmd/go/internal/par"
+ "cmd/go/internal/robustio"
+ "cmd/go/internal/str"
+ "cmd/go/internal/trace"
+
+ "golang.org/x/mod/module"
+ "golang.org/x/mod/sumdb/dirhash"
+ modzip "golang.org/x/mod/zip"
+)
+
+var downloadCache par.ErrCache[module.Version, string] // version → directory
+
+var ErrToolchain = errors.New("internal error: invalid operation on toolchain module")
+
+// Download downloads the specific module version to the
+// local download cache and returns the name of the directory
+// corresponding to the root of the module's file tree.
+func Download(ctx context.Context, mod module.Version) (dir string, err error) {
+ if gover.IsToolchain(mod.Path) {
+ return "", ErrToolchain
+ }
+ if err := checkCacheDir(ctx); err != nil {
+ base.Fatal(err)
+ }
+
+ // The par.Cache here avoids duplicate work.
+ return downloadCache.Do(mod, func() (string, error) {
+ dir, err := download(ctx, mod)
+ if err != nil {
+ return "", err
+ }
+ checkMod(ctx, mod)
+
+ // If go.mod exists (not an old legacy module), check version is not too new.
+ if data, err := os.ReadFile(filepath.Join(dir, "go.mod")); err == nil {
+ goVersion := gover.GoModLookup(data, "go")
+ if gover.Compare(goVersion, gover.Local()) > 0 {
+ return "", &gover.TooNewError{What: mod.String(), GoVersion: goVersion}
+ }
+ } else if !errors.Is(err, fs.ErrNotExist) {
+ return "", err
+ }
+
+ return dir, nil
+ })
+}
+
+func download(ctx context.Context, mod module.Version) (dir string, err error) {
+ ctx, span := trace.StartSpan(ctx, "modfetch.download "+mod.String())
+ defer span.Done()
+
+ dir, err = DownloadDir(ctx, mod)
+ if err == nil {
+ // The directory has already been completely extracted (no .partial file exists).
+ return dir, nil
+ } else if dir == "" || !errors.Is(err, fs.ErrNotExist) {
+ return "", err
+ }
+
+ // To avoid cluttering the cache with extraneous files,
+ // DownloadZip uses the same lockfile as Download.
+ // Invoke DownloadZip before locking the file.
+ zipfile, err := DownloadZip(ctx, mod)
+ if err != nil {
+ return "", err
+ }
+
+ unlock, err := lockVersion(ctx, mod)
+ if err != nil {
+ return "", err
+ }
+ defer unlock()
+
+ ctx, span = trace.StartSpan(ctx, "unzip "+zipfile)
+ defer span.Done()
+
+ // Check whether the directory was populated while we were waiting on the lock.
+ _, dirErr := DownloadDir(ctx, mod)
+ if dirErr == nil {
+ return dir, nil
+ }
+ _, dirExists := dirErr.(*DownloadDirPartialError)
+
+ // Clean up any remaining temporary directories created by old versions
+ // (before 1.16), as well as partially extracted directories (indicated by
+ // DownloadDirPartialError, usually because of a .partial file). This is only
+ // safe to do because the lock file ensures that their writers are no longer
+ // active.
+ parentDir := filepath.Dir(dir)
+ tmpPrefix := filepath.Base(dir) + ".tmp-"
+ if old, err := filepath.Glob(filepath.Join(str.QuoteGlob(parentDir), str.QuoteGlob(tmpPrefix)+"*")); err == nil {
+ for _, path := range old {
+ RemoveAll(path) // best effort
+ }
+ }
+ if dirExists {
+ if err := RemoveAll(dir); err != nil {
+ return "", err
+ }
+ }
+
+ partialPath, err := CachePath(ctx, mod, "partial")
+ if err != nil {
+ return "", err
+ }
+
+ // Extract the module zip directory at its final location.
+ //
+ // To prevent other processes from reading the directory if we crash,
+ // create a .partial file before extracting the directory, and delete
+ // the .partial file afterward (all while holding the lock).
+ //
+ // Before Go 1.16, we extracted to a temporary directory with a random name
+ // then renamed it into place with os.Rename. On Windows, this failed with
+ // ERROR_ACCESS_DENIED when another process (usually an anti-virus scanner)
+ // opened files in the temporary directory.
+ //
+ // Go 1.14.2 and higher respect .partial files. Older versions may use
+ // partially extracted directories. 'go mod verify' can detect this,
+ // and 'go clean -modcache' can fix it.
+ if err := os.MkdirAll(parentDir, 0777); err != nil {
+ return "", err
+ }
+ if err := os.WriteFile(partialPath, nil, 0666); err != nil {
+ return "", err
+ }
+ if err := modzip.Unzip(dir, mod, zipfile); err != nil {
+ fmt.Fprintf(os.Stderr, "-> %s\n", err)
+ if rmErr := RemoveAll(dir); rmErr == nil {
+ os.Remove(partialPath)
+ }
+ return "", err
+ }
+ if err := os.Remove(partialPath); err != nil {
+ return "", err
+ }
+
+ if !cfg.ModCacheRW {
+ makeDirsReadOnly(dir)
+ }
+ return dir, nil
+}
+
+var downloadZipCache par.ErrCache[module.Version, string]
+
+// DownloadZip downloads the specific module version to the
+// local zip cache and returns the name of the zip file.
+func DownloadZip(ctx context.Context, mod module.Version) (zipfile string, err error) {
+ // The par.Cache here avoids duplicate work.
+ return downloadZipCache.Do(mod, func() (string, error) {
+ zipfile, err := CachePath(ctx, mod, "zip")
+ if err != nil {
+ return "", err
+ }
+ ziphashfile := zipfile + "hash"
+
+ // Return without locking if the zip and ziphash files exist.
+ if _, err := os.Stat(zipfile); err == nil {
+ if _, err := os.Stat(ziphashfile); err == nil {
+ return zipfile, nil
+ }
+ }
+
+ // The zip or ziphash file does not exist. Acquire the lock and create them.
+ if cfg.CmdName != "mod download" {
+ vers := mod.Version
+ if mod.Path == "golang.org/toolchain" {
+ // Shorten v0.0.1-go1.13.1.darwin-amd64 to go1.13.1.darwin-amd64
+ _, vers, _ = strings.Cut(vers, "-")
+ if i := strings.LastIndex(vers, "."); i >= 0 {
+ goos, goarch, _ := strings.Cut(vers[i+1:], "-")
+ vers = vers[:i] + " (" + goos + "/" + goarch + ")"
+ }
+ fmt.Fprintf(os.Stderr, "go: downloading %s\n", vers)
+ } else {
+ fmt.Fprintf(os.Stderr, "go: downloading %s %s\n", mod.Path, vers)
+ }
+ }
+ unlock, err := lockVersion(ctx, mod)
+ if err != nil {
+ return "", err
+ }
+ defer unlock()
+
+ if err := downloadZip(ctx, mod, zipfile); err != nil {
+ return "", err
+ }
+ return zipfile, nil
+ })
+}
+
+func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err error) {
+ ctx, span := trace.StartSpan(ctx, "modfetch.downloadZip "+zipfile)
+ defer span.Done()
+
+ // Double-check that the zipfile was not created while we were waiting for
+ // the lock in DownloadZip.
+ ziphashfile := zipfile + "hash"
+ var zipExists, ziphashExists bool
+ if _, err := os.Stat(zipfile); err == nil {
+ zipExists = true
+ }
+ if _, err := os.Stat(ziphashfile); err == nil {
+ ziphashExists = true
+ }
+ if zipExists && ziphashExists {
+ return nil
+ }
+
+ // Create parent directories.
+ if err := os.MkdirAll(filepath.Dir(zipfile), 0777); err != nil {
+ return err
+ }
+
+ // Clean up any remaining tempfiles from previous runs.
+ // This is only safe to do because the lock file ensures that their
+ // writers are no longer active.
+ tmpPattern := filepath.Base(zipfile) + "*.tmp"
+ if old, err := filepath.Glob(filepath.Join(str.QuoteGlob(filepath.Dir(zipfile)), tmpPattern)); err == nil {
+ for _, path := range old {
+ os.Remove(path) // best effort
+ }
+ }
+
+ // If the zip file exists, the ziphash file must have been deleted
+ // or lost after a file system crash. Re-hash the zip without downloading.
+ if zipExists {
+ return hashZip(mod, zipfile, ziphashfile)
+ }
+
+ // From here to the os.Rename call below is functionally almost equivalent to
+ // renameio.WriteToFile, with one key difference: we want to validate the
+ // contents of the file (by hashing it) before we commit it. Because the file
+ // is zip-compressed, we need an actual file — or at least an io.ReaderAt — to
+ // validate it: we can't just tee the stream as we write it.
+ f, err := tempFile(ctx, filepath.Dir(zipfile), filepath.Base(zipfile), 0666)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ f.Close()
+ os.Remove(f.Name())
+ }
+ }()
+
+ var unrecoverableErr error
+ err = TryProxies(func(proxy string) error {
+ if unrecoverableErr != nil {
+ return unrecoverableErr
+ }
+ repo := Lookup(ctx, proxy, mod.Path)
+ err := repo.Zip(ctx, f, mod.Version)
+ if err != nil {
+ // Zip may have partially written to f before failing.
+ // (Perhaps the server crashed while sending the file?)
+ // Since we allow fallback on error in some cases, we need to fix up the
+ // file to be empty again for the next attempt.
+ if _, err := f.Seek(0, io.SeekStart); err != nil {
+ unrecoverableErr = err
+ return err
+ }
+ if err := f.Truncate(0); err != nil {
+ unrecoverableErr = err
+ return err
+ }
+ }
+ return err
+ })
+ if err != nil {
+ return err
+ }
+
+ // Double-check that the paths within the zip file are well-formed.
+ //
+ // TODO(bcmills): There is a similar check within the Unzip function. Can we eliminate one?
+ fi, err := f.Stat()
+ if err != nil {
+ return err
+ }
+ z, err := zip.NewReader(f, fi.Size())
+ if err != nil {
+ return err
+ }
+ prefix := mod.Path + "@" + mod.Version + "/"
+ for _, f := range z.File {
+ if !strings.HasPrefix(f.Name, prefix) {
+ return fmt.Errorf("zip for %s has unexpected file %s", prefix[:len(prefix)-1], f.Name)
+ }
+ }
+
+ if err := f.Close(); err != nil {
+ return err
+ }
+
+ // Hash the zip file and check the sum before renaming to the final location.
+ if err := hashZip(mod, f.Name(), ziphashfile); err != nil {
+ return err
+ }
+ if err := os.Rename(f.Name(), zipfile); err != nil {
+ return err
+ }
+
+ // TODO(bcmills): Should we make the .zip and .ziphash files read-only to discourage tampering?
+
+ return nil
+}
+
+// hashZip reads the zip file opened in f, then writes the hash to ziphashfile,
+// overwriting that file if it exists.
+//
+// If the hash does not match go.sum (or the sumdb if enabled), hashZip returns
+// an error and does not write ziphashfile.
+func hashZip(mod module.Version, zipfile, ziphashfile string) (err error) {
+ hash, err := dirhash.HashZip(zipfile, dirhash.DefaultHash)
+ if err != nil {
+ return err
+ }
+ if err := checkModSum(mod, hash); err != nil {
+ return err
+ }
+ hf, err := lockedfile.Create(ziphashfile)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if closeErr := hf.Close(); err == nil && closeErr != nil {
+ err = closeErr
+ }
+ }()
+ if err := hf.Truncate(int64(len(hash))); err != nil {
+ return err
+ }
+ if _, err := hf.WriteAt([]byte(hash), 0); err != nil {
+ return err
+ }
+ return nil
+}
+
+// makeDirsReadOnly makes a best-effort attempt to remove write permissions for dir
+// and its transitive contents.
+func makeDirsReadOnly(dir string) {
+ type pathMode struct {
+ path string
+ mode fs.FileMode
+ }
+ var dirs []pathMode // in lexical order
+ filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
+ if err == nil && d.IsDir() {
+ info, err := d.Info()
+ if err == nil && info.Mode()&0222 != 0 {
+ dirs = append(dirs, pathMode{path, info.Mode()})
+ }
+ }
+ return nil
+ })
+
+ // Run over list backward to chmod children before parents.
+ for i := len(dirs) - 1; i >= 0; i-- {
+ os.Chmod(dirs[i].path, dirs[i].mode&^0222)
+ }
+}
+
+// RemoveAll removes a directory written by Download or Unzip, first applying
+// any permission changes needed to do so.
+func RemoveAll(dir string) error {
+ // Module cache has 0555 directories; make them writable in order to remove content.
+ filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
+ if err != nil {
+ return nil // ignore errors walking in file system
+ }
+ if info.IsDir() {
+ os.Chmod(path, 0777)
+ }
+ return nil
+ })
+ return robustio.RemoveAll(dir)
+}
+
+var GoSumFile string // path to go.sum; set by package modload
+var WorkspaceGoSumFiles []string // path to module go.sums in workspace; set by package modload
+
+type modSum struct {
+ mod module.Version
+ sum string
+}
+
+var goSum struct {
+ mu sync.Mutex
+ m map[module.Version][]string // content of go.sum file
+ w map[string]map[module.Version][]string // sum file in workspace -> content of that sum file
+ status map[modSum]modSumStatus // state of sums in m
+ overwrite bool // if true, overwrite go.sum without incorporating its contents
+ enabled bool // whether to use go.sum at all
+}
+
+type modSumStatus struct {
+ used, dirty bool
+}
+
+// Reset resets globals in the modfetch package, so previous loads don't affect
+// contents of go.sum files.
+func Reset() {
+ GoSumFile = ""
+ WorkspaceGoSumFiles = nil
+
+ // Uses of lookupCache and downloadCache both can call checkModSum,
+ // which in turn sets the used bit on goSum.status for modules.
+ // Reset them so used can be computed properly.
+ lookupCache = par.Cache[lookupCacheKey, Repo]{}
+ downloadCache = par.ErrCache[module.Version, string]{}
+
+ // Clear all fields on goSum. It will be initialized later
+ goSum.mu.Lock()
+ goSum.m = nil
+ goSum.w = nil
+ goSum.status = nil
+ goSum.overwrite = false
+ goSum.enabled = false
+ goSum.mu.Unlock()
+}
+
+// initGoSum initializes the go.sum data.
+// The boolean it returns reports whether the
+// use of go.sum is now enabled.
+// The goSum lock must be held.
+func initGoSum() (bool, error) {
+ if GoSumFile == "" {
+ return false, nil
+ }
+ if goSum.m != nil {
+ return true, nil
+ }
+
+ goSum.m = make(map[module.Version][]string)
+ goSum.status = make(map[modSum]modSumStatus)
+ goSum.w = make(map[string]map[module.Version][]string)
+
+ for _, f := range WorkspaceGoSumFiles {
+ goSum.w[f] = make(map[module.Version][]string)
+ _, err := readGoSumFile(goSum.w[f], f)
+ if err != nil {
+ return false, err
+ }
+ }
+
+ enabled, err := readGoSumFile(goSum.m, GoSumFile)
+ goSum.enabled = enabled
+ return enabled, err
+}
+
+func readGoSumFile(dst map[module.Version][]string, file string) (bool, error) {
+ var (
+ data []byte
+ err error
+ )
+ if actualSumFile, ok := fsys.OverlayPath(file); ok {
+ // Don't lock go.sum if it's part of the overlay.
+ // On Plan 9, locking requires chmod, and we don't want to modify any file
+ // in the overlay. See #44700.
+ data, err = os.ReadFile(actualSumFile)
+ } else {
+ data, err = lockedfile.Read(file)
+ }
+ if err != nil && !os.IsNotExist(err) {
+ return false, err
+ }
+ readGoSum(dst, file, data)
+
+ return true, nil
+}
+
+// emptyGoModHash is the hash of a 1-file tree containing a 0-length go.mod.
+// A bug caused us to write these into go.sum files for non-modules.
+// We detect and remove them.
+const emptyGoModHash = "h1:G7mAYYxgmS0lVkHyy2hEOLQCFB0DlQFTMLWggykrydY="
+
+// readGoSum parses data, which is the content of file,
+// and adds it to goSum.m. The goSum lock must be held.
+func readGoSum(dst map[module.Version][]string, file string, data []byte) {
+ lineno := 0
+ for len(data) > 0 {
+ var line []byte
+ lineno++
+ i := bytes.IndexByte(data, '\n')
+ if i < 0 {
+ line, data = data, nil
+ } else {
+ line, data = data[:i], data[i+1:]
+ }
+ f := strings.Fields(string(line))
+ if len(f) == 0 {
+ // blank line; skip it
+ continue
+ }
+ if len(f) != 3 {
+ if cfg.CmdName == "mod tidy" {
+ // ignore malformed line so that go mod tidy can fix go.sum
+ continue
+ } else {
+ base.Fatalf("malformed go.sum:\n%s:%d: wrong number of fields %v\n", file, lineno, len(f))
+ }
+ }
+ if f[2] == emptyGoModHash {
+ // Old bug; drop it.
+ continue
+ }
+ mod := module.Version{Path: f[0], Version: f[1]}
+ dst[mod] = append(dst[mod], f[2])
+ }
+}
+
+// HaveSum returns true if the go.sum file contains an entry for mod.
+// The entry's hash must be generated with a known hash algorithm.
+// mod.Version may have a "/go.mod" suffix to distinguish sums for
+// .mod and .zip files.
+func HaveSum(mod module.Version) bool {
+ goSum.mu.Lock()
+ defer goSum.mu.Unlock()
+ inited, err := initGoSum()
+ if err != nil || !inited {
+ return false
+ }
+ for _, goSums := range goSum.w {
+ for _, h := range goSums[mod] {
+ if !strings.HasPrefix(h, "h1:") {
+ continue
+ }
+ if !goSum.status[modSum{mod, h}].dirty {
+ return true
+ }
+ }
+ }
+ for _, h := range goSum.m[mod] {
+ if !strings.HasPrefix(h, "h1:") {
+ continue
+ }
+ if !goSum.status[modSum{mod, h}].dirty {
+ return true
+ }
+ }
+ return false
+}
+
+// checkMod checks the given module's checksum and Go version.
+func checkMod(ctx context.Context, mod module.Version) {
+ // Do the file I/O before acquiring the go.sum lock.
+ ziphash, err := CachePath(ctx, mod, "ziphash")
+ if err != nil {
+ base.Fatalf("verifying %v", module.VersionError(mod, err))
+ }
+ data, err := lockedfile.Read(ziphash)
+ if err != nil {
+ base.Fatalf("verifying %v", module.VersionError(mod, err))
+ }
+ data = bytes.TrimSpace(data)
+ if !isValidSum(data) {
+ // Recreate ziphash file from zip file and use that to check the mod sum.
+ zip, err := CachePath(ctx, mod, "zip")
+ if err != nil {
+ base.Fatalf("verifying %v", module.VersionError(mod, err))
+ }
+ err = hashZip(mod, zip, ziphash)
+ if err != nil {
+ base.Fatalf("verifying %v", module.VersionError(mod, err))
+ }
+ return
+ }
+ h := string(data)
+ if !strings.HasPrefix(h, "h1:") {
+ base.Fatalf("verifying %v", module.VersionError(mod, fmt.Errorf("unexpected ziphash: %q", h)))
+ }
+
+ if err := checkModSum(mod, h); err != nil {
+ base.Fatalf("%s", err)
+ }
+}
+
+// goModSum returns the checksum for the go.mod contents.
+func goModSum(data []byte) (string, error) {
+ return dirhash.Hash1([]string{"go.mod"}, func(string) (io.ReadCloser, error) {
+ return io.NopCloser(bytes.NewReader(data)), nil
+ })
+}
+
+// checkGoMod checks the given module's go.mod checksum;
+// data is the go.mod content.
+func checkGoMod(path, version string, data []byte) error {
+ h, err := goModSum(data)
+ if err != nil {
+ return &module.ModuleError{Path: path, Version: version, Err: fmt.Errorf("verifying go.mod: %v", err)}
+ }
+
+ return checkModSum(module.Version{Path: path, Version: version + "/go.mod"}, h)
+}
+
+// checkModSum checks that the recorded checksum for mod is h.
+//
+// mod.Version may have the additional suffix "/go.mod" to request the checksum
+// for the module's go.mod file only.
+func checkModSum(mod module.Version, h string) error {
+ // We lock goSum when manipulating it,
+ // but we arrange to release the lock when calling checkSumDB,
+ // so that parallel calls to checkModHash can execute parallel calls
+ // to checkSumDB.
+
+ // Check whether mod+h is listed in go.sum already. If so, we're done.
+ goSum.mu.Lock()
+ inited, err := initGoSum()
+ if err != nil {
+ goSum.mu.Unlock()
+ return err
+ }
+ done := inited && haveModSumLocked(mod, h)
+ if inited {
+ st := goSum.status[modSum{mod, h}]
+ st.used = true
+ goSum.status[modSum{mod, h}] = st
+ }
+ goSum.mu.Unlock()
+
+ if done {
+ return nil
+ }
+
+ // Not listed, so we want to add them.
+ // Consult checksum database if appropriate.
+ if useSumDB(mod) {
+ // Calls base.Fatalf if mismatch detected.
+ if err := checkSumDB(mod, h); err != nil {
+ return err
+ }
+ }
+
+ // Add mod+h to go.sum, if it hasn't appeared already.
+ if inited {
+ goSum.mu.Lock()
+ addModSumLocked(mod, h)
+ st := goSum.status[modSum{mod, h}]
+ st.dirty = true
+ goSum.status[modSum{mod, h}] = st
+ goSum.mu.Unlock()
+ }
+ return nil
+}
+
+// haveModSumLocked reports whether the pair mod,h is already listed in go.sum.
+// If it finds a conflicting pair instead, it calls base.Fatalf.
+// goSum.mu must be locked.
+func haveModSumLocked(mod module.Version, h string) bool {
+ sumFileName := "go.sum"
+ if strings.HasSuffix(GoSumFile, "go.work.sum") {
+ sumFileName = "go.work.sum"
+ }
+ for _, vh := range goSum.m[mod] {
+ if h == vh {
+ return true
+ }
+ if strings.HasPrefix(vh, "h1:") {
+ base.Fatalf("verifying %s@%s: checksum mismatch\n\tdownloaded: %v\n\t%s: %v"+goSumMismatch, mod.Path, mod.Version, h, sumFileName, vh)
+ }
+ }
+ // Also check workspace sums.
+ foundMatch := false
+ // Check sums from all files in case there are conflicts between
+ // the files.
+ for goSumFile, goSums := range goSum.w {
+ for _, vh := range goSums[mod] {
+ if h == vh {
+ foundMatch = true
+ } else if strings.HasPrefix(vh, "h1:") {
+ base.Fatalf("verifying %s@%s: checksum mismatch\n\tdownloaded: %v\n\t%s: %v"+goSumMismatch, mod.Path, mod.Version, h, goSumFile, vh)
+ }
+ }
+ }
+ return foundMatch
+}
+
+// addModSumLocked adds the pair mod,h to go.sum.
+// goSum.mu must be locked.
+func addModSumLocked(mod module.Version, h string) {
+ if haveModSumLocked(mod, h) {
+ return
+ }
+ if len(goSum.m[mod]) > 0 {
+ fmt.Fprintf(os.Stderr, "warning: verifying %s@%s: unknown hashes in go.sum: %v; adding %v"+hashVersionMismatch, mod.Path, mod.Version, strings.Join(goSum.m[mod], ", "), h)
+ }
+ goSum.m[mod] = append(goSum.m[mod], h)
+}
+
+// checkSumDB checks the mod, h pair against the Go checksum database.
+// It calls base.Fatalf if the hash is to be rejected.
+func checkSumDB(mod module.Version, h string) error {
+ modWithoutSuffix := mod
+ noun := "module"
+ if before, found := strings.CutSuffix(mod.Version, "/go.mod"); found {
+ noun = "go.mod"
+ modWithoutSuffix.Version = before
+ }
+
+ db, lines, err := lookupSumDB(mod)
+ if err != nil {
+ return module.VersionError(modWithoutSuffix, fmt.Errorf("verifying %s: %v", noun, err))
+ }
+
+ have := mod.Path + " " + mod.Version + " " + h
+ prefix := mod.Path + " " + mod.Version + " h1:"
+ for _, line := range lines {
+ if line == have {
+ return nil
+ }
+ if strings.HasPrefix(line, prefix) {
+ return module.VersionError(modWithoutSuffix, fmt.Errorf("verifying %s: checksum mismatch\n\tdownloaded: %v\n\t%s: %v"+sumdbMismatch, noun, h, db, line[len(prefix)-len("h1:"):]))
+ }
+ }
+ return nil
+}
+
+// Sum returns the checksum for the downloaded copy of the given module,
+// if present in the download cache.
+func Sum(ctx context.Context, mod module.Version) string {
+ if cfg.GOMODCACHE == "" {
+ // Do not use current directory.
+ return ""
+ }
+
+ ziphash, err := CachePath(ctx, mod, "ziphash")
+ if err != nil {
+ return ""
+ }
+ data, err := lockedfile.Read(ziphash)
+ if err != nil {
+ return ""
+ }
+ data = bytes.TrimSpace(data)
+ if !isValidSum(data) {
+ return ""
+ }
+ return string(data)
+}
+
+// isValidSum returns true if data is the valid contents of a zip hash file.
+// Certain critical files are written to disk by first truncating
+// then writing the actual bytes, so that if the write fails
+// the corrupt file should contain at least one of the null
+// bytes written by the truncate operation.
+func isValidSum(data []byte) bool {
+ if bytes.IndexByte(data, '\000') >= 0 {
+ return false
+ }
+
+ if len(data) != len("h1:")+base64.StdEncoding.EncodedLen(sha256.Size) {
+ return false
+ }
+
+ return true
+}
+
+var ErrGoSumDirty = errors.New("updates to go.sum needed, disabled by -mod=readonly")
+
+// WriteGoSum writes the go.sum file if it needs to be updated.
+//
+// keep is used to check whether a newly added sum should be saved in go.sum.
+// It should have entries for both module content sums and go.mod sums
+// (version ends with "/go.mod"). Existing sums will be preserved unless they
+// have been marked for deletion with TrimGoSum.
+func WriteGoSum(ctx context.Context, keep map[module.Version]bool, readonly bool) error {
+ goSum.mu.Lock()
+ defer goSum.mu.Unlock()
+
+ // If we haven't read the go.sum file yet, don't bother writing it.
+ if !goSum.enabled {
+ return nil
+ }
+
+ // Check whether we need to add sums for which keep[m] is true or remove
+ // unused sums marked with TrimGoSum. If there are no changes to make,
+ // just return without opening go.sum.
+ dirty := false
+Outer:
+ for m, hs := range goSum.m {
+ for _, h := range hs {
+ st := goSum.status[modSum{m, h}]
+ if st.dirty && (!st.used || keep[m]) {
+ dirty = true
+ break Outer
+ }
+ }
+ }
+ if !dirty {
+ return nil
+ }
+ if readonly {
+ return ErrGoSumDirty
+ }
+ if _, ok := fsys.OverlayPath(GoSumFile); ok {
+ base.Fatalf("go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay")
+ }
+
+ // Make a best-effort attempt to acquire the side lock, only to exclude
+ // previous versions of the 'go' command from making simultaneous edits.
+ if unlock, err := SideLock(ctx); err == nil {
+ defer unlock()
+ }
+
+ err := lockedfile.Transform(GoSumFile, func(data []byte) ([]byte, error) {
+ if !goSum.overwrite {
+ // Incorporate any sums added by other processes in the meantime.
+ // Add only the sums that we actually checked: the user may have edited or
+ // truncated the file to remove erroneous hashes, and we shouldn't restore
+ // them without good reason.
+ goSum.m = make(map[module.Version][]string, len(goSum.m))
+ readGoSum(goSum.m, GoSumFile, data)
+ for ms, st := range goSum.status {
+ if st.used && !sumInWorkspaceModulesLocked(ms.mod) {
+ addModSumLocked(ms.mod, ms.sum)
+ }
+ }
+ }
+
+ var mods []module.Version
+ for m := range goSum.m {
+ mods = append(mods, m)
+ }
+ module.Sort(mods)
+
+ var buf bytes.Buffer
+ for _, m := range mods {
+ list := goSum.m[m]
+ sort.Strings(list)
+ str.Uniq(&list)
+ for _, h := range list {
+ st := goSum.status[modSum{m, h}]
+ if (!st.dirty || (st.used && keep[m])) && !sumInWorkspaceModulesLocked(m) {
+ fmt.Fprintf(&buf, "%s %s %s\n", m.Path, m.Version, h)
+ }
+ }
+ }
+ return buf.Bytes(), nil
+ })
+
+ if err != nil {
+ return fmt.Errorf("updating go.sum: %w", err)
+ }
+
+ goSum.status = make(map[modSum]modSumStatus)
+ goSum.overwrite = false
+ return nil
+}
+
+func sumInWorkspaceModulesLocked(m module.Version) bool {
+ for _, goSums := range goSum.w {
+ if _, ok := goSums[m]; ok {
+ return true
+ }
+ }
+ return false
+}
+
+// TrimGoSum trims go.sum to contain only the modules needed for reproducible
+// builds.
+//
+// keep is used to check whether a sum should be retained in go.mod. It should
+// have entries for both module content sums and go.mod sums (version ends
+// with "/go.mod").
+func TrimGoSum(keep map[module.Version]bool) {
+ goSum.mu.Lock()
+ defer goSum.mu.Unlock()
+ inited, err := initGoSum()
+ if err != nil {
+ base.Fatalf("%s", err)
+ }
+ if !inited {
+ return
+ }
+
+ for m, hs := range goSum.m {
+ if !keep[m] {
+ for _, h := range hs {
+ goSum.status[modSum{m, h}] = modSumStatus{used: false, dirty: true}
+ }
+ goSum.overwrite = true
+ }
+ }
+}
+
+const goSumMismatch = `
+
+SECURITY ERROR
+This download does NOT match an earlier download recorded in go.sum.
+The bits may have been replaced on the origin server, or an attacker may
+have intercepted the download attempt.
+
+For more information, see 'go help module-auth'.
+`
+
+const sumdbMismatch = `
+
+SECURITY ERROR
+This download does NOT match the one reported by the checksum server.
+The bits may have been replaced on the origin server, or an attacker may
+have intercepted the download attempt.
+
+For more information, see 'go help module-auth'.
+`
+
+const hashVersionMismatch = `
+
+SECURITY WARNING
+This download is listed in go.sum, but using an unknown hash algorithm.
+The download cannot be verified.
+
+For more information, see 'go help module-auth'.
+
+`
+
+var HelpModuleAuth = &base.Command{
+ UsageLine: "module-auth",
+ Short: "module authentication using go.sum",
+ Long: `
+When the go command downloads a module zip file or go.mod file into the
+module cache, it computes a cryptographic hash and compares it with a known
+value to verify the file hasn't changed since it was first downloaded. Known
+hashes are stored in a file in the module root directory named go.sum. Hashes
+may also be downloaded from the checksum database depending on the values of
+GOSUMDB, GOPRIVATE, and GONOSUMDB.
+
+For details, see https://golang.org/ref/mod#authenticating.
+`,
+}
+
+var HelpPrivate = &base.Command{
+ UsageLine: "private",
+ Short: "configuration for downloading non-public code",
+ Long: `
+The go command defaults to downloading modules from the public Go module
+mirror at proxy.golang.org. It also defaults to validating downloaded modules,
+regardless of source, against the public Go checksum database at sum.golang.org.
+These defaults work well for publicly available source code.
+
+The GOPRIVATE environment variable controls which modules the go command
+considers to be private (not available publicly) and should therefore not use
+the proxy or checksum database. The variable is a comma-separated list of
+glob patterns (in the syntax of Go's path.Match) of module path prefixes.
+For example,
+
+ GOPRIVATE=*.corp.example.com,rsc.io/private
+
+causes the go command to treat as private any module with a path prefix
+matching either pattern, including git.corp.example.com/xyzzy, rsc.io/private,
+and rsc.io/private/quux.
+
+For fine-grained control over module download and validation, the GONOPROXY
+and GONOSUMDB environment variables accept the same kind of glob list
+and override GOPRIVATE for the specific decision of whether to use the proxy
+and checksum database, respectively.
+
+For example, if a company ran a module proxy serving private modules,
+users would configure go using:
+
+ GOPRIVATE=*.corp.example.com
+ GOPROXY=proxy.example.com
+ GONOPROXY=none
+
+The GOPRIVATE variable is also used to define the "public" and "private"
+patterns for the GOVCS variable; see 'go help vcs'. For that usage,
+GOPRIVATE applies even in GOPATH mode. In that case, it matches import paths
+instead of module paths.
+
+The 'go env -w' command (see 'go help env') can be used to set these variables
+for future go command invocations.
+
+For more details, see https://golang.org/ref/mod#private-modules.
+`,
+}
diff --git a/src/cmd/go/internal/modfetch/key.go b/src/cmd/go/internal/modfetch/key.go
new file mode 100644
index 0000000..06f9989
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/key.go
@@ -0,0 +1,9 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modfetch
+
+var knownGOSUMDB = map[string]string{
+ "sum.golang.org": "sum.golang.org+033de0ae+Ac4zctda0e5eza+HJyk9SxEdh+s3Ux18htTTAD8OuAn8",
+}
diff --git a/src/cmd/go/internal/modfetch/proxy.go b/src/cmd/go/internal/modfetch/proxy.go
new file mode 100644
index 0000000..e0efb09
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/proxy.go
@@ -0,0 +1,453 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modfetch
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/fs"
+ "net/url"
+ "path"
+ pathpkg "path"
+ "path/filepath"
+ "strings"
+ "sync"
+ "time"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/modfetch/codehost"
+ "cmd/go/internal/web"
+
+ "golang.org/x/mod/module"
+ "golang.org/x/mod/semver"
+)
+
+var HelpGoproxy = &base.Command{
+ UsageLine: "goproxy",
+ Short: "module proxy protocol",
+ Long: `
+A Go module proxy is any web server that can respond to GET requests for
+URLs of a specified form. The requests have no query parameters, so even
+a site serving from a fixed file system (including a file:/// URL)
+can be a module proxy.
+
+For details on the GOPROXY protocol, see
+https://golang.org/ref/mod#goproxy-protocol.
+`,
+}
+
+var proxyOnce struct {
+ sync.Once
+ list []proxySpec
+ err error
+}
+
+type proxySpec struct {
+ // url is the proxy URL or one of "off", "direct", "noproxy".
+ url string
+
+ // fallBackOnError is true if a request should be attempted on the next proxy
+ // in the list after any error from this proxy. If fallBackOnError is false,
+ // the request will only be attempted on the next proxy if the error is
+ // equivalent to os.ErrNotFound, which is true for 404 and 410 responses.
+ fallBackOnError bool
+}
+
+func proxyList() ([]proxySpec, error) {
+ proxyOnce.Do(func() {
+ if cfg.GONOPROXY != "" && cfg.GOPROXY != "direct" {
+ proxyOnce.list = append(proxyOnce.list, proxySpec{url: "noproxy"})
+ }
+
+ goproxy := cfg.GOPROXY
+ for goproxy != "" {
+ var url string
+ fallBackOnError := false
+ if i := strings.IndexAny(goproxy, ",|"); i >= 0 {
+ url = goproxy[:i]
+ fallBackOnError = goproxy[i] == '|'
+ goproxy = goproxy[i+1:]
+ } else {
+ url = goproxy
+ goproxy = ""
+ }
+
+ url = strings.TrimSpace(url)
+ if url == "" {
+ continue
+ }
+ if url == "off" {
+ // "off" always fails hard, so can stop walking list.
+ proxyOnce.list = append(proxyOnce.list, proxySpec{url: "off"})
+ break
+ }
+ if url == "direct" {
+ proxyOnce.list = append(proxyOnce.list, proxySpec{url: "direct"})
+ // For now, "direct" is the end of the line. We may decide to add some
+ // sort of fallback behavior for them in the future, so ignore
+ // subsequent entries for forward-compatibility.
+ break
+ }
+
+ // Single-word tokens are reserved for built-in behaviors, and anything
+ // containing the string ":/" or matching an absolute file path must be a
+ // complete URL. For all other paths, implicitly add "https://".
+ if strings.ContainsAny(url, ".:/") && !strings.Contains(url, ":/") && !filepath.IsAbs(url) && !path.IsAbs(url) {
+ url = "https://" + url
+ }
+
+ // Check that newProxyRepo accepts the URL.
+ // It won't do anything with the path.
+ if _, err := newProxyRepo(url, "golang.org/x/text"); err != nil {
+ proxyOnce.err = err
+ return
+ }
+
+ proxyOnce.list = append(proxyOnce.list, proxySpec{
+ url: url,
+ fallBackOnError: fallBackOnError,
+ })
+ }
+
+ if len(proxyOnce.list) == 0 ||
+ len(proxyOnce.list) == 1 && proxyOnce.list[0].url == "noproxy" {
+ // There were no proxies, other than the implicit "noproxy" added when
+ // GONOPROXY is set. This can happen if GOPROXY is a non-empty string
+ // like "," or " ".
+ proxyOnce.err = fmt.Errorf("GOPROXY list is not the empty string, but contains no entries")
+ }
+ })
+
+ return proxyOnce.list, proxyOnce.err
+}
+
+// TryProxies iterates f over each configured proxy (including "noproxy" and
+// "direct" if applicable) until f returns no error or until f returns an
+// error that is not equivalent to fs.ErrNotExist on a proxy configured
+// not to fall back on errors.
+//
+// TryProxies then returns that final error.
+//
+// If GOPROXY is set to "off", TryProxies invokes f once with the argument
+// "off".
+func TryProxies(f func(proxy string) error) error {
+ proxies, err := proxyList()
+ if err != nil {
+ return err
+ }
+ if len(proxies) == 0 {
+ panic("GOPROXY list is empty")
+ }
+
+ // We try to report the most helpful error to the user. "direct" and "noproxy"
+ // errors are best, followed by proxy errors other than ErrNotExist, followed
+ // by ErrNotExist.
+ //
+ // Note that errProxyOff, errNoproxy, and errUseProxy are equivalent to
+ // ErrNotExist. errUseProxy should only be returned if "noproxy" is the only
+ // proxy. errNoproxy should never be returned, since there should always be a
+ // more useful error from "noproxy" first.
+ const (
+ notExistRank = iota
+ proxyRank
+ directRank
+ )
+ var bestErr error
+ bestErrRank := notExistRank
+ for _, proxy := range proxies {
+ err := f(proxy.url)
+ if err == nil {
+ return nil
+ }
+ isNotExistErr := errors.Is(err, fs.ErrNotExist)
+
+ if proxy.url == "direct" || (proxy.url == "noproxy" && err != errUseProxy) {
+ bestErr = err
+ bestErrRank = directRank
+ } else if bestErrRank <= proxyRank && !isNotExistErr {
+ bestErr = err
+ bestErrRank = proxyRank
+ } else if bestErrRank == notExistRank {
+ bestErr = err
+ }
+
+ if !proxy.fallBackOnError && !isNotExistErr {
+ break
+ }
+ }
+ return bestErr
+}
+
+type proxyRepo struct {
+ url *url.URL // The combined module proxy URL joined with the module path.
+ path string // The module path (unescaped).
+ redactedBase string // The base module proxy URL in [url.URL.Redacted] form.
+
+ listLatestOnce sync.Once
+ listLatest *RevInfo
+ listLatestErr error
+}
+
+func newProxyRepo(baseURL, path string) (Repo, error) {
+ // Parse the base proxy URL.
+ base, err := url.Parse(baseURL)
+ if err != nil {
+ return nil, err
+ }
+ redactedBase := base.Redacted()
+ switch base.Scheme {
+ case "http", "https":
+ // ok
+ case "file":
+ if *base != (url.URL{Scheme: base.Scheme, Path: base.Path, RawPath: base.RawPath}) {
+ return nil, fmt.Errorf("invalid file:// proxy URL with non-path elements: %s", redactedBase)
+ }
+ case "":
+ return nil, fmt.Errorf("invalid proxy URL missing scheme: %s", redactedBase)
+ default:
+ return nil, fmt.Errorf("invalid proxy URL scheme (must be https, http, file): %s", redactedBase)
+ }
+
+ // Append the module path to the URL.
+ url := base
+ enc, err := module.EscapePath(path)
+ if err != nil {
+ return nil, err
+ }
+ url.Path = strings.TrimSuffix(base.Path, "/") + "/" + enc
+ url.RawPath = strings.TrimSuffix(base.RawPath, "/") + "/" + pathEscape(enc)
+
+ return &proxyRepo{url, path, redactedBase, sync.Once{}, nil, nil}, nil
+}
+
+func (p *proxyRepo) ModulePath() string {
+ return p.path
+}
+
+var errProxyReuse = fmt.Errorf("proxy does not support CheckReuse")
+
+func (p *proxyRepo) CheckReuse(ctx context.Context, old *codehost.Origin) error {
+ return errProxyReuse
+}
+
+// versionError returns err wrapped in a ModuleError for p.path.
+func (p *proxyRepo) versionError(version string, err error) error {
+ if version != "" && version != module.CanonicalVersion(version) {
+ return &module.ModuleError{
+ Path: p.path,
+ Err: &module.InvalidVersionError{
+ Version: version,
+ Pseudo: module.IsPseudoVersion(version),
+ Err: err,
+ },
+ }
+ }
+
+ return &module.ModuleError{
+ Path: p.path,
+ Version: version,
+ Err: err,
+ }
+}
+
+func (p *proxyRepo) getBytes(ctx context.Context, path string) ([]byte, error) {
+ body, redactedURL, err := p.getBody(ctx, path)
+ if err != nil {
+ return nil, err
+ }
+ defer body.Close()
+
+ b, err := io.ReadAll(body)
+ if err != nil {
+ // net/http doesn't add context to Body read errors, so add it here.
+ // (See https://go.dev/issue/52727.)
+ return b, &url.Error{Op: "read", URL: redactedURL, Err: err}
+ }
+ return b, nil
+}
+
+func (p *proxyRepo) getBody(ctx context.Context, path string) (r io.ReadCloser, redactedURL string, err error) {
+ fullPath := pathpkg.Join(p.url.Path, path)
+
+ target := *p.url
+ target.Path = fullPath
+ target.RawPath = pathpkg.Join(target.RawPath, pathEscape(path))
+
+ resp, err := web.Get(web.DefaultSecurity, &target)
+ if err != nil {
+ return nil, "", err
+ }
+ if err := resp.Err(); err != nil {
+ resp.Body.Close()
+ return nil, "", err
+ }
+ return resp.Body, resp.URL, nil
+}
+
+func (p *proxyRepo) Versions(ctx context.Context, prefix string) (*Versions, error) {
+ data, err := p.getBytes(ctx, "@v/list")
+ if err != nil {
+ p.listLatestOnce.Do(func() {
+ p.listLatest, p.listLatestErr = nil, p.versionError("", err)
+ })
+ return nil, p.versionError("", err)
+ }
+ var list []string
+ allLine := strings.Split(string(data), "\n")
+ for _, line := range allLine {
+ f := strings.Fields(line)
+ if len(f) >= 1 && semver.IsValid(f[0]) && strings.HasPrefix(f[0], prefix) && !module.IsPseudoVersion(f[0]) {
+ list = append(list, f[0])
+ }
+ }
+ p.listLatestOnce.Do(func() {
+ p.listLatest, p.listLatestErr = p.latestFromList(ctx, allLine)
+ })
+ semver.Sort(list)
+ return &Versions{List: list}, nil
+}
+
+func (p *proxyRepo) latest(ctx context.Context) (*RevInfo, error) {
+ p.listLatestOnce.Do(func() {
+ data, err := p.getBytes(ctx, "@v/list")
+ if err != nil {
+ p.listLatestErr = p.versionError("", err)
+ return
+ }
+ list := strings.Split(string(data), "\n")
+ p.listLatest, p.listLatestErr = p.latestFromList(ctx, list)
+ })
+ return p.listLatest, p.listLatestErr
+}
+
+func (p *proxyRepo) latestFromList(ctx context.Context, allLine []string) (*RevInfo, error) {
+ var (
+ bestTime time.Time
+ bestVersion string
+ )
+ for _, line := range allLine {
+ f := strings.Fields(line)
+ if len(f) >= 1 && semver.IsValid(f[0]) {
+ // If the proxy includes timestamps, prefer the timestamp it reports.
+ // Otherwise, derive the timestamp from the pseudo-version.
+ var (
+ ft time.Time
+ )
+ if len(f) >= 2 {
+ ft, _ = time.Parse(time.RFC3339, f[1])
+ } else if module.IsPseudoVersion(f[0]) {
+ ft, _ = module.PseudoVersionTime(f[0])
+ } else {
+ // Repo.Latest promises that this method is only called where there are
+ // no tagged versions. Ignore any tagged versions that were added in the
+ // meantime.
+ continue
+ }
+ if bestTime.Before(ft) {
+ bestTime = ft
+ bestVersion = f[0]
+ }
+ }
+ }
+ if bestVersion == "" {
+ return nil, p.versionError("", codehost.ErrNoCommits)
+ }
+
+ // Call Stat to get all the other fields, including Origin information.
+ return p.Stat(ctx, bestVersion)
+}
+
+func (p *proxyRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
+ encRev, err := module.EscapeVersion(rev)
+ if err != nil {
+ return nil, p.versionError(rev, err)
+ }
+ data, err := p.getBytes(ctx, "@v/"+encRev+".info")
+ if err != nil {
+ return nil, p.versionError(rev, err)
+ }
+ info := new(RevInfo)
+ if err := json.Unmarshal(data, info); err != nil {
+ return nil, p.versionError(rev, fmt.Errorf("invalid response from proxy %q: %w", p.redactedBase, err))
+ }
+ if info.Version != rev && rev == module.CanonicalVersion(rev) && module.Check(p.path, rev) == nil {
+ // If we request a correct, appropriate version for the module path, the
+ // proxy must return either exactly that version or an error — not some
+ // arbitrary other version.
+ return nil, p.versionError(rev, fmt.Errorf("proxy returned info for version %s instead of requested version", info.Version))
+ }
+ return info, nil
+}
+
+func (p *proxyRepo) Latest(ctx context.Context) (*RevInfo, error) {
+ data, err := p.getBytes(ctx, "@latest")
+ if err != nil {
+ if !errors.Is(err, fs.ErrNotExist) {
+ return nil, p.versionError("", err)
+ }
+ return p.latest(ctx)
+ }
+ info := new(RevInfo)
+ if err := json.Unmarshal(data, info); err != nil {
+ return nil, p.versionError("", fmt.Errorf("invalid response from proxy %q: %w", p.redactedBase, err))
+ }
+ return info, nil
+}
+
+func (p *proxyRepo) GoMod(ctx context.Context, version string) ([]byte, error) {
+ if version != module.CanonicalVersion(version) {
+ return nil, p.versionError(version, fmt.Errorf("internal error: version passed to GoMod is not canonical"))
+ }
+
+ encVer, err := module.EscapeVersion(version)
+ if err != nil {
+ return nil, p.versionError(version, err)
+ }
+ data, err := p.getBytes(ctx, "@v/"+encVer+".mod")
+ if err != nil {
+ return nil, p.versionError(version, err)
+ }
+ return data, nil
+}
+
+func (p *proxyRepo) Zip(ctx context.Context, dst io.Writer, version string) error {
+ if version != module.CanonicalVersion(version) {
+ return p.versionError(version, fmt.Errorf("internal error: version passed to Zip is not canonical"))
+ }
+
+ encVer, err := module.EscapeVersion(version)
+ if err != nil {
+ return p.versionError(version, err)
+ }
+ path := "@v/" + encVer + ".zip"
+ body, redactedURL, err := p.getBody(ctx, path)
+ if err != nil {
+ return p.versionError(version, err)
+ }
+ defer body.Close()
+
+ lr := &io.LimitedReader{R: body, N: codehost.MaxZipFile + 1}
+ if _, err := io.Copy(dst, lr); err != nil {
+ // net/http doesn't add context to Body read errors, so add it here.
+ // (See https://go.dev/issue/52727.)
+ err = &url.Error{Op: "read", URL: redactedURL, Err: err}
+ return p.versionError(version, err)
+ }
+ if lr.N <= 0 {
+ return p.versionError(version, fmt.Errorf("downloaded zip file too large"))
+ }
+ return nil
+}
+
+// pathEscape escapes s so it can be used in a path.
+// That is, it escapes things like ? and # (which really shouldn't appear anyway).
+// It does not escape / to %2F: our REST API is designed so that / can be left as is.
+func pathEscape(s string) string {
+ return strings.ReplaceAll(url.PathEscape(s), "%2F", "/")
+}
diff --git a/src/cmd/go/internal/modfetch/repo.go b/src/cmd/go/internal/modfetch/repo.go
new file mode 100644
index 0000000..25fb02d
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/repo.go
@@ -0,0 +1,411 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modfetch
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "io/fs"
+ "os"
+ "strconv"
+ "time"
+
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/modfetch/codehost"
+ "cmd/go/internal/par"
+ "cmd/go/internal/vcs"
+ web "cmd/go/internal/web"
+
+ "golang.org/x/mod/module"
+)
+
+const traceRepo = false // trace all repo actions, for debugging
+
+// A Repo represents a repository storing all versions of a single module.
+// It must be safe for simultaneous use by multiple goroutines.
+type Repo interface {
+ // ModulePath returns the module path.
+ ModulePath() string
+
+ // CheckReuse checks whether the validation criteria in the origin
+ // are still satisfied on the server corresponding to this module.
+ // If so, the caller can reuse any cached Versions or RevInfo containing
+ // this origin rather than redownloading those from the server.
+ CheckReuse(ctx context.Context, old *codehost.Origin) error
+
+ // Versions lists all known versions with the given prefix.
+ // Pseudo-versions are not included.
+ //
+ // Versions should be returned sorted in semver order
+ // (implementations can use semver.Sort).
+ //
+ // Versions returns a non-nil error only if there was a problem
+ // fetching the list of versions: it may return an empty list
+ // along with a nil error if the list of matching versions
+ // is known to be empty.
+ //
+ // If the underlying repository does not exist,
+ // Versions returns an error matching errors.Is(_, os.NotExist).
+ Versions(ctx context.Context, prefix string) (*Versions, error)
+
+ // Stat returns information about the revision rev.
+ // A revision can be any identifier known to the underlying service:
+ // commit hash, branch, tag, and so on.
+ Stat(ctx context.Context, rev string) (*RevInfo, error)
+
+ // Latest returns the latest revision on the default branch,
+ // whatever that means in the underlying source code repository.
+ // It is only used when there are no tagged versions.
+ Latest(ctx context.Context) (*RevInfo, error)
+
+ // GoMod returns the go.mod file for the given version.
+ GoMod(ctx context.Context, version string) (data []byte, err error)
+
+ // Zip writes a zip file for the given version to dst.
+ Zip(ctx context.Context, dst io.Writer, version string) error
+}
+
+// A Versions describes the available versions in a module repository.
+type Versions struct {
+ Origin *codehost.Origin `json:",omitempty"` // origin information for reuse
+
+ List []string // semver versions
+}
+
+// A RevInfo describes a single revision in a module repository.
+type RevInfo struct {
+ Version string // suggested version string for this revision
+ Time time.Time // commit time
+
+ // These fields are used for Stat of arbitrary rev,
+ // but they are not recorded when talking about module versions.
+ Name string `json:"-"` // complete ID in underlying repository
+ Short string `json:"-"` // shortened ID, for use in pseudo-version
+
+ Origin *codehost.Origin `json:",omitempty"` // provenance for reuse
+}
+
+// Re: module paths, import paths, repository roots, and lookups
+//
+// A module is a collection of Go packages stored in a file tree
+// with a go.mod file at the root of the tree.
+// The go.mod defines the module path, which is the import path
+// corresponding to the root of the file tree.
+// The import path of a directory within that file tree is the module path
+// joined with the name of the subdirectory relative to the root.
+//
+// For example, the module with path rsc.io/qr corresponds to the
+// file tree in the repository https://github.com/rsc/qr.
+// That file tree has a go.mod that says "module rsc.io/qr".
+// The package in the root directory has import path "rsc.io/qr".
+// The package in the gf256 subdirectory has import path "rsc.io/qr/gf256".
+// In this example, "rsc.io/qr" is both a module path and an import path.
+// But "rsc.io/qr/gf256" is only an import path, not a module path:
+// it names an importable package, but not a module.
+//
+// As a special case to incorporate code written before modules were
+// introduced, if a path p resolves using the pre-module "go get" lookup
+// to the root of a source code repository without a go.mod file,
+// that repository is treated as if it had a go.mod in its root directory
+// declaring module path p. (The go.mod is further considered to
+// contain requirements corresponding to any legacy version
+// tracking format such as Gopkg.lock, vendor/vendor.conf, and so on.)
+//
+// The presentation so far ignores the fact that a source code repository
+// has many different versions of a file tree, and those versions may
+// differ in whether a particular go.mod exists and what it contains.
+// In fact there is a well-defined mapping only from a module path, version
+// pair - often written path@version - to a particular file tree.
+// For example rsc.io/qr@v0.1.0 depends on the "implicit go.mod at root of
+// repository" rule, while rsc.io/qr@v0.2.0 has an explicit go.mod.
+// Because the "go get" import paths rsc.io/qr and github.com/rsc/qr
+// both redirect to the Git repository https://github.com/rsc/qr,
+// github.com/rsc/qr@v0.1.0 is the same file tree as rsc.io/qr@v0.1.0
+// but a different module (a different name). In contrast, since v0.2.0
+// of that repository has an explicit go.mod that declares path rsc.io/qr,
+// github.com/rsc/qr@v0.2.0 is an invalid module path, version pair.
+// Before modules, import comments would have had the same effect.
+//
+// The set of import paths associated with a given module path is
+// clearly not fixed: at the least, new directories with new import paths
+// can always be added. But another potential operation is to split a
+// subtree out of a module into its own module. If done carefully,
+// this operation can be done while preserving compatibility for clients.
+// For example, suppose that we want to split rsc.io/qr/gf256 into its
+// own module, so that there would be two modules rsc.io/qr and rsc.io/qr/gf256.
+// Then we can simultaneously issue rsc.io/qr v0.3.0 (dropping the gf256 subdirectory)
+// and rsc.io/qr/gf256 v0.1.0, including in their respective go.mod
+// cyclic requirements pointing at each other: rsc.io/qr v0.3.0 requires
+// rsc.io/qr/gf256 v0.1.0 and vice versa. Then a build can be
+// using an older rsc.io/qr module that includes the gf256 package, but if
+// it adds a requirement on either the newer rsc.io/qr or the newer
+// rsc.io/qr/gf256 module, it will automatically add the requirement
+// on the complementary half, ensuring both that rsc.io/qr/gf256 is
+// available for importing by the build and also that it is only defined
+// by a single module. The gf256 package could move back into the
+// original by another simultaneous release of rsc.io/qr v0.4.0 including
+// the gf256 subdirectory and an rsc.io/qr/gf256 v0.2.0 with no code
+// in its root directory, along with a new requirement cycle.
+// The ability to shift module boundaries in this way is expected to be
+// important in large-scale program refactorings, similar to the ones
+// described in https://talks.golang.org/2016/refactor.article.
+//
+// The possibility of shifting module boundaries reemphasizes
+// that you must know both the module path and its version
+// to determine the set of packages provided directly by that module.
+//
+// On top of all this, it is possible for a single code repository
+// to contain multiple modules, either in branches or subdirectories,
+// as a limited kind of monorepo. For example rsc.io/qr/v2,
+// the v2.x.x continuation of rsc.io/qr, is expected to be found
+// in v2-tagged commits in https://github.com/rsc/qr, either
+// in the root or in a v2 subdirectory, disambiguated by go.mod.
+// Again the precise file tree corresponding to a module
+// depends on which version we are considering.
+//
+// It is also possible for the underlying repository to change over time,
+// without changing the module path. If I copy the github repo over
+// to https://bitbucket.org/rsc/qr and update https://rsc.io/qr?go-get=1,
+// then clients of all versions should start fetching from bitbucket
+// instead of github. That is, in contrast to the exact file tree,
+// the location of the source code repository associated with a module path
+// does not depend on the module version. (This is by design, as the whole
+// point of these redirects is to allow package authors to establish a stable
+// name that can be updated as code moves from one service to another.)
+//
+// All of this is important background for the lookup APIs defined in this
+// file.
+//
+// The Lookup function takes a module path and returns a Repo representing
+// that module path. Lookup can do only a little with the path alone.
+// It can check that the path is well-formed (see semver.CheckPath)
+// and it can check that the path can be resolved to a target repository.
+// To avoid version control access except when absolutely necessary,
+// Lookup does not attempt to connect to the repository itself.
+
+var lookupCache par.Cache[lookupCacheKey, Repo]
+
+type lookupCacheKey struct {
+ proxy, path string
+}
+
+// Lookup returns the module with the given module path,
+// fetched through the given proxy.
+//
+// The distinguished proxy "direct" indicates that the path should be fetched
+// from its origin, and "noproxy" indicates that the patch should be fetched
+// directly only if GONOPROXY matches the given path.
+//
+// For the distinguished proxy "off", Lookup always returns a Repo that returns
+// a non-nil error for every method call.
+//
+// A successful return does not guarantee that the module
+// has any defined versions.
+func Lookup(ctx context.Context, proxy, path string) Repo {
+ if traceRepo {
+ defer logCall("Lookup(%q, %q)", proxy, path)()
+ }
+
+ return lookupCache.Do(lookupCacheKey{proxy, path}, func() Repo {
+ return newCachingRepo(ctx, path, func(ctx context.Context) (Repo, error) {
+ r, err := lookup(ctx, proxy, path)
+ if err == nil && traceRepo {
+ r = newLoggingRepo(r)
+ }
+ return r, err
+ })
+ })
+}
+
+// lookup returns the module with the given module path.
+func lookup(ctx context.Context, proxy, path string) (r Repo, err error) {
+ if cfg.BuildMod == "vendor" {
+ return nil, errLookupDisabled
+ }
+
+ switch path {
+ case "go", "toolchain":
+ return &toolchainRepo{path, Lookup(ctx, proxy, "golang.org/toolchain")}, nil
+ }
+
+ if module.MatchPrefixPatterns(cfg.GONOPROXY, path) {
+ switch proxy {
+ case "noproxy", "direct":
+ return lookupDirect(ctx, path)
+ default:
+ return nil, errNoproxy
+ }
+ }
+
+ switch proxy {
+ case "off":
+ return errRepo{path, errProxyOff}, nil
+ case "direct":
+ return lookupDirect(ctx, path)
+ case "noproxy":
+ return nil, errUseProxy
+ default:
+ return newProxyRepo(proxy, path)
+ }
+}
+
+type lookupDisabledError struct{}
+
+func (lookupDisabledError) Error() string {
+ if cfg.BuildModReason == "" {
+ return fmt.Sprintf("module lookup disabled by -mod=%s", cfg.BuildMod)
+ }
+ return fmt.Sprintf("module lookup disabled by -mod=%s\n\t(%s)", cfg.BuildMod, cfg.BuildModReason)
+}
+
+var errLookupDisabled error = lookupDisabledError{}
+
+var (
+ errProxyOff = notExistErrorf("module lookup disabled by GOPROXY=off")
+ errNoproxy error = notExistErrorf("disabled by GOPRIVATE/GONOPROXY")
+ errUseProxy error = notExistErrorf("path does not match GOPRIVATE/GONOPROXY")
+)
+
+func lookupDirect(ctx context.Context, path string) (Repo, error) {
+ security := web.SecureOnly
+
+ if module.MatchPrefixPatterns(cfg.GOINSECURE, path) {
+ security = web.Insecure
+ }
+ rr, err := vcs.RepoRootForImportPath(path, vcs.PreferMod, security)
+ if err != nil {
+ // We don't know where to find code for a module with this path.
+ return nil, notExistError{err: err}
+ }
+
+ if rr.VCS.Name == "mod" {
+ // Fetch module from proxy with base URL rr.Repo.
+ return newProxyRepo(rr.Repo, path)
+ }
+
+ code, err := lookupCodeRepo(ctx, rr)
+ if err != nil {
+ return nil, err
+ }
+ return newCodeRepo(code, rr.Root, path)
+}
+
+func lookupCodeRepo(ctx context.Context, rr *vcs.RepoRoot) (codehost.Repo, error) {
+ code, err := codehost.NewRepo(ctx, rr.VCS.Cmd, rr.Repo)
+ if err != nil {
+ if _, ok := err.(*codehost.VCSError); ok {
+ return nil, err
+ }
+ return nil, fmt.Errorf("lookup %s: %v", rr.Root, err)
+ }
+ return code, nil
+}
+
+// A loggingRepo is a wrapper around an underlying Repo
+// that prints a log message at the start and end of each call.
+// It can be inserted when debugging.
+type loggingRepo struct {
+ r Repo
+}
+
+func newLoggingRepo(r Repo) *loggingRepo {
+ return &loggingRepo{r}
+}
+
+// logCall prints a log message using format and args and then
+// also returns a function that will print the same message again,
+// along with the elapsed time.
+// Typical usage is:
+//
+// defer logCall("hello %s", arg)()
+//
+// Note the final ().
+func logCall(format string, args ...any) func() {
+ start := time.Now()
+ fmt.Fprintf(os.Stderr, "+++ %s\n", fmt.Sprintf(format, args...))
+ return func() {
+ fmt.Fprintf(os.Stderr, "%.3fs %s\n", time.Since(start).Seconds(), fmt.Sprintf(format, args...))
+ }
+}
+
+func (l *loggingRepo) ModulePath() string {
+ return l.r.ModulePath()
+}
+
+func (l *loggingRepo) CheckReuse(ctx context.Context, old *codehost.Origin) (err error) {
+ defer func() {
+ logCall("CheckReuse[%s]: %v", l.r.ModulePath(), err)
+ }()
+ return l.r.CheckReuse(ctx, old)
+}
+
+func (l *loggingRepo) Versions(ctx context.Context, prefix string) (*Versions, error) {
+ defer logCall("Repo[%s]: Versions(%q)", l.r.ModulePath(), prefix)()
+ return l.r.Versions(ctx, prefix)
+}
+
+func (l *loggingRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
+ defer logCall("Repo[%s]: Stat(%q)", l.r.ModulePath(), rev)()
+ return l.r.Stat(ctx, rev)
+}
+
+func (l *loggingRepo) Latest(ctx context.Context) (*RevInfo, error) {
+ defer logCall("Repo[%s]: Latest()", l.r.ModulePath())()
+ return l.r.Latest(ctx)
+}
+
+func (l *loggingRepo) GoMod(ctx context.Context, version string) ([]byte, error) {
+ defer logCall("Repo[%s]: GoMod(%q)", l.r.ModulePath(), version)()
+ return l.r.GoMod(ctx, version)
+}
+
+func (l *loggingRepo) Zip(ctx context.Context, dst io.Writer, version string) error {
+ dstName := "_"
+ if dst, ok := dst.(interface{ Name() string }); ok {
+ dstName = strconv.Quote(dst.Name())
+ }
+ defer logCall("Repo[%s]: Zip(%s, %q)", l.r.ModulePath(), dstName, version)()
+ return l.r.Zip(ctx, dst, version)
+}
+
+// errRepo is a Repo that returns the same error for all operations.
+//
+// It is useful in conjunction with caching, since cache hits will not attempt
+// the prohibited operations.
+type errRepo struct {
+ modulePath string
+ err error
+}
+
+func (r errRepo) ModulePath() string { return r.modulePath }
+
+func (r errRepo) CheckReuse(ctx context.Context, old *codehost.Origin) error { return r.err }
+func (r errRepo) Versions(ctx context.Context, prefix string) (*Versions, error) { return nil, r.err }
+func (r errRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) { return nil, r.err }
+func (r errRepo) Latest(ctx context.Context) (*RevInfo, error) { return nil, r.err }
+func (r errRepo) GoMod(ctx context.Context, version string) ([]byte, error) { return nil, r.err }
+func (r errRepo) Zip(ctx context.Context, dst io.Writer, version string) error { return r.err }
+
+// A notExistError is like fs.ErrNotExist, but with a custom message
+type notExistError struct {
+ err error
+}
+
+func notExistErrorf(format string, args ...any) error {
+ return notExistError{fmt.Errorf(format, args...)}
+}
+
+func (e notExistError) Error() string {
+ return e.err.Error()
+}
+
+func (notExistError) Is(target error) bool {
+ return target == fs.ErrNotExist
+}
+
+func (e notExistError) Unwrap() error {
+ return e.err
+}
diff --git a/src/cmd/go/internal/modfetch/sumdb.go b/src/cmd/go/internal/modfetch/sumdb.go
new file mode 100644
index 0000000..ea7d561
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/sumdb.go
@@ -0,0 +1,315 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Go checksum database lookup
+
+//go:build !cmd_go_bootstrap
+
+package modfetch
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "io/fs"
+ "net/url"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+ "time"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/lockedfile"
+ "cmd/go/internal/web"
+
+ "golang.org/x/mod/module"
+ "golang.org/x/mod/sumdb"
+ "golang.org/x/mod/sumdb/note"
+)
+
+// useSumDB reports whether to use the Go checksum database for the given module.
+func useSumDB(mod module.Version) bool {
+ if mod.Path == "golang.org/toolchain" {
+ must := true
+ // Downloaded toolchains cannot be listed in go.sum,
+ // so we require checksum database lookups even if
+ // GOSUMDB=off or GONOSUMDB matches the pattern.
+ // If GOSUMDB=off, then the eventual lookup will fail
+ // with a good error message.
+
+ // Exception #1: using GOPROXY=file:// to test a distpack.
+ if strings.HasPrefix(cfg.GOPROXY, "file://") && !strings.ContainsAny(cfg.GOPROXY, ",|") {
+ must = false
+ }
+ // Exception #2: the Go proxy+checksum database cannot check itself
+ // while doing the initial download.
+ if strings.Contains(os.Getenv("GIT_HTTP_USER_AGENT"), "proxy.golang.org") {
+ must = false
+ }
+
+ // Another potential exception would be GOPROXY=direct,
+ // but that would make toolchain downloads only as secure
+ // as HTTPS, and in particular they'd be susceptible to MITM
+ // attacks on systems with less-than-trustworthy root certificates.
+ // The checksum database provides a stronger guarantee,
+ // so we don't make that exception.
+
+ // Otherwise, require the checksum database.
+ if must {
+ return true
+ }
+ }
+ return cfg.GOSUMDB != "off" && !module.MatchPrefixPatterns(cfg.GONOSUMDB, mod.Path)
+}
+
+// lookupSumDB returns the Go checksum database's go.sum lines for the given module,
+// along with the name of the database.
+func lookupSumDB(mod module.Version) (dbname string, lines []string, err error) {
+ dbOnce.Do(func() {
+ dbName, db, dbErr = dbDial()
+ })
+ if dbErr != nil {
+ return "", nil, dbErr
+ }
+ lines, err = db.Lookup(mod.Path, mod.Version)
+ return dbName, lines, err
+}
+
+var (
+ dbOnce sync.Once
+ dbName string
+ db *sumdb.Client
+ dbErr error
+)
+
+func dbDial() (dbName string, db *sumdb.Client, err error) {
+ // $GOSUMDB can be "key" or "key url",
+ // and the key can be a full verifier key
+ // or a host on our list of known keys.
+
+ // Special case: sum.golang.google.cn
+ // is an alias, reachable inside mainland China,
+ // for sum.golang.org. If there are more
+ // of these we should add a map like knownGOSUMDB.
+ gosumdb := cfg.GOSUMDB
+ if gosumdb == "sum.golang.google.cn" {
+ gosumdb = "sum.golang.org https://sum.golang.google.cn"
+ }
+
+ if gosumdb == "off" {
+ return "", nil, fmt.Errorf("checksum database disabled by GOSUMDB=off")
+ }
+
+ key := strings.Fields(gosumdb)
+ if len(key) >= 1 {
+ if k := knownGOSUMDB[key[0]]; k != "" {
+ key[0] = k
+ }
+ }
+ if len(key) == 0 {
+ return "", nil, fmt.Errorf("missing GOSUMDB")
+ }
+ if len(key) > 2 {
+ return "", nil, fmt.Errorf("invalid GOSUMDB: too many fields")
+ }
+ vkey, err := note.NewVerifier(key[0])
+ if err != nil {
+ return "", nil, fmt.Errorf("invalid GOSUMDB: %v", err)
+ }
+ name := vkey.Name()
+
+ // No funny business in the database name.
+ direct, err := url.Parse("https://" + name)
+ if err != nil || strings.HasSuffix(name, "/") || *direct != (url.URL{Scheme: "https", Host: direct.Host, Path: direct.Path, RawPath: direct.RawPath}) || direct.RawPath != "" || direct.Host == "" {
+ return "", nil, fmt.Errorf("invalid sumdb name (must be host[/path]): %s %+v", name, *direct)
+ }
+
+ // Determine how to get to database.
+ var base *url.URL
+ if len(key) >= 2 {
+ // Use explicit alternate URL listed in $GOSUMDB,
+ // bypassing both the default URL derivation and any proxies.
+ u, err := url.Parse(key[1])
+ if err != nil {
+ return "", nil, fmt.Errorf("invalid GOSUMDB URL: %v", err)
+ }
+ base = u
+ }
+
+ return name, sumdb.NewClient(&dbClient{key: key[0], name: name, direct: direct, base: base}), nil
+}
+
+type dbClient struct {
+ key string
+ name string
+ direct *url.URL
+
+ once sync.Once
+ base *url.URL
+ baseErr error
+}
+
+func (c *dbClient) ReadRemote(path string) ([]byte, error) {
+ c.once.Do(c.initBase)
+ if c.baseErr != nil {
+ return nil, c.baseErr
+ }
+
+ var data []byte
+ start := time.Now()
+ targ := web.Join(c.base, path)
+ data, err := web.GetBytes(targ)
+ if false {
+ fmt.Fprintf(os.Stderr, "%.3fs %s\n", time.Since(start).Seconds(), targ.Redacted())
+ }
+ return data, err
+}
+
+// initBase determines the base URL for connecting to the database.
+// Determining the URL requires sending network traffic to proxies,
+// so this work is delayed until we need to download something from
+// the database. If everything we need is in the local cache and
+// c.ReadRemote is never called, we will never do this work.
+func (c *dbClient) initBase() {
+ if c.base != nil {
+ return
+ }
+
+ // Try proxies in turn until we find out how to connect to this database.
+ //
+ // Before accessing any checksum database URL using a proxy, the proxy
+ // client should first fetch <proxyURL>/sumdb/<sumdb-name>/supported.
+ //
+ // If that request returns a successful (HTTP 200) response, then the proxy
+ // supports proxying checksum database requests. In that case, the client
+ // should use the proxied access method only, never falling back to a direct
+ // connection to the database.
+ //
+ // If the /sumdb/<sumdb-name>/supported check fails with a “not found” (HTTP
+ // 404) or “gone” (HTTP 410) response, or if the proxy is configured to fall
+ // back on errors, the client will try the next proxy. If there are no
+ // proxies left or if the proxy is "direct" or "off", the client should
+ // connect directly to that database.
+ //
+ // Any other response is treated as the database being unavailable.
+ //
+ // See https://golang.org/design/25530-sumdb#proxying-a-checksum-database.
+ err := TryProxies(func(proxy string) error {
+ switch proxy {
+ case "noproxy":
+ return errUseProxy
+ case "direct", "off":
+ return errProxyOff
+ default:
+ proxyURL, err := url.Parse(proxy)
+ if err != nil {
+ return err
+ }
+ if _, err := web.GetBytes(web.Join(proxyURL, "sumdb/"+c.name+"/supported")); err != nil {
+ return err
+ }
+ // Success! This proxy will help us.
+ c.base = web.Join(proxyURL, "sumdb/"+c.name)
+ return nil
+ }
+ })
+ if errors.Is(err, fs.ErrNotExist) {
+ // No proxies, or all proxies failed (with 404, 410, or were allowed
+ // to fall back), or we reached an explicit "direct" or "off".
+ c.base = c.direct
+ } else if err != nil {
+ c.baseErr = err
+ }
+}
+
+// ReadConfig reads the key from c.key
+// and otherwise reads the config (a latest tree head) from GOPATH/pkg/sumdb/<file>.
+func (c *dbClient) ReadConfig(file string) (data []byte, err error) {
+ if file == "key" {
+ return []byte(c.key), nil
+ }
+
+ if cfg.SumdbDir == "" {
+ return nil, fmt.Errorf("could not locate sumdb file: missing $GOPATH: %s",
+ cfg.GoPathError)
+ }
+ targ := filepath.Join(cfg.SumdbDir, file)
+ data, err = lockedfile.Read(targ)
+ if errors.Is(err, fs.ErrNotExist) {
+ // Treat non-existent as empty, to bootstrap the "latest" file
+ // the first time we connect to a given database.
+ return []byte{}, nil
+ }
+ return data, err
+}
+
+// WriteConfig rewrites the latest tree head.
+func (*dbClient) WriteConfig(file string, old, new []byte) error {
+ if file == "key" {
+ // Should not happen.
+ return fmt.Errorf("cannot write key")
+ }
+ if cfg.SumdbDir == "" {
+ return fmt.Errorf("could not locate sumdb file: missing $GOPATH: %s",
+ cfg.GoPathError)
+ }
+ targ := filepath.Join(cfg.SumdbDir, file)
+ os.MkdirAll(filepath.Dir(targ), 0777)
+ f, err := lockedfile.Edit(targ)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ data, err := io.ReadAll(f)
+ if err != nil {
+ return err
+ }
+ if len(data) > 0 && !bytes.Equal(data, old) {
+ return sumdb.ErrWriteConflict
+ }
+ if _, err := f.Seek(0, 0); err != nil {
+ return err
+ }
+ if err := f.Truncate(0); err != nil {
+ return err
+ }
+ if _, err := f.Write(new); err != nil {
+ return err
+ }
+ return f.Close()
+}
+
+// ReadCache reads cached lookups or tiles from
+// GOPATH/pkg/mod/cache/download/sumdb,
+// which will be deleted by "go clean -modcache".
+func (*dbClient) ReadCache(file string) ([]byte, error) {
+ targ := filepath.Join(cfg.GOMODCACHE, "cache/download/sumdb", file)
+ data, err := lockedfile.Read(targ)
+ // lockedfile.Write does not atomically create the file with contents.
+ // There is a moment between file creation and locking the file for writing,
+ // during which the empty file can be locked for reading.
+ // Treat observing an empty file as file not found.
+ if err == nil && len(data) == 0 {
+ err = &fs.PathError{Op: "read", Path: targ, Err: fs.ErrNotExist}
+ }
+ return data, err
+}
+
+// WriteCache updates cached lookups or tiles.
+func (*dbClient) WriteCache(file string, data []byte) {
+ targ := filepath.Join(cfg.GOMODCACHE, "cache/download/sumdb", file)
+ os.MkdirAll(filepath.Dir(targ), 0777)
+ lockedfile.Write(targ, bytes.NewReader(data), 0666)
+}
+
+func (*dbClient) Log(msg string) {
+ // nothing for now
+}
+
+func (*dbClient) SecurityError(msg string) {
+ base.Fatalf("%s", msg)
+}
diff --git a/src/cmd/go/internal/modfetch/toolchain.go b/src/cmd/go/internal/modfetch/toolchain.go
new file mode 100644
index 0000000..0d7cfcf
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/toolchain.go
@@ -0,0 +1,181 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modfetch
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "sort"
+ "strings"
+
+ "cmd/go/internal/gover"
+ "cmd/go/internal/modfetch/codehost"
+)
+
+// A toolchainRepo is a synthesized repository reporting Go toolchain versions.
+// It has path "go" or "toolchain". The "go" repo reports versions like "1.2".
+// The "toolchain" repo reports versions like "go1.2".
+//
+// Note that the repo ONLY reports versions. It does not actually support
+// downloading of the actual toolchains. Instead, that is done using
+// the regular repo code with "golang.org/toolchain".
+// The naming conflict is unfortunate: "golang.org/toolchain"
+// should perhaps have been "go.dev/dl", but it's too late.
+//
+// For clarity, this file refers to golang.org/toolchain as the "DL" repo,
+// the one you can actually download.
+type toolchainRepo struct {
+ path string // either "go" or "toolchain"
+ repo Repo // underlying DL repo
+}
+
+func (r *toolchainRepo) ModulePath() string {
+ return r.path
+}
+
+func (r *toolchainRepo) Versions(ctx context.Context, prefix string) (*Versions, error) {
+ // Read DL repo list and convert to "go" or "toolchain" version list.
+ versions, err := r.repo.Versions(ctx, "")
+ if err != nil {
+ return nil, err
+ }
+ versions.Origin = nil
+ var list []string
+ have := make(map[string]bool)
+ goPrefix := ""
+ if r.path == "toolchain" {
+ goPrefix = "go"
+ }
+ for _, v := range versions.List {
+ v, ok := dlToGo(v)
+ if !ok {
+ continue
+ }
+ if !have[v] {
+ have[v] = true
+ list = append(list, goPrefix+v)
+ }
+ }
+
+ // Always include our own version.
+ // This means that the development branch of Go 1.21 (say) will allow 'go get go@1.21'
+ // even though there are no Go 1.21 releases yet.
+ // Once there is a release, 1.21 will be treated as a query matching the latest available release.
+ // Before then, 1.21 will be treated as a query that resolves to this entry we are adding (1.21).
+ if v := gover.Local(); !have[v] {
+ list = append(list, goPrefix+v)
+ }
+
+ if r.path == "go" {
+ sort.Slice(list, func(i, j int) bool {
+ return gover.Compare(list[i], list[j]) < 0
+ })
+ } else {
+ sort.Slice(list, func(i, j int) bool {
+ return gover.Compare(gover.FromToolchain(list[i]), gover.FromToolchain(list[j])) < 0
+ })
+ }
+ versions.List = list
+ return versions, nil
+}
+
+func (r *toolchainRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
+ // Convert rev to DL version and stat that to make sure it exists.
+ // In theory the go@ versions should be like 1.21.0
+ // and the toolchain@ versions should be like go1.21.0
+ // but people will type the wrong one, and so we accept
+ // both and silently correct it to the standard form.
+ prefix := ""
+ v := rev
+ v = strings.TrimPrefix(v, "go")
+ if r.path == "toolchain" {
+ prefix = "go"
+ }
+
+ if !gover.IsValid(v) {
+ return nil, fmt.Errorf("invalid %s version %s", r.path, rev)
+ }
+
+ // If we're asking about "go" (not "toolchain"), pretend to have
+ // all earlier Go versions available without network access:
+ // we will provide those ourselves, at least in GOTOOLCHAIN=auto mode.
+ if r.path == "go" && gover.Compare(v, gover.Local()) <= 0 {
+ return &RevInfo{Version: prefix + v}, nil
+ }
+
+ // Similarly, if we're asking about *exactly* the current toolchain,
+ // we don't need to access the network to know that it exists.
+ if r.path == "toolchain" && v == gover.Local() {
+ return &RevInfo{Version: prefix + v}, nil
+ }
+
+ if gover.IsLang(v) {
+ // We can only use a language (development) version if the current toolchain
+ // implements that version, and the two checks above have ruled that out.
+ return nil, fmt.Errorf("go language version %s is not a toolchain version", rev)
+ }
+
+ // Check that the underlying toolchain exists.
+ // We always ask about linux-amd64 because that one
+ // has always existed and is likely to always exist in the future.
+ // This avoids different behavior validating go versions on different
+ // architectures. The eventual download uses the right GOOS-GOARCH.
+ info, err := r.repo.Stat(ctx, goToDL(v, "linux", "amd64"))
+ if err != nil {
+ return nil, err
+ }
+
+ // Return the info using the canonicalized rev
+ // (toolchain 1.2 => toolchain go1.2).
+ return &RevInfo{Version: prefix + v, Time: info.Time}, nil
+}
+
+func (r *toolchainRepo) Latest(ctx context.Context) (*RevInfo, error) {
+ versions, err := r.Versions(ctx, "")
+ if err != nil {
+ return nil, err
+ }
+ var max string
+ for _, v := range versions.List {
+ if max == "" || gover.ModCompare(r.path, v, max) > 0 {
+ max = v
+ }
+ }
+ return r.Stat(ctx, max)
+}
+
+func (r *toolchainRepo) GoMod(ctx context.Context, version string) (data []byte, err error) {
+ return []byte("module " + r.path + "\n"), nil
+}
+
+func (r *toolchainRepo) Zip(ctx context.Context, dst io.Writer, version string) error {
+ return fmt.Errorf("invalid use of toolchainRepo: Zip")
+}
+
+func (r *toolchainRepo) CheckReuse(ctx context.Context, old *codehost.Origin) error {
+ return fmt.Errorf("invalid use of toolchainRepo: CheckReuse")
+}
+
+// goToDL converts a Go version like "1.2" to a DL module version like "v0.0.1-go1.2.linux-amd64".
+func goToDL(v, goos, goarch string) string {
+ return "v0.0.1-go" + v + ".linux-amd64"
+}
+
+// dlToGo converts a DL module version like "v0.0.1-go1.2.linux-amd64" to a Go version like "1.2".
+func dlToGo(v string) (string, bool) {
+ // v0.0.1-go1.19.7.windows-amd64
+ // cut v0.0.1-
+ _, v, ok := strings.Cut(v, "-")
+ if !ok {
+ return "", false
+ }
+ // cut .windows-amd64
+ i := strings.LastIndex(v, ".")
+ if i < 0 || !strings.Contains(v[i+1:], "-") {
+ return "", false
+ }
+ return strings.TrimPrefix(v[:i], "go"), true
+}
diff --git a/src/cmd/go/internal/modfetch/zip_sum_test/testdata/zip_sums.csv b/src/cmd/go/internal/modfetch/zip_sum_test/testdata/zip_sums.csv
new file mode 100644
index 0000000..0906975
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/zip_sum_test/testdata/zip_sums.csv
@@ -0,0 +1,2119 @@
+9fans.net/go,v0.0.2,h1:RYM6lWITV8oADrwLfdzxmt8ucfW6UtP9v1jg4qAbqts=,2c42aad9ed60e24046fbf5720f438884942897197cb790ce58cccdacedd9532d
+aahframe.work,v0.12.3,h1:hc3chv+f49yLYVT/aSEhgpoqd8bS0rDKEew1un8AkSo=,0c7e3fab03920a79ace8e0a9ddf4517225f595ce39f2124ec3d9353508da5dbd
+aahframework.org/essentials.v0,v0.8.0,h1:R/lcfOuhvZptG4IWX/CzAtpiVJFUjbCxLao6DfmeWBA=,d640fe6b83a31ffe09d12eea37de000be7ec8d7330c0a1d7413d6e31a675628d
+bazil.org/fuse,v0.0.0-20180421153158-65cc252bf669,h1:FNCRpXiquG1aoyqcIWVFmpTSKVcx2bQD38uZZeGtdlw=,fce7ed008451861ba30974e95468d716f5ff4fde14e9605dbc2db5fac935c71d
+bitbucket.org/abex/go-optional,v0.0.0-20150902044611-5304370459de,h1:iGmurCCO42qFsQ46DzROSsZJFf8/7AKFH/VpRGd2PBw=,02e1b23db09fb6945ba4ca57c0af8125b608fceae125fe625f6536b9e466e7e0
+bitbucket.org/abex/pathfinder,v0.0.0-20170507112819-bdce8b2efbc9,h1:M1jjfmrcOcmWy2/aABpm3k9h/M6NccmjgLtE5gVl+y8=,8469c0a656a895863d4714a658ee4a9634e78547142fa7239331e15d0143c679
+bitbucket.org/abex/sliceconv,v0.0.0-20151017061159-594a23261816,h1:7XPf5/Oar0LfWbnUY29doBDzSr6ToseiJRqkZtb0YOo=,e2433a32246bd5e2fb5d52bf6dc36188a75c4b59b98f76eb7607035b8525dd37
+bitbucket.org/abex/yumeko,v0.0.0-20190825151534-d98ca20ac08c,h1:ES4kIm83Q1RYr9uhhpQhqh/tqjt8H+Xz4xuSAv5Crcw=,1d352a11b3ed5850a425fde048cafa65b2c079c4e9647c52a339b28276065ba9
+bitbucket.org/liamstask/goose,v0.0.0-20150115234039-8488cc47d90c,h1:bkb2NMGo3/Du52wvYj9Whth5KZfMV6d3O0Vbr3nz/UE=,3d64cac7774bf87a9d050222b87387c112bcb6ef0ea0e2b3324a95330573a0c5
+bitbucket.org/ww/goautoneg,v0.0.0-20120707110453-75cd24fc2f2c,h1:t+Ra932MCC0eeyD/vigXqMbZTzgZjd4JOfBJWC6VSMI=,8ad2afdee1dc46b2c78e986bc2cce89cd0b8815b278a01879ef08d56585c247f
+bou.ke/monkey,v1.0.1,h1:zEMLInw9xvNakzUUPjfS4Ds6jYPqCFx3m7bRmG5NH2U=,20cb7da509322267189d32a125d7e0f782264508bc8e17306c80424514e797ce
+cloud.google.com/go,v0.47.0,h1:1JUtpcY9E7+eTospEwWS2QXP3DEn7poB3E2j0jN74mM=,7739fd24e36a536488115ef0ec9d739e608ee68448f8a469e84855c008b00ecd
+cloud.google.com/go/bigquery,v1.0.1,h1:hL+ycaJpVE9M7nLoiXb/Pn10ENE2u+oddxbD8uu0ZVU=,738d1f726ce24f618ee7563f6c9419e6307f8814548f45ad8a227cffbb1448c0
+cloud.google.com/go/datastore,v1.0.0,h1:Kt+gOPPp2LEPWp8CSfxhsM8ik9CcyE/gYu+0r+RnZvM=,41e93ec9526ae580da90300d7e421a6d39d79cb6118d62ad1d3c06422d8a71bf
+cloud.google.com/go/pubsub,v1.0.1,h1:W9tAK3E57P75u0XLLR82LZyw8VpAnhmyTOxW9qzmyj8=,8bca46a7c5f0dcd576d23fa9a5f107955316d6f0d8f306ee1d6faa7de99c3d29
+cloud.google.com/go/spanner,v1.0.0,h1:jLKThep5kbWLeBhLgtEfm/OPT08n1z7itVTR82WUBQg=,90579f16545e352c662ae9f62dd02dddf834fe10b33d1dbcfbf0a8aadfcd21f8
+cloud.google.com/go/storage,v1.0.0,h1:VV2nUM3wwLLGh9lSABFgZMjInyUbJeaRSE64WuAIQ+4=,baec4756c573ede58f19eb7ae4acaebd7ac3f0c56413ecbbd216ad46a589a5da
+code.cloudfoundry.org/clock,v0.0.0-20180518195852-02e53af36e6c,h1:5eeuG0BHx1+DHeT3AP+ISKZ2ht1UjGhm581ljqYpVeQ=,61785787db7dadaf695506636dcb98c26bbdd0c847f589aa1fb4bbe9ef0e4455
+code.cloudfoundry.org/gofileutils,v0.0.0-20170111115228-4d0c80011a0f,h1:UrKzEwTgeiff9vxdrfdqxibzpWjxLnuXDI5m6z3GJAk=,ec71ca818158525773e53568f71db38f63423822a426e1a18f7d34318e97eb3e
+code.cloudfoundry.org/lager,v2.0.0+incompatible,h1:WZwDKDB2PLd/oL+USK4b4aEjUymIej9My2nUQ9oWEwQ=,ce1da175885c2587ca091532a937108ed646e3bd6bd902640891f75ae70adb8b
+code.gitea.io/gitea,v1.9.5,h1:Q3PROlfPth1NlLGaeYcr6YVqyfAy7txnFpDKe1BXo7Q=,c7b63394004fb8f355d859f11a007ff17126eac092f90507a80392335351a6df
+code.gitea.io/sdk,v0.0.0-20191030144301-2a5a0e75e5cf,h1:uXUz7lXbs33QAYIu1rF0o8tNsa3DlDDSMYek/3CldIo=,6472a2b30b8108cae9b6a4914ce986d61e9ed37baade5ad35cb337270602b70a
+code.gitea.io/sdk/gitea,v0.0.0-20191030144301-2a5a0e75e5cf,h1:aAwV+RyellgKMACMu21Vyv/XgSHipLvbJsXDoXP1Yv0=,62570a621e1bf13724fb1f45d7ea95c48de02abb00468cf1da4b35820203d3b4
+contrib.go.opencensus.io/exporter/aws,v0.0.0-20181029163544-2befc13012d0,h1:YsbWYxDZkC7x2OxlsDEYvvEXZ3cBI3qBgUK5BqkZvRw=,3e351a39c3caf9ce263155f2d6e5a4e0cd84177661e1bf40f0d8fd06854831e9
+contrib.go.opencensus.io/exporter/ocagent,v0.6.0,h1:Z1n6UAyr0QwM284yUuh5Zd8JlvxUGAhFZcgMJkMPrGM=,e526ae16b06c682c3661738938f912a2e301a5e2d0ba875c7a0ec40fde825491
+contrib.go.opencensus.io/exporter/stackdriver,v0.12.8,h1:iXI5hr7pUwMx0IwMphpKz5Q3If/G5JiWFVZ5MPPxP9E=,db745d331f8a0455abbbcfeb4bb33dbc5cbb73a119b4e86f833cd497cfc72559
+contrib.go.opencensus.io/integrations/ocsql,v0.1.4,h1:kfg5Yyy1nYUrqzyfW5XX+dzMASky8IJXhtHe0KTYNS4=,0a4be97a579c5212bd83d21a177b279bc5b0c04350a63c56e8f8e611ffcba09c
+contrib.go.opencensus.io/resource,v0.1.1,h1:4r2CANuYhKGmYWP02+5E94rLRcS/YeD+KlxSrOsMxk0=,07ad3d36f96cb86ecba376353d02730855e117db3ffac5c2ab2c7cdf4eca25dc
+cuelang.org/go,v0.0.11,h1:t7s006dOWh6tgnwPifvO3l704eg8oPuIH7AR1hfTFYk=,69bdc6b3f1000308d399f166dd0d46576019f68cbf37765bd30821584b1296de
+dmitri.shuralyov.com/app/changes,v0.0.0-20180602232624-0a106ad413e3,h1:hJiie5Bf3QucGRa4ymsAUOxyhYwGEz1xrsVk0P8erlw=,a4d9079d5550094191f608c628ff2eb6999e0d0b6aea894ba59d063107777dfa
+dmitri.shuralyov.com/gpu/mtl,v0.0.0-20190408044501-666a987793e9,h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY=,ca5330901fcda83d09553ac362576d196c531157bc9c502e76b237cca262b400
+dmitri.shuralyov.com/html/belt,v0.0.0-20180602232347-f7d459c86be0,h1:SPOUaucgtVls75mg+X7CXigS71EnsfVUK/2CgVrwqgw=,bd6b059cceaea8ab23e65b8118fab5d22f82149417fcc5fcf930ef9a52d582f1
+dmitri.shuralyov.com/service/change,v0.0.0-20181023043359-a85b471d5412,h1:GvWw74lx5noHocd+f6HBMXK6DuggBB1dhVkuGZbv7qM=,8a1ba9c7ba7eea08389c15315a23485d19fc7166d30b5b47a35fab949c4bf886
+dmitri.shuralyov.com/state,v0.0.0-20190403024436-2cf192113e66,h1:/74W9PTF+vJhgRsWpPWlZT77+phX7vXPcelX7JXFu5s=,eda200c06f669f06c56e1d53a1879b88dd7ee99eea1f56d329028fa773cfc2dd
+docker.io/go-docker,v1.0.0,h1:VdXS/aNYQxyA9wdLD5z8Q8Ro688/hG8HzKxYVEVbE6s=,b162036b1af6e1e5434e2e5a35faa7191014529259fbf2f4f1b3e7de6b816516
+fyne.io/fyne,v1.1.2,h1:a9YLFXxqN7lKNqTrk+ocw3/3ROrn6aFiofix8ATVOBc=,dc2d7fd4a4ee9852328fc79c52459a53d94d26f6ac3282ebcacc0c6cd6688d23
+git.apache.org/thrift.git,v0.13.0,h1:/3bz5WZ+sqYArk7MBBBbDufMxKKOA56/6JO6psDpUDY=,10412b7bc503ef2a7cc3bf58fe69e5a2d2594354ae3cc5ab2baa2b3ecc8c4f1d
+git.fd.io/govpp.git,v0.1.0,h1:fV5H9ghURFfmNAjk7Scb/aG3OGwevLayHfSdS8GsYjE=,0a023d4b5b36131a4fde2c3d19047bbd4f5c3a7cc07c1ccf40bfb75a501f51b3
+git.torproject.org/pluggable-transports/goptlib.git,v1.1.0,h1:LMQAA8pAho+QtYrrVNimJQiINNEwcwuuD99vezD/PAo=,f6769c4813dedf933071289bfd9381aa5eb3a012b3a32d1da02aa9bebd3a3b5b
+gitee.com/nggs/util,v0.0.0-20190830024003-3e49d2efc84b,h1:6KQpPEs326uPrICQy9x/PxmR8U0v/XsFzpt0k1nFKcY=,a062c99c2b560a36168fe51eab8f17f4fadf5d534238881628e83d8d61e51c2a
+github.com/1and1/oneandone-cloudserver-sdk-go,v1.0.1,h1:RMTyvS5bjvSWiUcfqfr/E2pxHEMrALvU+E12n6biymg=,7f068808fc0857d7de8c8f829cc380dce1c6611a3fc819daf4421e9bcb75a07c
+github.com/99designs/gqlgen,v0.10.1,h1:1BgB6XKGTHq7uH4G1/PYyKe2Kz7/vw3AlvMZlD3TEEY=,04b9e7d8a3df6543cd870325b1140ce9ac3f4bbfd8c90ebecec4f908dd420d08
+github.com/AndreasBriese/bbloom,v0.0.0-20190306092124-e2d15f34fcf9,h1:HD8gA2tkByhMAwYaFAX9w2l7vxvBQ5NMoxDrkhqhtn4=,6d7c1af06f8597fde1e86166f26416057392f1b0bdb84f2af555aa461282dd18
+github.com/AsynkronIT/goconsole,v0.0.0-20160504192649-bfa12eebf716,h1:Pk/Kzi5O0T4QxfqvbaUsh8UklbJ9BklZ/ClZBptX5WU=,5a2507b89bb4436881718d785a0ef383652aa99782508b7444cf20255082dab9
+github.com/Azure/azure-amqp-common-go,v1.1.4,h1:DmPXxmLZwi/71CgRTZIKR6yiKEW3eC42S4gSBhfG7y0=,4b800793ff4fefa86a427c445e3a4671b8d1dcd87a44075f6309cace6b0e01e2
+github.com/Azure/azure-amqp-common-go/v2,v2.1.0,h1:+QbFgmWCnPzdaRMfsI0Yb6GrRdBj5jVL8N3EXuEUcBQ=,9a91c6ac9656faea0ddfb0bb497c109451faaba09b85ce3237309f5982b095a3
+github.com/Azure/azure-pipeline-go,v0.2.2,h1:6oiIS9yaG6XCCzhgAgKFfIWyo4LLCiDhZot6ltoThhY=,3e4f90f6ec86d4875e8758f01947adece11c1b4317b448fe0197188765c83efc
+github.com/Azure/azure-sdk-for-go,v36.0.0+incompatible,h1:XIaBmA4pgKqQ7jInQPaNJQ4pOHrdJjw9gYXhbyiChaU=,71db17c798b784b96a45efdbabd18ad86d03e5f490701081a2f7bf19efa67c13
+github.com/Azure/azure-service-bus-go,v0.9.1,h1:G1qBLQvHCFDv9pcpgwgFkspzvnGknJRR0PYJ9ytY/JA=,81e42ed51354d71b53daf93b5b9f0f2c20fb7d2923f45ab88eea22419bfbc63a
+github.com/Azure/azure-storage-blob-go,v0.8.0,h1:53qhf0Oxa0nOjgbDeeYPUeyiNmafAFEY95rZLK0Tj6o=,3b02b720c25bbb6cdaf77f45a29a21e374e087081dedfeac2700aed6147b4b35
+github.com/Azure/go-ansiterm,v0.0.0-20170929234023-d6e3b3328b78,h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=,b7a14d18891abef8b8a2e622f62a3cebeac32f9f1223dc9d62a6f8769861aaf2
+github.com/Azure/go-autorest,v13.3.0+incompatible,h1:8Ix0VdeOllBx9jEcZ2Wb1uqWUpE1awmJiaHztwaJCPk=,44fdf420bd96bb97df7910806efb25f2fae701078c39f5592f5c4131ffce41e6
+github.com/Azure/go-autorest/autorest,v0.9.2,h1:6AWuh3uWrsZJcNoCHrCF/+g4aKPCU39kaMO6/qrnK/4=,26df5fc6c03e8c66021dd272b04242f6c2ce2a5975f87799dfcf1b9597800dba
+github.com/Azure/go-autorest/autorest/adal,v0.8.0,h1:CxTzQrySOxDnKpLjFJeZAS5Qrv/qFPkgLjx5bOAi//I=,af59c00ec7e19cda9b960babaee7bfe27cf3d5f7415ac3afdb4cddc73d4b5743
+github.com/Azure/go-autorest/autorest/azure/auth,v0.4.0,h1:18ld/uw9Rr7VkNie7a7RMAcFIWrJdlUL59TWGfcu530=,2fe394de946f42c2ea8ad07f1b282eac6bb56e372f5c2a35e49dfef0cf015ccb
+github.com/Azure/go-autorest/autorest/azure/cli,v0.3.0,h1:5PAqnv+CSTwW9mlZWZAizmzrazFWEgZykEZXpr2hDtY=,729d09b69a1912faa7c2395389bbf67ec22a420d42c15414823d43a380a2f09a
+github.com/Azure/go-autorest/autorest/date,v0.2.0,h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM=,9ec7b48c865a185b72d3822ac2dff7e0163315a23911c87a479a3db616af9853
+github.com/Azure/go-autorest/autorest/mocks,v0.3.0,h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc=,d5daf74cf531c37b27b39d3bf65b6930aee4b226b5fb4ea91a87be93aaf37f10
+github.com/Azure/go-autorest/autorest/to,v0.3.0,h1:zebkZaadz7+wIQYgC7GXaz3Wb28yKYfVkkBKwc38VF8=,955ee6bde8af1314d22b51f265799147f42f7c705714b1cc1c51144441d5fa9c
+github.com/Azure/go-autorest/autorest/validation,v0.2.0,h1:15vMO4y76dehZSq7pAaOLQxC6dZYsSrj2GQpflyM/L4=,10f40b0d943d4d1a0a1cbcb9fdb058b8a3a59a55ae26583566dfaa82883f86ea
+github.com/Azure/go-autorest/logger,v0.1.0,h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=,5e0804944db0707502c9d29defb54961c281a19311c9eb321a246ba054ac5256
+github.com/Azure/go-autorest/tracing,v0.5.0,h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k=,4951b0f4a88a44b7ed4e4834654e4e01922ade35d97899b8596998184abbc652
+github.com/Azure/go-ntlmssp,v0.0.0-20180810175552-4a21cbd618b4,h1:pSm8mp0T2OH2CPmPDPtwHPr3VAQaOwVF/JbllOPP4xA=,64cd585589154ce18d7557ccfd8d26e2c2f5c4ecf13b17bdbfb913e17863d280
+github.com/BurntSushi/locker,v0.0.0-20171006230638-a6e239ea1c69,h1:+tu3HOoMXB7RXEINRVIpxJCT+KdYiI7LAEAUrOw3dIU=,836038343df9e9126b59d54201951191898bd875ec32d93c2018d759f358fcfb
+github.com/BurntSushi/toml,v0.3.1,h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=,815c6e594745f2d8842ff9a4b0569c6695e6cdfd5e07e5b3d98d06b72ca41e3c
+github.com/BurntSushi/xgb,v0.0.0-20160522181843-27f122750802,h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=,f52962c7fbeca81ea8a777d1f8b1f1d25803dc437fbb490f253344232884328e
+github.com/BurntSushi/xgbutil,v0.0.0-20190907113008-ad855c713046,h1:O/r2Sj+8QcMF7V5IcmiE2sMFV2q3J47BEirxbXJAdzA=,492ce6b11d7faaec4e15d1279d81e28d2e0e9844ad117f9de9411286a5b0e305
+github.com/ChrisTrenkamp/goxpath,v0.0.0-20170922090931-c385f95c6022,h1:y8Gs8CzNfDF5AZvjr+5UyGQvQEBL7pwo+v+wX6q9JI8=,8d79cd78a309a1b0f22790d354b9c4c929c64d03c7e572627ba430908fbb9d78
+github.com/CodisLabs/codis,v0.0.0-20181104082235-de1ad026e329,h1:KyRmPlfd2xewxb54vIBPNILFyCh2R3zNDwLZURDxT0E=,f61ae85688d10dddf0d62c30aaaa2701373fc11851dae4435de0212513c578c1
+github.com/DATA-DOG/go-sqlmock,v1.3.3,h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=,5dc430c2836af3bfc85f590366a6e284a251978e9397d0d54fa97db913263461
+github.com/DataDog/datadog-go,v3.2.0+incompatible,h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4=,ede4a024d3c106b2f57ca04d7bfc7610e0c83f4d8a3bace2cf87b42fd5cf66cd
+github.com/DataDog/zstd,v1.4.0,h1:vhoV+DUHnRZdKW1i5UMjAk2G4JY8wN4ayRfYDNdEhwo=,601f6fe1f4138d676946f4b27f7a714bbedea8c1785d10c1b74a03c68ad13070
+github.com/FiloSottile/b2,v0.0.0-20170207175032-b197f7a2c317,h1:1GuMjC4tjfwnWBdoTS7YqtQ3JIsEft6NRcdmXdzvYYc=,6ff3cfed3f510fc69b47f263936642950afc7892f557ed716dd8c5584f187411
+github.com/GeertJohan/go-sourcepath,v0.0.0-20150925135350-83e8b8723a9b,h1:D4H5C4VvURnduTQydyEhA6OWnNcZTLUlNX4YBw5yelY=,8bdcf0b6cc58f5ec1cef031b4052e6d699683bf1daf4a1a20f92f67d5be06b82
+github.com/GeertJohan/go.incremental,v1.0.0,h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg=,ce46b3b717f8d2927046bcfb99c6f490b1b547a681e6b23240ac2c2292a891e8
+github.com/GeertJohan/go.rice,v1.0.0,h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ=,2fc48b9422bf356c18ed3fe32ec52f6a8b87ac168f83d2eed249afaebcc3eeb8
+github.com/GoogleCloudPlatform/cloudsql-proxy,v0.0.0-20191017031552-46c5533ff5ba,h1:ZNYxMf89tMi+NydPAq7yGAxMfMNaMHgG+7WL1CEabjc=,25a1fe9f189e6a4d6e108f22abaec7dd36edc819ab5af1a3e448450b73026271
+github.com/GoogleCloudPlatform/docker-credential-gcr,v1.5.0,h1:wykTgKwhVr2t2qs+xI020s6W5dt614QqCHV+7W9dg64=,4acfcaddfe2aa53e1e643ea13ff3534a2fca1e043d008ab5bba5a0910db1f7c2
+github.com/IBM/go-sdk-core,v1.0.1,h1:vF9Lsoih6fxrAxzJp2fWqnO6Mg8x8O8fzwQAdFoUdok=,e063c8f79f94936a165355f61bdc6f2c404975472ad6be5e47bfdb87fb393c72
+github.com/Jeffail/gabs,v1.4.0,h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo=,cb193b1477109c19b0d2521fc61735619202e58ac4699605f72313d70884ca9e
+github.com/Joker/hpp,v0.0.0-20180418125244-6893e659854a,h1:PiDAizhfJbwZMISZ1Itx1ZTFeOFCml89Ofmz3V8rhoU=,4e99372a7576c587c107fb16d1ae0e8662111e2ca5e5127f7cd93bb01cd02076
+github.com/Joker/jade,v1.0.0,h1:lOCEPvTAtWfLpSZYMOv/g44MGQFAolbKh2khHHGu0Kc=,c4a7f39e7483446ff7b0d7e213a4cd813c783108d6d2e7c6e9a8e968789b18bc
+github.com/Knetic/govaluate,v3.0.1-0.20171022003610-9aa49832a739+incompatible,h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=,d1d4ac5b4f5759726368f68b0d47f3c17c6d8689243ec66272311359d28a865b
+github.com/Kodeworks/golang-image-ico,v0.0.0-20141118225523-73f0f4cfade9,h1:1ltqoej5GtaWF8jaiA49HwsZD459jqm9YFz9ZtMFpQA=,1d677069e35c4a3e4f290e68c6e2391f6237aee9ce3f39448ed09a2ddab274b0
+github.com/Kubuxu/go-os-helper,v0.0.1,h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk=,90a16f95a8a238910ab0dc9004cb6e56242a10810bf1e296a263d2e385f002e0
+github.com/KyleBanks/depth,v1.2.1,h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=,8f3e9af2e038f561d9c34b631fddc7db39e39992a121fd087f0bf980026464d9
+github.com/MakeNowJust/heredoc,v1.0.0,h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=,062afe6e11aa3c3ac0035d08907b80d5e5b7563905603391ee774bda440abf16
+github.com/Masterminds/goutils,v1.1.0,h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=,b9520e8d2775ac1ff3fbf18c93dbc4b921133f957ae274f5b047965e9359d27d
+github.com/Masterminds/semver,v1.5.0,h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=,15f6b54a695c15ffb205d5719e5ed50fab9ba9a739e1b4bdf3a0a319f51a7202
+github.com/Masterminds/semver/v3,v3.0.1,h1:2kKm5lb7dKVrt5TYUiAavE6oFc1cFT0057UVGT+JqLk=,f1eef1a1b6489d895eb32326f3369bd1615812a4c5fbfe60b2b6cc774c6340f0
+github.com/Masterminds/sprig,v2.22.0+incompatible,h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=,1b4d772334cc94e5703291b5f0fe4ac4965ac265424b1060baf18ef5ff9d845c
+github.com/Masterminds/squirrel,v1.1.0,h1:baP1qLdoQCeTw3ifCdOq2dkYc6vGcmRdaociKLbEJXs=,cede1b0a054e000a5e6a8000cb02de7ab64ddca9e0f4153732274627adeed0ae
+github.com/Microsoft/go-winio,v0.4.14,h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=,7a86644691d3c86c77ae0b639fa27029706552f00cd51b445389a61694576f6b
+github.com/Microsoft/hcsshim,v0.8.6,h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=,900feaaec1c41d4e111a66bbde330b41fc78902c70c0af37d611505bf42e0632
+github.com/NYTimes/gziphandler,v1.1.1,h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=,2948d9f70e4388f13f4ed9400df41dca60841059f7dcc30cf909c82796cc705a
+github.com/NaverCloudPlatform/ncloud-sdk-go,v0.0.0-20180110055012-c2e73f942591,h1:/P9HCl71+Eh6vDbKNyRu+rpIIR70UCZWNOGexVV3e6k=,2e9eacfe3e6785beef75391bcebc14a6a082687c0f0582bc441c3d0106b8bf5c
+github.com/NebulousLabs/entropy-mnemonics,v0.0.0-20181203154559-bc7e13c5ccd8,h1:wPFCU8DwC4k5C2LfJc/rVp4cmTqzF3vyydxRR3b3HhQ=,6a65ca779cd216db7bf326ebbb5a26a87d85ff6a6ba832eec281c5c09a8294e3
+github.com/Netflix/go-expect,v0.0.0-20180615182759-c93bf25de8e8,h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=,fbe7b2f58ecb0e1067a6670bbcf0718d54ec407aab81790cc9e58db9a6774775
+github.com/NickBall/go-aes-key-wrap,v0.0.0-20170929221519-1c3aa3e4dfc5,h1:5BIUS5hwyLM298mOf8e8TEgD3cCYqc86uaJdQCYZo/o=,fd78212ec77052b032b9fc308c028e8fc166de3d6ae4494f5eb3254930728a0b
+github.com/Nvveen/Gotty,v0.0.0-20120604004816-cd527374f1e5,h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=,362ac7b59d74231419471b65b60079d167785b97fd4aa0de71575088cd192b1e
+github.com/OneOfOne/xxhash,v1.2.5,h1:zl/OfRA6nftbBK9qTohYBJ5xvw6C/oNKizR7cZGl3cI=,7ab3c6a0e7c16c987a589e50a9a353e8877cfffea02bf9e04e370fd26a0c85e1
+github.com/OpenBazaar/jsonpb,v0.0.0-20171123000858-37d32ddf4eef,h1:+aqKrHtCJTRp8ziyrjfHbTF5puPQZfgRt65+iM7FD2w=,5f6ea1466b9d27f016c1bf2650669c788db623142cdc8a1794bc1784fc80fc4e
+github.com/OpenBazaar/wallet-interface,v0.0.0-20190807004547-aa8e214acd9b,h1:KjQH45msWRtDhb5JAbBW+eU4M/9xIm11rsOSgAaqDOs=,f7ac40d665241766533b1a49a726068d9dfea5e02c7fd426df81f9e390a7003e
+github.com/OpenDNS/vegadns2client,v0.0.0-20180418235048-a3fa4a771d87,h1:xPMsUicZ3iosVPSIP7bW5EcGUzjiiMl1OYTe14y/R24=,b73d6b37d519c7bf181e502b92962f1bf961bb0ca3a9ef7057c3d9a8a3c2f3cd
+github.com/OwnLocal/goes,v1.0.0,h1:81QQ3z6dvLhgXlkNpLkaYhk8jiKS7saFG01xy039KaU=,ebb6c7e2c12577c590d2d5546b7a4b4e6fa75c9a408ae5244b5ba2cf09dec1d6
+github.com/PuerkitoBio/goquery,v1.5.0,h1:uGvmFXOA73IKluu/F84Xd1tt/z07GYm8X49XKHP7EJk=,f0064ad35f21c2b9d1377b94f09ead56ec1862da3807e78c26b99c4b3a04f5e6
+github.com/PuerkitoBio/purell,v1.1.1,h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=,59e636760d7f2ab41c2f80c1784b1c73d381d44888d1999228dedd634ddcf5ed
+github.com/PuerkitoBio/urlesc,v0.0.0-20170810143723-de5bf2ad4578,h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=,1793124273dd94e7089e95716d40529bcf70b9e87162d60218f68dde4d6aeb9d
+github.com/Quasilyte/inltest,v0.7.0,h1:yHvFAaoXn+6iK2uKtb8mXB9KURz6SDPyszoyBAC0Xk4=,8fb4273cea3514742aec06ed58f20cea1214cc542799c70c331a80865aaf3988
+github.com/RangelReale/osin,v1.0.1,h1:JcqBe8ljQq9WQJPtioXGxBWyIcfuVMw0BX6yJ9E4HKw=,edbcc6208879bffa533369bbf417db41c1322193ca05d0deecf13075972c9d57
+github.com/RangelReale/osincli,v0.0.0-20160924135400-fababb0555f2,h1:x8Brv0YNEe6jY3V/hQglIG2nd8g5E2Zj5ubGKkPQctQ=,82fc65bad3da9fc26cc77b485e10ee117459e830547ce89592c41d92871e1129
+github.com/Rican7/retry,v0.1.0,h1:FqK94z34ly8Baa6K+G8Mmza9rYWTKOJk+yckIBB5qVk=,c0e956967f2f632ffc889eeae5b82e437f30e9be409870cdd1e7998def458843
+github.com/RoaringBitmap/roaring,v0.4.7,h1:eGUudvFzvF7Kxh7JjYvXfI1f7l22/2duFby7r5+d4oc=,515892d9b8e4350e5ac5b7a487da94d5d9ab9641071e002b778dd864b7a31c2a
+github.com/SAP/go-hdb,v0.14.1,h1:hkw4ozGZ/i4eak7ZuGkY5e0hxiXFdNUBNhr4AvZVNFE=,273de28a254c39e9f24293b864c1d664488e4a5d44d535755a5e5b68ae7eed8d
+github.com/Sereal/Sereal,v0.0.0-20190529075751-4d99287c2c28,h1:kmfzzWpCZIrVhxx4V/2oSGhGnhtX+/JijVIlPuKYfHg=,eebfe79e62b5a07f98a367d8a84bcf33ed69818c031e70c3ebc6e9fc34361466
+github.com/SermoDigital/jose,v0.0.0-20180104203859-803625baeddc,h1:LkkwnbY+S8WmwkWq1SVyRWMH9nYWO1P5XN3OD1tts/w=,1711f20ec5b1498c98e46b96e578f39b723557ab50183d644702d40f44a1a345
+github.com/Shopify/go-lua,v0.0.0-20181106184032-48449c60c0a9,h1:+2M9NEk3+xSg0+bWzt1kxsL6EtoEg7sgtT11CZjGwq8=,3e399584ff4a876314243c01be3cba5b98b46bba483d6996dd2d0e7f161b7ad8
+github.com/Shopify/goreferrer,v0.0.0-20181106222321-ec9c9a553398,h1:WDC6ySpJzbxGWFh4aMxFFC28wwGp5pEuoTtvA4q/qQ4=,e47cdf750e6aa39707b90e62f4f87e97abb8d64b2525a16c021c82efb24f9969
+github.com/Shopify/sarama,v1.24.1,h1:svn9vfN3R1Hz21WR2Gj0VW9ehaDGkiOS+VqlIcZOkMI=,c5e06f9c835846eeb5cbbbc540ab949f9775ff37c08cab503dd820b858b1f2e7
+github.com/Shopify/toxiproxy,v2.1.4+incompatible,h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=,9427e70698ee6a906904dfa0652624f640619acef40652a1e5490e13b31e7f61
+github.com/Sirupsen/logrus,v1.0.6,h1:HCAGQRk48dRVPA5Y+Yh0qdCSTzPOyU1tBJ7Q9YzotII=,dc69c77019152ace477a7f5c0cd97fd25d6ab866e01e1dd06f391722f4f9fba9
+github.com/StackExchange/wmi,v0.0.0-20190523213315-cbe66965904d,h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=,68f499ad4c3f45fc6c286fd2a5966e8e15c0f3abc1f96fbf4a979245df936e16
+github.com/Stebalien/go-bitfield,v0.0.1,h1:X3kbSSPUaJK60wV2hjOPZwmpljr6VGCqdq4cBLhbQBo=,9b17a2749922c810f3598606b87b5f2ba0f3c6abc70966911a8c32f0533ee827
+github.com/Telmate/proxmox-api-go,v0.0.0-20190815172943-ef9222844e60,h1:iEmbIRk4brAP3wevhCr5MGAqxHUbbIDHvE+6D1/7pRA=,55dd16e2cd8e6c1464c6456007cdc5d8676b8b096e90230312daa8c84b57b34d
+github.com/TheThingsNetwork/api,v0.0.0-20190522113053-d844e8c040fc,h1:hDk+SAT2tV584ye1hqMN5+NHL6RHJDIbe97cNot6/WQ=,7931f7c4699cd1019c950a68361e3b3fec8bbb8e9204c65c08b50bd588ac506a
+github.com/TheThingsNetwork/go-account-lib,v2.0.3+incompatible,h1:pnDIalIqac/VlXenPr+L1XEEf3gIq1eIoZ78S5AP1/s=,e62dcb784cbd28bcec55cf332f7dc06779c75c7df66299f4ce542cd6852358b4
+github.com/TheThingsNetwork/go-cayenne-lib,v1.0.0,h1:be7h6E/69+qaYs1iwQ2xjGjSFPXzvU3q6AWBCWayG2Y=,17091b77ac39b8e73ca6ac3f39f34909bc6a3770098ff2dd534b59a10f6e66ad
+github.com/TheThingsNetwork/go-utils,v0.0.0-20190813113035-8715cf82e887,h1:DF/1gkOPk3jtwWa9dFd5tUtwb6z3bLw9tZ/UALbS5Ck=,be4c7c2955630b63300f21773efcdc991d5ff201a53b01d92b2f20fede77065c
+github.com/TheThingsNetwork/ttn,v2.10.1+incompatible,h1:LQw+g+kinajii5DHJ6I2o82ObaU/Ws+YYgdLkF5eF54=,4a803fe23636f9c99926e6b5a2b956fb42e84ca38c98458a12bd7fe1c22f7439
+github.com/TheThingsNetwork/ttn/api,v0.0.0-20190516081709-034d40b328bd,h1:vCjDYImJDdW+39EXwij00yzDi1pd3TmP6XtCteDJBd0=,9cda2f899f15f57e8f649bbffb955a8153d6c25a13a4e969df8898bb61559a44
+github.com/TheThingsNetwork/ttn/core/types,v0.0.0-20191015060859-00a6f7874bb9,h1:tlWwCxI3/Zu4vJ4dLWb2wMOYSkeMBvLAxQGwJDCFXi8=,7b3895805d6ac341e5df44c2c8154b374b4bed4c8f54e248ea967abfc37186e7
+github.com/TheThingsNetwork/ttn/utils/errors,v0.0.0-20190516081709-034d40b328bd,h1:ITXOJpmUR4Jhp3Xb/xNUIJH4WR0h2/NsxZkSDzFIFiU=,d64decf456c10fdbbb887212ea63749b495264c40bb5ac047b9f0e5ccd7e540b
+github.com/TheThingsNetwork/ttn/utils/random,v0.0.0-20190516081709-034d40b328bd,h1:zKTRK1r3K55XxHuUGxnqYg9aiPDduYeilHUEHua+F+Y=,c504030254919a902b3957267b7ce1870f909cbdd65f0f927819f60710e41d9b
+github.com/TheThingsNetwork/ttn/utils/security,v0.0.0-20190516081709-034d40b328bd,h1:og10Wq5S/QC+f4ziON4vrxlYKv9gfEKxG8v/MDs00xw=,e6f013adee3a7a212a6f892db59c8efaf715fe49413e6dbca22229fa04f0d006
+github.com/Unknwon/cae,v0.0.0-20160715032808-c6aac99ea2ca,h1:xU8R31tsvj6TesCBog973+UgI3TXjh/LqN5clki6hcc=,15a1394a603423c5bcd4659275be09d7696774990d5f127500f4156c1a78eb85
+github.com/Unknwon/com,v0.0.0-20190321035513-0fed4efef755,h1:1B7wb36fHLSwZfHg6ngZhhtIEHQjiC5H4p7qQGBEffg=,2cfba36da8f59c6dd8c7a20af59e5ccf9558f42bde7e0918a64a9b68dafcf271
+github.com/Unknwon/i18n,v0.0.0-20171114194641-b64d33658966,h1:Mp8GNJ/tdTZIEdLdZfykEJaL3mTyEYrSzYNcdoQKpJk=,a5ce1436582e797d60e967d853fd22458fc7edeb31bd390d6ace979133bedb78
+github.com/Unknwon/paginater,v0.0.0-20170405233947-45e5d631308e,h1:HnbTtNLKnRmwn85vBmyl7nNJCXUw4rh6X3UeIX5nvko=,60e3af4ba9b482892127f829ec7cc837977ca9e9e634be855d599cc08230e606
+github.com/VividCortex/ewma,v1.1.1,h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=,eebee7c0f20e96abbda1611ed2a3d26b4c2c10393caa6a2dfd1605763a5c1a12
+github.com/VividCortex/gohistogram,v1.0.0,h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=,16ebeceeb7e4066f90edbfb90282cd90d4dad0f71339199551de3fbdc7e8c545
+github.com/Workiva/go-datastructures,v1.0.50,h1:slDmfW6KCHcC7U+LP3DDBbm4fqTwZGn1beOFPfGaLvo=,1ac8c9334b63ee2b089b7ecc3b6c8d45793cc4ef4c460f6ebbfd6ecea3ee83bc
+github.com/a8m/mark,v0.1.1-0.20170507133748-44f2db618845,h1:hIjQrEARcc9LcH8igte3JBpWBZ7+SpinU70dOjU/afo=,048bfeb7427ff5622874d874a52d7215a2cea99f9741c031e9963348785103c2
+github.com/abbot/go-http-auth,v0.4.0,h1:QjmvZ5gSC7jm3Zg54DqWE/T5m1t2AfDu6QlXJT0EVT0=,8204bca24734f55f179dd1c0b820ae5be83151268693a147086f33cd2d4d473c
+github.com/abdullin/seq,v0.0.0-20160510034733-d5467c17e7af,h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14=,bcbe9a2c1e3ac0b981ee436cd1bbb2da8220527511b3cea6517a28a881636814
+github.com/abronan/valkeyrie,v0.0.0-20191010124425-1ae9442de16e,h1:4SrbWyef51DHDc957/8Ms/fDM4D+3bkbXqg6OTnIEAo=,553dce6f5ff57f7ccc5ed6a94e6bf29b38b8773236f3b85bb4025dc0d10d2a92
+github.com/aead/siphash,v1.0.1,h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg=,25da04ff418e0b2871b1193a3478977b4aa66c20737b9ca70a5040b876b6d3d9
+github.com/aerogo/http,v1.0.12,h1:1o5QW6TQLNuutQLuPCX0Tn7g/sSH3JMHv79UGIBpvkw=,a58d344ff2010737d2418050f4188339087cfb369c903bd31e20ccba388304a1
+github.com/afex/hystrix-go,v0.0.0-20180502004556-fa1af6a1f4f5,h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw=,c0e0ea63b57e95784eeeb18ab8988ac2c3d3a17dc729d557c963f391f372301c
+github.com/agext/levenshtein,v1.2.2,h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE=,07caaae8fcdb7c83195a0afffc03c9df76275b1e9a7b69dabfe0d2f47729bc7c
+github.com/agl/ed25519,v0.0.0-20170116200512-5312a6153412,h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI=,98c1510ac20b7d61bf4e2c76e7184fcbd0a8b78b0fc667c2b772777912963d3f
+github.com/agnivade/levenshtein,v1.0.1,h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ=,cb0e7f070ba2b6a10e1c600d71f06508404801ff45046853001b83be6ebedac3
+github.com/ajg/form,v1.5.1,h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=,b063b07639670ce9b6a0065b4dc35ef9e4cebc0c601be27f5494a3e6a87eb78b
+github.com/ajstarks/svgo,v0.0.0-20190826172357-de52242f3d65,h1:kZegOsPGxfV9mM8WzfllNZOx3MvM5zItmhQlvITKVvA=,1459a44f9162f463b59eacf58e4bb8873e612c5b3df45fc6e34074310d2269ae
+github.com/akamai/AkamaiOPEN-edgegrid-golang,v0.9.0,h1:rXPPPxDA4GCPN0YWwyVHMzcxVpVg8gai2uGhJ3VqOSs=,91c3a4743d959b3bb2bb7359790df4688021830e482d393ea6d4f3a27aebd63d
+github.com/akavel/rsrc,v0.8.0,h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=,13954a09edc3a680d633c5ea7b4be902df3a70ca1720b349faadca44dc0c7ecc
+github.com/akyoto/assert,v0.2.3,h1:ftENRGDEK5AKuKmZb9LtbDIHeE8p8cIYI4M92CbA9nE=,f0a31d5859109c37568b8702fcf92cd3a49ec4892dace74d113df5fd49491975
+github.com/akyoto/color,v1.8.11,h1:uCQi+uRyngo1cJhJSv28PQmduGFiOAGNF6F9MFoRDek=,0fa16c51743ca03e108fde20eabb070d17d25111cb287e15f8567268d439098a
+github.com/akyoto/colorable,v0.1.7,h1:ge91E25hiOiT/Zu47ij/rTO3cks7wMlTrcQspua1hFM=,07c2dd4d994d9ff1dad97ad2e2650ff60d90f50ecd52380f357e562efda99613
+github.com/akyoto/stringutils,v0.2.6,h1:IP+7jtH8uofpan8MYlV/WMNaLDGBRbzgiTKYnxcAwkw=,802a3b54f91b930c1e8f2376bebf783b16894da626fc7c8064268b07ab567f7c
+github.com/akyoto/tty,v0.1.3,h1:AdnLETzgooimWLvoBQLn5bT1j+i0yiB4E596BfFKnmA=,749381ec9dce8bc96bec66c5dfb0874db917a008f9685d9c65c15da43ede964c
+github.com/alcortesm/tgz,v0.0.0-20161220082320-9c5fe88206d7,h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=,ccedffb2c46724216b787fb1a79ae33fb0dfdd672c669db000c4ed5a68b08014
+github.com/alecthomas/assert,v0.0.0-20170929043011-405dbfeb8e38,h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=,873d257170b1363142cbf5e16b49c6a21cccb3e4aaceb9d370c3b78b051a5663
+github.com/alecthomas/chroma,v0.6.8,h1:TW4JJaIdbAbMyUtGEd6BukFlOKYvVQz3vVhLBEUNwMU=,ebc5202e6a0ededc5a2c7396b01b76c050331bead9d047f31fe648cb63e68aa3
+github.com/alecthomas/colour,v0.0.0-20160524082231-60882d9e2721,h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=,334101c562d2e74338f6baab1de04f3bbff89021d24f4206c551ef47b96a2bfe
+github.com/alecthomas/kingpin,v2.2.6+incompatible,h1:5svnBTFgJjZvGKyYBtMB0+m5wvrbUHiqye8wRJMlnYI=,a88daee47262ffeca1f6e348399c16c9be160f3c5e972c0b6c9dc275d85bcdc6
+github.com/alecthomas/kong,v0.2.1-0.20190708041108-0548c6b1afae,h1:C4Q9m+oXOxcSWwYk9XzzafY2xAVAaeubZbUHJkw3PlY=,4292d9b6903d67f060d3bd57ffca0a4ebca359824ce2d32a512ac1b963fa3dc0
+github.com/alecthomas/kong-hcl,v0.1.8-0.20190615233001-b21fea9723c8,h1:atLL+K8Hg0e8863K2X+k7qu+xz3M2a/mWFIACAPf55M=,21a34d6ee62e3419601d0e083b8829001a9833899dd3c2d27a82c794426fd0ee
+github.com/alecthomas/log4go,v0.0.0-20180109082532-d146e6b86faa,h1:0zdYOLyuQ3TWIgWNgEH+LnmZNMmkO1ze3wriQt093Mk=,04bdaa7d57a681072316927175c21ca7c9e7a19bd7fee2102b5f40e5b01a7559
+github.com/alecthomas/repr,v0.0.0-20181024024818-d37bc2a10ba1,h1:GDQdwm/gAcJcLAKQQZGOJ4knlw+7rfEQQcmwTbt4p5E=,c01a833ec56f68113f6cd7ed82b7da9bfaec641a10e929e0e3e5e5dadb1a85ad
+github.com/alecthomas/template,v0.0.0-20190718012654-fb15b899a751,h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=,25e3be7192932d130d0af31ce5bcddae887647ba4afcfb32009c3b9b79dbbdb3
+github.com/alecthomas/units,v0.0.0-20190924025748-f65c72e2690d,h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=,e6b0ccb38bfba85d90092d1c57671d5f7996757bd71f6f1970c6ae2f9dae3f6e
+github.com/alicebob/gopher-json,v0.0.0-20180125190556-5a6b3ba71ee6,h1:45bxf7AZMwWcqkLzDAQugVEwedisr5nRJ1r+7LYnv0U=,2374b534198621157afb9466a52d361b6eed33dcf9bb0674019515e64b16129e
+github.com/alicebob/miniredis,v0.0.0-20180911162847-3657542c8629,h1:gLoh8jzwIxdisBnHiWRIuReqtH9cpslSE2564UWXun0=,14b5e988ec6d8357a25ba19a7adbdb34920f5f91401b2b26eb25f04fed9893b0
+github.com/aliyun/alibaba-cloud-sdk-go,v0.0.0-20191031111935-12810c79403d,h1:CmGtZPPsr0C31ZBrzdP+D2oczTbyEBbO3bYg6z5EIDY=,4f0f25f45d954ab970b24783e31b716b619b128081acc9ed7b00727cd7c2d536
+github.com/aliyun/aliyun-oss-go-sdk,v2.0.3+incompatible,h1:724q2AmQ3m1mrdD9kYqK5+1+Zr77vS21jdQ9iF9t4b8=,47ede6a440ad4bb1a1c33d71bd12f76f44aa2487f676b8770152130be3021657
+github.com/aliyun/aliyun-tablestore-go-sdk,v4.1.2+incompatible,h1:ABQ7FF+IxSFHDMOTtjCfmMDMHiCq6EsAoCV/9sFinaM=,82c8ced9cd377462c6ea5070258f97c77ffddd66621e8960b08184eb58416846
+github.com/allegro/bigcache,v1.2.1,h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc=,9250edab8c7851cfa0c6c173e721cf70831e90742a7485c2eba1d6e2cc8c71eb
+github.com/anacrolix/envpprof,v1.1.0,h1:hz8QWMN1fA01YNQsUtVvl9hBXQWWMxSnHHoOK9IdrNY=,97f2340bcb169956bad97c59fdc17bbd2eb7c0acefe4e2ae327c7d6bd5a5f6cf
+github.com/anacrolix/log,v0.3.0,h1:Btxh7GkT4JYWvWJ1uKOwgobf+7q/1eFQaDdCUXCtssw=,e8bc14381d8746426c7e272228780047e0594d695d02e188269f1e86ef1644d4
+github.com/anacrolix/missinggo,v1.2.1,h1:0IE3TqX5y5D0IxeMwTyIgqdDew4QrzcXaaEnJQyjHvw=,2fb8cba1f6eaf69989ca5c522c2d4afd6c1071ad9459f940b6058dbfc2f3b285
+github.com/anacrolix/missinggo/perf,v1.0.0,h1:7ZOGYziGEBytW49+KmYGTaNfnwUqP1HBsy6BqESAJVw=,f4271e6359cf3dd5cba81bcf1436e8abc5d0c96c11820b881544708caa131713
+github.com/anacrolix/sync,v0.0.0-20180808010631-44578de4e778,h1:XpCDEixzXOB8yaTW/4YBzKrJdMcFI0DzpPTYNv75wzk=,bef95f54e1b17e4e7666cbf552e541e670f29fc3fd354aba0ebeee73f744ea24
+github.com/anacrolix/tagflag,v1.0.1,h1:Yd3d5DaKbRA70k7CoFuBsbmfSWIsvtZ9t80xW/x4vQY=,8fc0a5b5607cde223bacd9e4fa3b26f6166c09a09bfabe2c2c803e45e17971fa
+github.com/anacrolix/utp,v0.0.0-20180219060659-9e0e1d1d0572,h1:kpt6TQTVi6gognY+svubHfxxpq0DLU9AfTQyZVc3UOc=,35c47428844d10f077225195f9a6c7587c671b7fc70bbaf59ef74cd6d8834e32
+github.com/andreyvit/diff,v0.0.0-20170406064948-c7f18ee00883,h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=,d39614ff930006640ec15865bca0bb6bf8e1ed145bccf30bab08b88c1d90f670
+github.com/andybalholm/cascadia,v1.0.0,h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o=,7fd82e560ca1a453974a64c9bf6514b17322d1b7392bad730a5006d929996906
+github.com/andygrunwald/go-jira,v1.5.0,h1:/1CyYLNdwus7TvB/DHyD3udb52K12aYL9m7WaGAO9m4=,3ee973941f400bf95005cada54e09e319cb4943cd6c8d66480243d3b40895821
+github.com/anmitsu/go-shlex,v0.0.0-20161002113705-648efa622239,h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=,3b8376ff631f30d47e0348a8f847050b97c3db89483f45d1cd8f11d23c7c56a2
+github.com/antchfx/htmlquery,v1.0.0,h1:O5IXz8fZF3B3MW+B33MZWbTHBlYmcfw0BAxgErHuaMA=,81c86507bf2a226d5a3d20db547503d490f1e3b77035f267056e80cd73e240e2
+github.com/antchfx/xmlquery,v1.0.0,h1:YuEPqexGG2opZKNc9JU3Zw6zFXwC47wNcy6/F8oKsrM=,969fc21438fe076aee032574578158ac7e030979153dcf7b5ff5c133cbfa4d86
+github.com/antchfx/xpath,v0.0.0-20190129040759-c8489ed3251e,h1:ptBAamGVd6CfRsUtyHD+goy2JGhv1QC32v3gqM8mYAM=,22cb767dc0cafecba39e1b0322cc8aebbc6fd912e4b0fcda8c2c1dde2d80c4d2
+github.com/antchfx/xquery,v0.0.0-20180515051857-ad5b8c7a47b0,h1:JaCC8jz0zdMLk2m+qCCVLLLM/PL93p84w4pK3aJWj60=,9ddc9d830f2d6c7a22604035f0c621228ffa4ed6ff1f1d34655ee477c203c899
+github.com/antihax/optional,v0.0.0-20180407024304-ca021399b1a6,h1:uZuxRZCz65cG1o6K/xUqImNcYKtmk9ylqaH0itMSvzA=,7b0a2bf3eb029d9abe761db1874a501b60f267e675d72ae8c4b8c6f406ddcfd0
+github.com/apache/arrow/go/arrow,v0.0.0-20191024131854-af6fa24be0db,h1:nxAtV4VajJDhKysp2kdcJZsq8Ss1xSA0vZTkVHHJd0E=,4bd8443c24bc06843c0270df4f08f98b3eee6116604ff16d14dce34b242783cf
+github.com/apache/thrift,v0.13.0,h1:5hryIiq9gtn+MiLVn0wP37kb/uTeRZgN08WoCsAhIhI=,d75265e363da943c24e7ed69104bf018429024a50968421e48a6ab3e624733c2
+github.com/apex/log,v1.1.1,h1:BwhRZ0qbjYtTob0I+2M+smavV0kOC8XgcnGZcyL9liA=,5bb0f19e5c68b104ed32a311ea9c6f6e2a5e8fa597b342695e069468e2248d83
+github.com/aphistic/golf,v0.0.0-20180712155816-02c07f170c5a,h1:2KLQMJ8msqoPHIPDufkxVcoTtcmE5+1sL9950m4R9Pk=,a0ca77a50520037607c3a2a798b66aee1d5df63f4800b4236f51be2f1e3c1d70
+github.com/aphistic/gomol,v0.0.0-20190314031446-1546845ba714,h1:ml3df+ybkktxzxTLInLXEDqfoFQUMC8kQtdfv8iwI+M=,c2fd1a9db2fb7a5ca7ba9132fbddb5d8efd64babcff7c0f66d41d3cf97b8caab
+github.com/aphistic/gomol-console,v0.0.0-20180111152223-9fa1742697a8,h1:tzgowv45TOFALtZLJ9y3k+krzOh2J8IkCvJ8T//6VAU=,26a1b99db9a92a7f5d088e529c43db6de957a3a1650c27d7a872495f73a52880
+github.com/aphistic/gomol-gelf,v0.0.0-20170516042314-573e82a82082,h1:PgPqI/JnStmzwTof+PtT53Pz53dlrz2BmF7cn5CAwQM=,e44d4de8d62391c1e0e70c3b27f4c341bb0398083f33b99be46e29144fad3c50
+github.com/aphistic/gomol-json,v1.1.0,h1:XJWwW8PxYOHf0f0FquuBWcgvZBvQ89nPxZsqQ9pfpro=,0e1ab66a46afe81c4662f8a49ca38042f0c6bc8645895336399adef1eedaff59
+github.com/aphistic/sweet,v0.2.0,h1:I4z+fAUqvKfvZV/CHi5dV0QuwbmIvYYFDjG0Ss5QpAs=,02bebcef905b02cf7195137d9b20920367bb5f8c635a6e5a112b787596414f51
+github.com/aphistic/sweet-junit,v0.0.0-20190314030539-8d7e248096c2,h1:qDCG/a4+mCcRqj+QHTc1RNncar6rpg0oGz9ynH4IRME=,6a3ab195b97bd1981f2ae87a172bc24ecfb44ffbd8d28428f97bfa46e66f559b
+github.com/apparentlymart/go-cidr,v1.0.1,h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U=,5af128e1ecdf5f2203fda104a653f13fb2e46acc3f68b2d7634a760a8f556ea0
+github.com/apparentlymart/go-dump,v0.0.0-20190214190832-042adf3cf4a0,h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I=,3506757fd2dcbcf8e77aa962c923d9ceaf918538bf9b117f98aa562bc83c77ef
+github.com/apparentlymart/go-textseg,v1.0.0,h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0=,2572a77af285125f1980e9b751e5a7c3ae59b73c4fc97e7c2407681609991142
+github.com/appc/spec,v0.8.11,h1:BFwMCTHSDwanDlAA3ONbsLllTw4pCW85kVm290dNrV4=,4a17d699b3e2c3cc8b301de260a45c8fc31054fbb5c689e567f24e3e63bf8f79
+github.com/apple/foundationdb/bindings/go,v0.0.0-20190411004307-cd5c9d91fad2,h1:VoHKYIXEQU5LWoambPBOvYxyLqZYHuj+rj5DVnMUc3k=,a2dc6bd23d9066d3acf174c9b33378c08ae4a95cfd017abc70a16388e74ea2c3
+github.com/approvals/go-approval-tests,v0.0.0-20160714161514-ad96e53bea43,h1:ePCAQPf5tUc5IMcUvu6euhSGna7jzs7eiXtJXHig6Zc=,e3b51ab88c4f3b1c4aea2fadd0b3d3e2ec178d37232066b9fe3b0177e1c6e9aa
+github.com/aquasecurity/fanal,v0.0.0-20191031102512-c1c079886da6,h1:B84l/SNXzzcqwgIORAmEv7gs4K4l+DJkdliI6ib/zNw=,7247188e1746360364e7ff77aa0c531df69074c49b23e7f67d65134ca577b0e0
+github.com/aquasecurity/go-dep-parser,v0.0.0-20190819075924-ea223f0ef24b,h1:55Ulc/gvfWm4ylhVaR7MxOwujRjA6et7KhmUbSgUFf4=,73ce01b48b9aa56349d928a27bdd4b77c149541385e645951b2e25f1d6ab5d26
+github.com/araddon/dateparse,v0.0.0-20190622164848-0fb0a474d195,h1:c4mLfegoDw6OhSJXTd2jUEQgZUQuJWtocudb97Qn9EM=,3b88bff198316e2795d11340862ef873387cd7dba97eeb17f106f41deb00d602
+github.com/araddon/gou,v0.0.0-20190110011759-c797efecbb61,h1:Xz25cuW4REGC5W5UtpMU3QItMIImag615HiQcRbxqKQ=,936e20f4c9eaa45f54586ab86bce911f0b1f935d0410dd683dc647797ed7225d
+github.com/aristanetworks/fsnotify,v1.4.2,h1:it2ydpY6k0aXB7qjb4vGhOYOL6YDC/sr8vhqwokFQwQ=,9c0dd5427e82f044a9e5808a3436b43472ff032f23ac853829e5c166171044a3
+github.com/aristanetworks/glog,v0.0.0-20180419172825-c15b03b3054f,h1:Gj+4e4j6g8zOhckHfGbZnpa0k8yDrc0XRmiyQj2jzlU=,496dd08756b324a7925b670a907328433f1477763a229b76a4eef8ed254c9683
+github.com/aristanetworks/goarista,v0.0.0-20191023202215-f096da5361bb,h1:gXDS2cX8AS8KbnP32J6XMSjzC1FhHEdHfUUCy018VrA=,2c348fcdf827ac0d1238fb556f66ad1f13f05d8c5a6d2b3efe5f94be40af5021
+github.com/aristanetworks/splunk-hec-go,v0.3.3,h1:O7zlcm4ve7JvqTyEK3vSBh1LngLezraqcxv8Ya6tQFY=,545adec43ebdf1c9cdc65cd3d738d131f1b02706d25876de1fda65c4989195af
+github.com/armon/circbuf,v0.0.0-20190214190532-5111143e8da2,h1:7Ip0wMmLHLRJdrloDxZfhMm0xrLXZS8+COSu2bXmEQs=,c8b7ba977844b5378a2413c123c3e55d0885fb67f64ad6cf06575a791a36b827
+github.com/armon/consul-api,v0.0.0-20180202201655-eb2c6b5be1b6,h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA=,091b79667f16ae245785956c490fe05ee26970a89f8ecdbe858ae3510d725088
+github.com/armon/go-metrics,v0.0.0-20190430140413-ec5e00d3c878,h1:EFSB7Zo9Eg91v7MJPVsifUysc/wPdN+NOnVe6bWbdBM=,3d48bc38dda0cff4dbf0b56b9b6e2e8fc3e6be2282f2a612a96a6702cc8a9fc5
+github.com/armon/go-proxyproto,v0.0.0-20190211145416-68259f75880e,h1:h0gP0hBU6DsA5IQduhLWGOEfIUKzJS5hhXQBSgHuF/g=,1004212be9a343c99e1849425845af1ec5e3e35cc4917483721cb03620982d58
+github.com/armon/go-radix,v1.0.0,h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=,df93c816505baf12c3efe61328dc6f8fa42438f68f80b0b3725cae957d021c90
+github.com/armon/go-socks5,v0.0.0-20160902184237-e75332964ef5,h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=,f473e6dce826a0552639833cf72cfaa8bc7141daa7b537622d7f78eacfd9dfb3
+github.com/asaskevich/govalidator,v0.0.0-20190424111038-f61b66f89f4a,h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=,b5dfb936e0256459bc633c8acf433f4a01a468868db9bd6e390a67f4678185f5
+github.com/asdine/storm,v2.1.2+incompatible,h1:dczuIkyqwY2LrtXPz8ixMrU/OFgZp71kbKTHGrXYt/Q=,ffea8b759006a871732554e1e0a42753fb9a5dd9884eb150e1b42806d51cd5fd
+github.com/assetsadapterstore/tivalue-adapter,v1.0.3,h1:zcFcT1x1rWDYQEaA3wI7Hr7F25Cspy+O1cr+vUMjrks=,c42adddd544495ef0ebe1d8730bad20c4251c7646e1782542782bc946c839eca
+github.com/astaxie/beego,v1.12.0,h1:MRhVoeeye5N+Flul5PoVfD9CslfdoH+xqC/xvSQ5u2Y=,1f14eb5d216170c027754bea1129bbcdafc06a035650e635375c61a17be6f316
+github.com/asticode/go-astilog,v1.0.0,h1:l9tek0K7KoQCmhZ7cvBTtVu0NsKpS9hB6jBLtQyxWYk=,49fe2b286073848e780a9326f7d37771372e61827ff07b80db89667e6ac4d1d4
+github.com/aws/amazon-ssm-agent,v0.0.0-20191011205301-04bb0617297b,h1:xv695CeRjoBS0baQSS5UfQkeo63GiMjmDwiAeY09bSw=,08ede8d7aa20210a4738e0ea033f1bf8fd1ce13bba6c375431c8c1e7a8565c37
+github.com/aws/aws-lambda-go,v1.13.2,h1:8lYuRVn6rESoUNZXdbCmtGB4bBk4vcVYojiHjE4mMrM=,05b1633366a8df9e313df4409d003a277ff7ae46f1079b3ad7f6b48c0dabfb75
+github.com/aws/aws-sdk-go,v1.25.25,h1:j3HLOqcDWjNox1DyvJRs+kVQF42Ghtv6oL6cVBfXS3U=,c34d718d97487766a9a8ac818d37dd135d75d747a8d191a616b75425c32456f2
+github.com/aybabtme/rgbterm,v0.0.0-20170906152045-cc83f3b3ce59,h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo=,a4456a42277e0c987de99e9c4ba141db064107ce737ad1dd2e050aeb1149b67e
+github.com/aymerick/raymond,v2.0.2+incompatible,h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0=,df6e22632cb314b76ab10dd6a1c2c66a79da44200bfec9f5e4f321100d90dc64
+github.com/baiyubin/aliyun-sts-go-sdk,v0.0.0-20180326062324-cfa1a18b161f,h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=,0965da027355d9b385358331ec359cf729ec4571ec4ca86339da925364c13559
+github.com/bartekn/go-bip39,v0.0.0-20171116152956-a05967ea095d,h1:1aAija9gr0Hyv4KfQcRcwlmFIrhkDmIj2dz5bkg/s/8=,6a278508499838d4c57c1dbdafcfc9f9f909e7358c518a8699728053b695d0c5
+github.com/bazelbuild/buildtools,v0.0.0-20191024175656-9f3978593d3e,h1:QdfIPgk+fJY8AcfjVk2/tdc2dNtl6d+7x8dhVBP72Ik=,f768dd2a38a1dedc924740f9b7a3194ca68d8a24db8fb840c547aee3911162d3
+github.com/bbangert/toml,v0.0.0-20130821181452-a2063ce2e5cf,h1:SGoM2ypzNnI+hMs01svW6wRddndk7eWRs1Bx1zOGRTI=,63690dcb3fcf13b55193cfe263b4a4fdbbe2ee9d7f93440375815dac28d34cb9
+github.com/bcext/cashutil,v0.0.0-20190126062106-1194a0af0582,h1:+sgikGWB0jvS9rzLlPww+SSFoieOLB8yieXyX9DRCF4=,4d5b42e5d472015edeef1b6bf54e253a85bab6df1ac16aabea7fd0dea4aa85e3
+github.com/bcext/gcash,v0.0.0-20190404152342-2e38815af4f2,h1:XVuqYNixmuo81vR/PnBRDDiTH7596mAwQlQ8BucvGnM=,6b24e00369a493c32e730a4d78d8c4fd122ffe0ce319c5d72f3c7d2f12ede4b7
+github.com/beego/goyaml2,v0.0.0-20130207012346-5545475820dd,h1:jZtX5jh5IOMu0fpOTC3ayh6QGSPJ/KWOv1lgPvbRw1M=,aaa4165412caaacbb2df4427207a206e09215c3f7a19f8309e9222ca9ff80691
+github.com/beego/x2j,v0.0.0-20131220205130-a0352aadc542,h1:nYXb+3jF6Oq/j8R/y90XrKpreCxIalBWfeyeKymgOPk=,f9a32026b2107f3cc3610ac6b75c4c64818646a316c35e648c8811d4276a9993
+github.com/beevik/etree,v1.1.0,h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=,614a33736f8b9262a809f101df5bf71f47777879b1191165b6247d6b67c7468c
+github.com/beevik/guid,v0.0.0-20170504223318-d0ea8faecee0,h1:oLd/YLOTOgA4D4aAUhIE8vhl/LAP1ZJrj0mDQpl7GB8=,5add94fcade6c7afa236112c8da300d47ec499ad1789a5e805c8198062dd0749
+github.com/beevik/ntp,v0.2.0,h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw=,42e14f30c23ba2f5ddaff76101016d87f0f0a0f1d96d3d20e42fd02842091c76
+github.com/beorn7/perks,v1.0.1,h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=,25bd9e2d94aca770e6dbc1f53725f84f6af4432f631d35dd2c46f96ef0512f1a
+github.com/bep/debounce,v1.2.0,h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo=,ddc0a77e4819b6b826d69fdf1a5a153f3f867a31e030cfe28296355b670adf21
+github.com/bep/gitmap,v1.1.1,h1:Nf8ySnC3I7/xPjuWeCwzukUFv185iTUQ6nOvLy9gCJA=,364163e67741ae331d164fd881964160f19fdbdfe094e0e762314cc37aac646a
+github.com/bep/go-tocss,v0.6.0,h1:lJf+nIjsQDpifUr+NgHi9QMBnrr9cFvMvEBT+uV9Q9E=,40e7175da9564796e184e4383bfce703f63244b850999b5a54fd5792bfc5baf5
+github.com/bep/tmc,v0.5.0,h1:AP43LlBcCeJuXqwuQkVbTUOG6gQCo04Et4dHqOOx4hA=,f8e0be71fb845a4ca22825f5b9c51c1a66c29e9ccff723e063781ee64c664c66
+github.com/bgentry/go-netrc,v0.0.0-20140422174119-9fd32a8b3d3d,h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=,59fbb1e8e307ccd7052f77186990d744284b186e8b1c5ebdfb12405ae8d7f935
+github.com/bgentry/speakeasy,v0.1.0,h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=,d4bfd48b9bf68c87f92c94478ac910bcdab272e15eb909d58f1fb939233f75f0
+github.com/bifurcation/mint,v0.0.0-20180715133206-93c51c6ce115,h1:fUjoj2bT6dG8LoEe+uNsKk8J+sLkDbQkJnB6Z1F02Bc=,40a4bd02b9e3477271638bc17ae8537e2675ace0a9b85d753820e979dbf97f36
+github.com/binance-chain/go-sdk,v1.0.8,h1:mC1Tai9diqIWuKTJmrFLal90OCsgtDvyLEItMvglaHA=,3d0f86f959b38f11174d8ee574e77e5d80d2c672d0720dee519f3708e873b0ca
+github.com/binance-chain/ledger-cosmos-go,v0.9.9-binance.1,h1:8mAtw1Tp/BhhTrsXmXM60H1fihcvcKLfo2ZSxShaXKw=,f6dc2bfb4d29db01cad72815615301e089d727110d1d5a0de43e829953e45041
+github.com/biogo/hts,v0.0.0-20160420073057-50da7d4131a3,h1:3b+p838vN4sc37brz9W2HDphtSwZFcXZwFLyzm5Vk28=,93be93b79da8920fb5f02bb2e50a364e2b33dc831229d163e7be70c1010cdb9e
+github.com/bitcoinsv/bsvd,v0.0.0-20190609155523-4c29707f7173,h1:2yTIV9u7H0BhRDGXH5xrAwAz7XibWJtX2dNezMeNsUo=,8e1e554ddc232e763fac27ddc0661cfe543163802b0d6bb9a2904bf24756ddc3
+github.com/bitcoinsv/bsvlog,v0.0.0-20181216181007-cb81b076bf2e,h1:6f+gRvaPE/4h0g39dqTNPr9/P4mikw0aB+dhiExaWN8=,89f0c34e6936d82a1629d5d255923ff27c0adeb99709269cf62071e48cb5fbd8
+github.com/bitcoinsv/bsvutil,v0.0.0-20181216182056-1d77cf353ea9,h1:hFI8rT84FCA0FFy3cFrkW5Nz4FyNKlIdCvEvvTNySKg=,4d4923e8743012e1f8ed1a1ef721786fc2d5249cc5dafd96fdd350c485378cfe
+github.com/bitly/go-hostpool,v0.0.0-20171023180738-a3a6125de932,h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=,9a55584d7fa2c1639d0ea11cd5b437786c2eadc2401d825e699ad6445fc8e476
+github.com/bitly/go-simplejson,v0.5.0,h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=,53930281dc7fba8947c1b1f07c82952a38dcaefae23bd3c8e71d70a6daa6cb40
+github.com/blackducksoftware/horizon,v0.0.0-20190625151958-16cafa9109a3,h1:noI1RY2cUFZfdZMIz1+1LzT8ZeuWK703gwmH/ZC2YnQ=,ece353e9e973ce03d131b29c6c00aea53f1b2e507960b389cdfeb2cc317897ef
+github.com/blacktear23/go-proxyprotocol,v0.0.0-20180807104634-af7a81e8dd0d,h1:rQlvB2AYWme2bIB18r/SipGiMEVJYE9U0z+MGoU/LtQ=,123c82a455309b3a3118504c0a70771352292abced294dca39a570b89e48adba
+github.com/blakesmith/ar,v0.0.0-20190502131153-809d4375e1fb,h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=,015878daba57ba5ce7228f772b843fffa847d99c7afeb308089bef77f433c510
+github.com/blang/semver,v3.5.1+incompatible,h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=,8d032399cf835b93f7cf641b5477a31a002059eed7888a775f97bd3e9677ad3c
+github.com/blevesearch/bleve,v0.8.1,h1:20zBREtGe8dvBxCC+717SaxKcUVQOWk3/Fm75vabKpU=,58a5b5ade8123d54b7510e463c25e1e59e6cd3d98acdcb4d582c42db67c03519
+github.com/blevesearch/blevex,v0.0.0-20180227211930-4b158bb555a3,h1:U6vnxZrTfItfiUiYx0lf/LgHjRSfaKK5QHSom3lEbnA=,defa5966f802eab571cc8d9315323104b776751dd13caae9d8fc0476576d57ca
+github.com/blevesearch/go-porterstemmer,v0.0.0-20141230013033-23a2c8e5cf1f,h1:J9ZVHbB2X6JNxbKw/f3Y4E9Xq+Ro+zPiivzgmi3RTvg=,e13cc37d08c58870cdbad544b726934cd62ca6aa2ae35f02598f72e30d7c0f59
+github.com/blevesearch/segment,v0.0.0-20160105220820-db70c57796cc,h1:7OfDAkuAGx71ruzOIFqCkHqGIsVZU0C7PMw5u1bIrwU=,21278826e6ba0f63024a953c480467bf41d6717ae4a87c3021a9f74d2f2ae618
+github.com/blocktree/arkecosystem-adapter,v1.0.4,h1:TkZWCzAgi20CjAMlOpwTDppt6XO7X8Fn5EjSUsuB6kI=,22346af6957b0b8fae47d982605f565e5e16e86bc52a9fdd234b023067896cf2
+github.com/blocktree/bitshares-adapter,v1.0.5,h1:mzYlpip0crtYaDaXbKqtGLAxad83p19HLTVa9LLW3fc=,03ce80398ab59af79feb92b054e5da02a290ef27aef5facb93cdd86de2e0df91
+github.com/blocktree/ddmchain-adapter,v1.0.5,h1:Lx8zD0lOHb9TJ7EcGJQhyvpDkYko6OoV8uwudKRKlJA=,81e65ed5692152fcaa1dbf997f71dc43192abc72dad6fb78b721d742c05c1a7a
+github.com/blocktree/eosio-adapter,v1.0.0,h1:cncKE4QbQxDsr8B+HlhU7tywbCtZRsWMln2ek8I5lbc=,cc658d6f9fa5470c5affb4caad58e17637a6d46f8e5d1b3730ed06e570e61959
+github.com/blocktree/ethereum-adapter,v1.1.10,h1:PkmQeRT5ljyCOQZPT0diJo+4G9OqOcJsnRcXeF5fitU=,cf8465db958e214c8196e6311fd5db24f8d28265a37914c2cf9d2dac54a5fd1a
+github.com/blocktree/futurepia-adapter,v1.0.12,h1:mL1rDvcM55hKwLhHOkg1v2GwnCEsDniUrqrMG3PK/+4=,ae29bbdb9a4a1ec345f7d220d6a736ed827a307454d0466bb065dacf3d94200d
+github.com/blocktree/go-owcdrivers,v1.1.18,h1:KCNm+HczpDfxyUf+Wrvbj/iWwQDJ+ca/FBjm3H06rIY=,65bcca1918d8b9e1048bac14b1393dec246402320b6a5dde20ee6afe84585736
+github.com/blocktree/go-owcrypt,v1.0.3,h1:qfAwJsWYp7WaI26hAwPuFUrMXhD9bWwuGXYWBOLsVes=,f365daad6adfcc5aee14faa1455f772b5e39b1c9ff3598afb1c3645587cb6b2e
+github.com/blocktree/moacchain-adapter,v1.0.3,h1:k9drMeekvBsXORortW/zJXaO6CokXVv2EL0/YK3c1/A=,66c87656369c5246bad1527f7385d1cb98bbeda431383f154a23e9bf821a05a2
+github.com/blocktree/nulsio-adapter,v1.1.7,h1:d0xuovBqodBAv8BE/CPZjfe5CNma6FFSP6W3ynJRD0U=,c814c05686483abc345bf4fb997fc61595e738b99cc8a8d36742414f93e948b0
+github.com/blocktree/ontology-adapter,v1.0.8,h1:Lej35ZPPgjS6nP5CEumIUskRNASMZswgrByYSxrWPe0=,fcdeb4c6d8f37a22f52e2938ebc51b4ff1f4cf4116eebce8ecc7591995236853
+github.com/blocktree/openwallet,v1.5.3,h1:6hNj61wLfzEGqbbY0ZOeqGAjSj9snoRSBikgSlWPqZI=,1f169b69cd3ec4a4f82836c2b2178eb162464d6413c09f8170f73a838d28650b
+github.com/blocktree/ripple-adapter,v1.0.13,h1:zgJt7onq5+V6pvQ7Kl3xiiSkk3uxuCF07OpwCtJTM8w=,bb7f515a6573eb185da0bebb28bf57364d175ee7f937e18af5b2eac98741464f
+github.com/blocktree/virtualeconomy-adapter,v1.1.5,h1:YJ2JKUifSsCjCneM0NUky3WbG0LEm7IKUBmf9EAmAXc=,7a5085b8b0b114e2491032ec6f95e300c28fa309ec5883044d8b954d7d4db06e
+github.com/blocktree/waykichain-adapter,v1.0.3,h1:qY/Txh+n4iIJA49rDMj41qpIUj3McjBir8Ls+sX8c3w=,62ea2ff873c84a32d3482c8ec1687221a1e46055b9be18fcd25be584cf2cac5d
+github.com/bluele/gcache,v0.0.0-20190518031135-bc40bd653833,h1:yCfXxYaelOyqnia8F/Yng47qhmfC9nKTRIbYRrRueq4=,334accb65479b1b18fb569b08d14eebceb6478ea16abe9fbad2f1c6b6586deb6
+github.com/bluele/slack,v0.0.0-20180528010058-b4b4d354a079,h1:dm7wU6Dyf+rVGryOAB8/J/I+pYT/9AdG8dstD3kdMWU=,2b0055c292b7baa49f56eb9fc710f35f005747ddbef16427d5c985617c3b697d
+github.com/bmatcuk/doublestar,v1.1.5,h1:2bNwBOmhyFEFcoB3tGvTD5xanq+4kyOZlB8wFYbMjkk=,81f592b11277591e943b91522497c323fcf0c6b4f3099f495de10f83e8c3e697
+github.com/bmizerany/assert,v0.0.0-20160611221934-b7ed37b82869,h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=,2532a167df77ade7e8012f07c0e3db4d4c15abdb7ffa7b05e1d961408da9a539
+github.com/bmizerany/pat,v0.0.0-20170815010413-6226ea591a40,h1:y4B3+GPxKlrigF1ha5FFErxK+sr6sWxQovRMzwMhejo=,ed04bed4d193e25371ebc6524984da4af9ece5c107fcc82d5aa4914b726706d2
+github.com/bndr/gotabulate,v1.1.2,h1:yC9izuZEphojb9r+KYL4W9IJKO/ceIO8HDwxMA24U4c=,2c1ecc544368e40010082f800c1ee24eaf1b8e0f96fa76a56e4f61dda4cd0d60
+github.com/boltdb/bolt,v1.3.1,h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=,ecaf17b0dbe7c85a017704c72667b2526b492b1a753ce7302a27dd2fb2e6ee79
+github.com/boombuler/barcode,v1.0.0,h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDdrc=,ef3832c4d22a09377323980bacd9f5f2ab43d0d20da115e1cfb139e093d7bb9b
+github.com/bradfitz/go-smtpd,v0.0.0-20170404230938-deb6d6237625,h1:ckJgFhFWywOx+YLEMIJsTb+NV6NexWICk5+AMSuz3ss=,0a06dd547fed38e2744800b5f4ebae5ac00ee08717ded281510a8d319b8db8f3
+github.com/bradfitz/gomemcache,v0.0.0-20190913173617-a41fca850d0b,h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=,eb71acfac0c4ce5f0b6537d8029de98902d83fd38fdcbfd757f06697c6323f78
+github.com/bradfitz/iter,v0.0.0-20190303215204-33e6a9893b0c,h1:FUUopH4brHNO2kJoNN3pV+OBEYmgraLT/KHZrMM69r0=,6883ce0960849ca9c024a4a4e7508ff521da2a3bb66d1974ea2f970a5265ea39
+github.com/bradfitz/latlong,v0.0.0-20140711231157-b74550508561,h1:mz4equOOUOnI4q5E7dyHlRx1x63YEaYwhlVluCDila4=,d1c124508f1825697a2bdb9fac48d2b8805b41f8e546d262fc487d8450962cec
+github.com/bradhe/stopwatch,v0.0.0-20180424000511-fd55e776a960,h1:YJWTgxlTgeHlvhe7tZJm0yBcg2GhjDQs8zig5O5vup8=,c2926a4febee7eea0f523b3d4fcaa414c27effc2abc053137a3dbf0b3a4fa324
+github.com/briankassouf/jose,v0.9.2-0.20180619214549-d2569464773f,h1:ZMEzE7R0WNqgbHplzSBaYJhJi5AZWTCK9baU0ebzG6g=,c0b50157ec3c39fbd6ded9d5e6bc763890e6d909db38b337a72876124c2baeeb
+github.com/brocaar/lorawan,v0.0.0-20190925120821-154a30dbdce2,h1:51WcQ+VAc/6jZ/8GBJiQ3B7FrT2aXI+YsUx2iG9tJlw=,0082cebaf26ed36c901f9b44b6d785eccc2a0c123088642eac7c9b5711b7d0ca
+github.com/bsm/go-vlq,v0.0.0-20150828105119-ec6e8d4f5f4e,h1:D64GF/Xr5zSUnM3q1Jylzo4sK7szhP/ON+nb2DB5XJA=,61fc03674cd72d5a4c55413e8b58fc8eafc58fbb71fb89c719225650754b3469
+github.com/bsm/sarama-cluster,v2.1.15+incompatible,h1:RkV6WiNRnqEEbp81druK8zYhmnIgdOjqSVi0+9Cnl2A=,a8a4867f09704222362b75fa00c9894106a928dc7cf905f1b80ca7bbd1a3b8e5
+github.com/btcsuite/btclog,v0.0.0-20170628155309-84c8d2346e9f,h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=,74ad4defbabf48c98bbb547be1c40c11fa2c286f599412c774d1c5604dc1808d
+github.com/btcsuite/btcutil,v0.0.0-20190425235716-9e5f4b9a998d,h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng=,de1ee450ff2cfec2df220fec0d3e265cc812f214892bfad601e142632e2cf3f9
+github.com/btcsuite/go-socks,v0.0.0-20170105172521-4720035b7bfd,h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=,cc27776f56f7c58c2808af55781e9b3f7d0eb0dc08e4c19c38c6bdf2465ce0e7
+github.com/btcsuite/goleveldb,v1.0.0,h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4=,13e37462cb2fe5976221f57d357051c1c3cc63a9b0e67e6ed97f98af795d0815
+github.com/btcsuite/snappy-go,v1.0.0,h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE=,d136165bdbf91780ded5d3ebaba9026f900595e56c19aa0ef29896015eae9627
+github.com/btcsuite/websocket,v0.0.0-20150119174127-31079b680792,h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=,d45ac16f59082ac369e61c7bbe23153e289cad03619ab8041963d54cd700d6f0
+github.com/btcsuite/winsvc,v1.0.0,h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk=,6893f7a62faec17d7b0856c7464754cab14c4d913e27af5276f6a98b25f3c779
+github.com/buger/jsonparser,v0.0.0-20191004114745-ee4c978eae7e,h1:oJCXMss/3rg5F6Poy9wG3JQusc58Mzk5B9Z6wSnssNE=,7e2dda4c1b4217408903f3b4a1f2cdd93d71bc7682387ba860cfa0cc9fcf88be
+github.com/bugsnag/bugsnag-go,v1.5.3,h1:yeRUT3mUE13jL1tGwvoQsKdVbAsQx9AJ+fqahKveP04=,8aaf02df2c1a4e8a5725eea1d91af69c4f9e157c2559a3452388f64a977534c0
+github.com/bugsnag/panicwrap,v1.2.0,h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA=,75357d3a5cd89dc04f1f101e02686fc1ef33b4a4f67edb82b3fa63fded3f47e9
+github.com/bwmarrin/discordgo,v0.20.1,h1:Ihh3/mVoRwy3otmaoPDUioILBJq4fdWkpsi83oj2Lmk=,616d49cc107ccd85872b6008f028c4aca021f66381828bb921f15f9e8149988a
+github.com/bwmarrin/snowflake,v0.0.0-20180412010544-68117e6bbede,h1:lTJlWdyhwqq7h29GtuIDHW/xi+sMN+JOLMgYAwQ5O74=,2e13ad82f7ae64821f9851a66b4800f1589e413b27b469f28d21970957a3c6da
+github.com/c-bata/go-prompt,v0.2.2,h1:uyKRz6Z6DUyj49QVijyM339UJV9yhbr70gESwbNU3e0=,ffe765d86d90afdf8519def13cb027c94a1fbafea7a18e9625210786663436c4
+github.com/c2h5oh/datasize,v0.0.0-20171227191756-4eba002a5eae,h1:2Zmk+8cNvAGuY8AyvZuWpUdpQUAXwfom4ReVMe/CTIo=,b5543f3e104a84e35ac51780968282b455dd30c88730d0da166d8d6512301da6
+github.com/caarlos0/ctrlc,v1.0.0,h1:2DtF8GSIcajgffDFJzyG15vO+1PuBWOMUdFut7NnXhw=,e4b5e9dd37cee2d47ff1c5eeba9a4b6e2b778c349a3615ca9653531f035a3ca6
+github.com/cactus/go-statsd-client/statsd,v0.0.0-20191030180650-a68a2246f89c,h1:rrLWPlpOKwnBpVUXitbgM3+Nie1eBaFfBZqfiPpxVj8=,cbb94149ec688419a91406b374955946c3679b1dde0752d7c0ffdc87432cd0b3
+github.com/caddyserver/caddy,v1.0.3,h1:i9gRhBgvc5ifchwWtSe7pDpsdS9+Q0Rw9oYQmYUTw1w=,029f14052f1ec9937c4028f3231899bf5391d5eeb7f58795d5d470a6f4c338a7
+github.com/campoy/unique,v0.0.0-20180121183637-88950e537e7e,h1:V9a67dfYqPLAvzk5hMQOXYJlZ4SLIXgyKIE+ZiHzgGQ=,4bc20f70e0b170ecdabd740a5de012d05f4c9149e2882fbdb303dc1b1793a77e
+github.com/casbin/casbin,v1.9.1,h1:ucjbS5zTrmSLtH4XogqOG920Poe6QatdXtz1FEbApeM=,e2ef71d15eb595374d27961d255941b50691f9eaa91b5590f081fe3a4ab195c2
+github.com/cavaliercoder/go-cpio,v0.0.0-20180626203310-925f9528c45e,h1:hHg27A0RSSp2Om9lubZpiMgVbvn39bsUmW9U5h0twqc=,08b68e1d424b545418828c05c46bce5d795bbb8b534871667650ec6b3e7b33a6
+github.com/cenk/backoff,v2.2.1+incompatible,h1:djdFT7f4gF2ttuzRKPbMOWgZajgesItGLwG5FTQKmmE=,e3d1c641f85f548370aedc6bae3d4b975b09e3b2d1d9060f0e72bd5e2710d4c9
+github.com/cenkalti/backoff,v2.2.1+incompatible,h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=,f8196815a1b4d25e5b8158029d5264801fc8aa5ff128ccf30752fd169693d43b
+github.com/cenkalti/backoff/v3,v3.0.0,h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=,c69bf77e7b43cb3935d763c24af3810d9869a664bbcd26ffad9d3dc1bf602006
+github.com/census-instrumentation/opencensus-proto,v0.2.1,h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=,b3c09f3e635d47b4138695a547d1f2c7138f382cbe5a8b5865b66a8e08233461
+github.com/centrify/cloud-golang-sdk,v0.0.0-20190214225812-119110094d0f,h1:gJzxrodnNd/CtPXjO3WYiakyNzHg3rtAi7rO74ejHYU=,dc3de1393d7ae63ce35393630417ff8c5421a2a03cbf1a20680c7d57a74cd311
+github.com/certifi/gocertifi,v0.0.0-20180118203423-deb3ae2ef261,h1:6/yVvBsKeAw05IUj4AzvrxaCnDjN4nUqKjW9+w5wixg=,054d6c3a6f8d78fba2f08fbc2f23ec839d5a4aead4a184270d87d095c80eb6dc
+github.com/cespare/cp,v1.1.1,h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU=,25f2ed5bac9ac3c1891ff364b213f6b7b0ee2e7aed13510738ced93ea71860e3
+github.com/cespare/xxhash,v1.1.0,h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=,fe98c56670b21631f7fd3305a29a3b17e86a6cce3876a2119460717a18538e2e
+github.com/cespare/xxhash/v2,v2.1.0,h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA=,655feb22a395d9f56315280770d386eb99cdca79a97970812dbd3b30a7940638
+github.com/chaseadamsio/goorgeous,v0.0.0-20170901132237-098da33fde5f,h1:REH9VH5ubNR0skLaOxK7TRJeRbE2dDfvaouQo8FsRcA=,f81f4ef8ac52852b232ea971d009ec88007f1258c29e10e49918a31a99c6c4cc
+github.com/checkpoint-restore/go-criu,v0.0.0-20190109184317-bdb7599cd87b,h1:T4nWG1TXIxeor8mAu5bFguPJgSIGhZqv/f0z55KCrJM=,1d1f5c6e529c87259305d8ed6bf4d381dabbf85458de187981204339e251a5be
+github.com/cheekybits/genny,v1.0.0,h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=,770f3e01425b9b0a87a5e0b29fc6ac2cfa67a3f1265aafb16c96a47bafc304e4
+github.com/cheekybits/is,v0.0.0-20150225183255-68e9c0620927,h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764=,f7bf9ac5b1fc574ef5a373382909af550ef1a7f01182469eaa12e18c7c5fc7cb
+github.com/cheggaaa/pb,v2.0.7+incompatible,h1:gLKifR1UkZ/kLkda5gC0K6c8g+jU2sINPtBeOiNlMhU=,383b717f271a2471e57ac52f64dbb77304ec1c0b53c5efeb7a1392668f59d0b4
+github.com/cheggaaa/pb/v3,v3.0.1,h1:m0BngUk2LuSRYdx4fujDKNRXNDpbNCfptPfVT2m6OJY=,781be3118614dfaeb2df44d31d8af36c703c2aaed18e9ca49fa4ef9ba1539236
+github.com/chewxy/hm,v1.0.0,h1:zy/TSv3LV2nD3dwUEQL2VhXeoXbb9QkpmdRAVUFiA6k=,68ab03d9f8cb3d92d6c8234cfd879004be2fd69457d2c9fa6834d1c6ddb22b43
+github.com/chewxy/math32,v1.0.4,h1:dfqy3+BbCmet2zCkaDaIQv9fpMxnmYYlAEV2Iqe3DZo=,7885f637bb90729d04f125e030542b9a6999f9e5dffd3294baffbcdd548bbc3e
+github.com/chrismalek/oktasdk-go,v0.0.0-20181212195951-3430665dfaa0,h1:CWU8piLyqoi9qXEUwzOh5KFKGgmSU5ZhktJyYcq6ryQ=,094a132bc1e950677f75e570b17a52f103edd6acd3ec1c0943cf9cda3cd6355a
+github.com/chromedp/cdproto,v0.0.0-20191009033829-c22f49c9ff0a,h1:AuIGvB6IuWpMEdfKQ+t77D6dzLpNftzxAsktehYyWn8=,bf85eeebdc65b1e90d851b42f56a3dbf5bcff4923aa426692a1c0d0a1727a522
+github.com/chromedp/chromedp,v0.5.1,h1:PAqhoCWCHzRphYnmmxLSiYk7EEwDplCm4woTCCaV2cQ=,59cd1ab42eeb90e32cc60e77a8fbb19ca629603200d5bd40d611f780e646062b
+github.com/chzyer/logex,v1.1.10,h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=,2c94771c1e335a2c58a96444b3768b8e00297747d6ce7e7c14bab2e8b39d91bd
+github.com/chzyer/readline,v0.0.0-20180603132655-2972be24d48e,h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=,3dc842677887278fb33d25078d375ae6a7a94bb77a8d205ee2230b581b6947a6
+github.com/chzyer/test,v0.0.0-20180213035817-a1ea475d72b1,h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=,ad8550bed3c4a94bbef57b9fc5bb15806eaceda00925716404320580d60e2f7d
+github.com/cihub/seelog,v0.0.0-20170130134532-f561c5e57575,h1:kHaBemcxl8o/pQ5VM1c8PVE1PubbNx3mjUr09OqWGCs=,fc279208e6094fb22c8ea651c6e9794844069693c9b916c225276c54f7e76bfe
+github.com/circonus-labs/circonus-gometrics,v2.3.1+incompatible,h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY=,d8081141497e3cd34844df66af016c7900d58b324fb689e17e57bc053d91c9ba
+github.com/circonus-labs/circonusllhist,v0.1.3,h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA=,4dc805d9735dd9ca9b8875c0ad23126abb5bc969c5a40c61b5bc891808dbdcb6
+github.com/clbanning/mxj,v1.8.4,h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=,8947cf617bdd9efc62817c8ddb17bafe497f35abdf10a3c60f295e387f633f70
+github.com/client9/misspell,v0.3.4,h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=,a3af206372e131dd10a68ac470c66a1b18eaf51c6afacb55b2e2a06e39b90728
+github.com/cloudflare/backoff,v0.0.0-20161212185259-647f3cdfc87a,h1:8d1CEOF1xldesKds5tRG3tExBsMOgWYownMHNCsev54=,2aea6d1528c42cf5f111e035bba564fd0481cb4ddb3b50f783f2481d855947cb
+github.com/cloudflare/cfssl,v1.4.0,h1:TdyQbj/bDUMUHf2IkcHU2EHUmzCmRLuJ3fFd8EYMg1E=,845fc5f4a7f4c2356d676916fdd7b4b2217b76c8f9b7a960290ab8884d6f8e0e
+github.com/cloudflare/cloudflare-go,v0.10.4,h1:7C1D9mtcNFZLCqmhkHK2BlwKKm9fi4cBqY6qpYtQv5E=,e8f6ee817c9b807c98559ff87d4ed7a284738d9dc253b6db7520911d93bd81e3
+github.com/cloudflare/go-metrics,v0.0.0-20151117154305-6a9aea36fb41,h1:/8sZyuGTAU2+fYv0Sz9lBcipqX0b7i4eUl8pSStk/4g=,9176a680ad7a72cf717e3e01ee1ca6b292cb576b543e12ff1770cc58957bc222
+github.com/cloudflare/golz4,v0.0.0-20150217214814-ef862a3cdc58,h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg=,75832d1c2989b2a0d7eb8d2cec300f6d457254d42927a23f522b164833e791d4
+github.com/cloudflare/redoctober,v0.0.0-20171127175943-746a508df14c,h1:p0Q1GvgWtVf46XpMMibupKiE7aQxPYUIb+/jLTTK2kM=,e69334393aec994f9ba55bbdfa8a65c0cfa46080230068c44ca16a85c0a74079
+github.com/cloudfoundry-community/go-cfclient,v0.0.0-20190201205600-f136f9222381,h1:rdRS5BT13Iae9ssvcslol66gfOOXjaLYwqerEn/cl9s=,f01d41c3c911b59bf717674690799c978f3a841ef695c7ee09f4afe5f7c96e64
+github.com/cloudfoundry-incubator/candiedyaml,v0.0.0-20170901234223-a41693b7b7af,h1:6Cpkahw28+gcBdnXQL7LcMTX488+6jl6hfoTMRT6Hm4=,325af9d6827b8d120a72992c38ba776187fbd947a39c9f1928a43a1a2b262453
+github.com/cloudfoundry/bosh-agent,v2.271.0+incompatible,h1:277mM9hsUzyrd5Qd/5e1LFwiobIYorE7vTBRZohRV8s=,42e253b855d03655ec2cf59ab01a14aa0037f25029517be595dda26ff9a2a552
+github.com/cloudfoundry/bosh-utils,v0.0.0-20191026100324-0b6803ec5382,h1:Rrpgz+K2Zso//XUmqbGlnYi9rw6EtYJ4uLlTNSnSBIw=,c08bbf97e510b2de271fd64f5b2acedfa011b4fd3f30092804992084c67b68b7
+github.com/cloudfoundry/gosigar,v1.1.0,h1:V/dVCzhKOdIU3WRB5inQU20s4yIgL9Dxx/Mhi0SF8eM=,53acb43e5111c6af6af138e1144907bb5f9bf8abc28e71a703502f92c13ba274
+github.com/cloudfoundry/sonde-go,v0.0.0-20171206171820-b33733203bb4,h1:cWfya7mo/zbnwYVio6eWGsFJHqYw4/k/uhwIJ1eqRPI=,6124fdcac54e1baf09703ed2b938a4e2bb55d9cd20f78451f25c16638a95f62d
+github.com/cockroachdb/apd,v1.1.0,h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=,fef7ec2fae220f84bfacb17fbfc1b04a666ab7f6fc04f3ff6d2b1e05c380777d
+github.com/cockroachdb/apd/v2,v2.0.1,h1:y1Rh3tEU89D+7Tgbw+lp52T6p/GJLpDmNvr10UWqLTE=,9f1c35b8118f70f08150bf5e9da225fa1201f5d0f8c22f326468ea22ab6b791d
+github.com/cockroachdb/cockroach-go,v0.0.0-20190916165215-ad57a61cc915,h1:QX2Zc22B15gdWwDCwS7BXmbeD/SWdcRK12gOfZ5BsIs=,e3faa1cdf2a15357d1e2eb200b3bdb81dae3fb084cb04534e0caf27a68487a88
+github.com/cockroachdb/datadriven,v0.0.0-20190809214429-80d97fb3cbaa,h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y=,170480bf3daa133144f2578e3f051f0fd98313666642cab64cef3359753a5c32
+github.com/codahale/hdrhistogram,v0.0.0-20161010025455-3a0bb77429bd,h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=,e7e117da64da2f921b1f9dc57c524430a7f74a78c4b0bad718d85b08e8374e78
+github.com/codegangsta/inject,v0.0.0-20150114235600-33e0aa1cb7c0,h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=,0a324d56992bffd288fa70a6d10eb9b8a9467665b0b1eb749ac6ae80e8977ee2
+github.com/codegangsta/negroni,v1.0.0,h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY=,2e6301aa682a7c38305f2ee72b276181cd0990f224f9fe115a433a5beb138488
+github.com/codeskyblue/go-sh,v0.0.0-20190412065543-76bd3d59ff27,h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=,77348ab27860460a015d0e65d08f18ed2194c13981f5fd722143a6e0c2dbb589
+github.com/confluentinc/confluent-kafka-go,v1.1.0,h1:HIW7Nkm8IeKRotC34mGY06DwQMf9Mp9PZMyqDxid2wI=,bc9aee1c8052340809bc43bf015a183985ec3426d404c34acfa3970e3b245340
+github.com/container-storage-interface/spec,v1.2.0,h1:bD9KIVgaVKKkQ/UbVUY9kCaH/CJbhNxe0eeB4JeJV2s=,86ecb02d57af97c9a4de8f2f3cacbceb5c7f2f96ee007133e0cfb9525ce45177
+github.com/containerd/cgroups,v0.0.0-20191011165608-5fbad35c2a7e,h1:3bt+8T1I/CuYx+a5ww32+UT4fc9x8iRiXrhfduFTlBU=,4646f14f27a365ff08abb1266b7ca4dffc1acd5e8e74b57211acbba22b496d46
+github.com/containerd/console,v0.0.0-20181022165439-0650fd9eeb50,h1:WMpHmC6AxwWb9hMqhudkqG7A/p14KiMnl6d3r1iUMjU=,62a7f1da11b3be4c0ef4f9f03b99dcf59dc988f062749f35e4e6bb585fb4e4fe
+github.com/containerd/containerd,v1.3.0,h1:xjvXQWABwS2uiv3TWgQt5Uth60Gu86LTGZXMJkjc7rY=,e3f529147f2c909c85ac461126ad092a3c5d5a2abcc4f3c22600685af6dc2f08
+github.com/containerd/continuity,v0.0.0-20190827140505-75bee3e2ccb6,h1:NmTXa/uVnDyp0TY5MKi197+3HWcnYWfnHGyaFthlnGw=,ef1a3a4c2c1508d293eb2730e47e9601cba19d939393b1018d8e476b30dfd90b
+github.com/containerd/fifo,v0.0.0-20190816180239-bda0ff6ed73c,h1:KFbqHhDeaHM7IfFtXHfUHMDaUStpM2YwBR+iJCIOsKk=,0c1b858ee9dd28bd915a3f7bd108b98b1d689be3c14535e7e8aee4a60c4a72c0
+github.com/containerd/go-runc,v0.0.0-20190923131748-a2952bc25f51,h1:vmF3zULCGpZ4QJCCLsGUXX7tNXW+0x3r9owerRAmRaU=,76ce6296dc07f1f5957867e9a5925cf9e16c69ad2b635f74a4ec471e6672ee51
+github.com/containerd/ttrpc,v0.0.0-20191028202541-4f1b8fe65a5c,h1:+RqLdWzn0xFunb+sxXaEzHOg8NuEG/eaI+9C1xXX8Mw=,f43884f8f37259c4b50a4413092064f35abd03b9db3bbe2ca3264b5a4b591b04
+github.com/containerd/typeurl,v0.0.0-20190911142611-5eb25027c9fd,h1:bRLyitWw3PT/2YuVaCKTPg0cA5dOFKFwKtkfcP2dLsA=,aa4e0823acf7b686a9521617134a171c5b5813de302e3fba742cd3b7f43ba944
+github.com/containernetworking/cni,v0.7.1,h1:fE3r16wpSEyaqY4Z4oFrLMmIGfBYIKpPrHK31EJ9FzE=,b83f1b8e9bba747e41512737383da57e517cf425beb1bd58882904dae9348b1d
+github.com/containers/image,v3.0.2+incompatible,h1:B1lqAE8MUPCrsBLE86J0gnXleeRq8zJnQryhiiGQNyE=,dadc25bfff923d4f2c8b570471be3b0fd1449f42251fb6c318b68e04f6d47b3a
+github.com/containers/storage,v1.12.13,h1:GtaLCY8p1Drlk1Oew581jGvB137UaO+kpz0HII67T0A=,08f5ee958be629b73ff02296eb11f4b0698dbd90e585ce019c5428a8e1d371d4
+github.com/containous/flaeg,v1.4.1,h1:VTouP7EF2JeowNvknpP3fJAJLUDsQ1lDHq/QQTQc1xc=,d097191570bb92f920cd15500a93205e6e93b5ee4723a51c9b8e3bfbcfaae505
+github.com/corbym/gocrest,v1.0.3,h1:gwEdq6RkTmq+09CTuM29DfKOCtZ7G7bcyxs3IZ6EVdU=,f13221d177442318b04f468fa57ea92bd9892d86e7cf7bb7299e0c58cea9df48
+github.com/coredns/coredns,v1.1.2,h1:bAFHrSsBeTeRG5W3Nf2su3lUGw7Npw2UKeCJm/3A638=,cbf720a9af4fdc5be08b0eea67fe219bb08c75292e22dca90095bf45cbd4a926
+github.com/coreos/bbolt,v1.3.3,h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY=,63ea574f28bd03b6d2a82304e0f7c96dcb30fa048311a4c8c3ad512dbacc4630
+github.com/coreos/clair,v0.0.0-20180919182544-44ae4bc9590a,h1:glxUtT0RlaVJU86kg78ygzfhwW6D+uj5H+aOK01QDgI=,3bc8c4b06a61c5673fcc69d5278b3a5313633fca1166e94a7140c363399c3dc6
+github.com/coreos/etcd,v3.3.17+incompatible,h1:f/Z3EoDSx1yjaIjLQGo1diYUlQYSBrrAQ5vP8NjwXwo=,d7ca8db509166ce05482c9b3e80cfb8d1086691901e80202f571d152da912153
+github.com/coreos/go-etcd,v2.0.0+incompatible,h1:bXhRBIXoTm9BYHS3gE0TtQuyNZyeEMux2sDi4oo5YOo=,4b226732835b9298af65db5d075024a5971aa11ef4b456899a3830bccd435b07
+github.com/coreos/go-iptables,v0.4.3,h1:jJg1aFuhCqWbgBl1VTqgTHG5faPM60A5JDMjQ2HYv+A=,4626df8f719f93e5d66bd995d586ae3540c24b2203c0d2aab7c6d5e60f89a3dc
+github.com/coreos/go-oidc,v2.1.0+incompatible,h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM=,e2e123270614dd7d47d95ae1fce80a9102df019f9e820d4f5cf5c92c64e1ad91
+github.com/coreos/go-semver,v0.3.0,h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=,b2fc075395ffc34cff4b964681d0ae3cd22096cfcadd2970eeaa877596ceb210
+github.com/coreos/go-systemd,v0.0.0-20190719114852-fd7a80b32e1f,h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c=,22237f0aed3ab6018a1025c65f4f45b4c05f9aa0c0bb9ec880294273b9a15bf2
+github.com/coreos/pkg,v0.0.0-20180928190104-399ea9e2e55f,h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=,7fe161d49439a9b4136c932233cb4b803b9e3ac7ee46f39ce247defc4f4ea8d7
+github.com/coreos/rkt,v1.30.0,h1:Kkt6sYeEGKxA3Y7SCrY+nHoXkWed6Jr2BBY42GqMymM=,436e294b735bada49407ad3c066ae251ef105ce59076ef8f0f732c586a72970e
+github.com/cosiner/argv,v0.0.0-20170225145430-13bacc38a0a5,h1:rIXlvz2IWiupMFlC45cZCXZFvKX/ExBcSLrDy2G0Lp8=,deb11c1c7a2fa44b3497731d497b3d7be5a51cf696ed43280e01822e2eed9b96
+github.com/cosmos/cosmos-sdk,v0.35.0,h1:EPeie1aKHwnXtTzKggvabG7aAPN+DDmju2xquvjFwao=,ccc975b48e3b40f4eb054e28e9243ecb48c0d8ecdf52b9512da26a8200cc7c43
+github.com/cosmos/go-bip39,v0.0.0-20180819234021-555e2067c45d,h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU=,e41d7ea781b15421a4690bedf78543f2eaad00c36c439dd4973131dec1985177
+github.com/cosmos/ledger-cosmos-go,v0.10.3,h1:Qhi5yTR5Pg1CaTpd00pxlGwNl4sFRdtK1J96OTjeFFc=,f1089701d8868e4ff3fd9e9a4104476963f725a713ee2a476b4ef8094a0bca20
+github.com/cosmos/ledger-go,v0.9.2,h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI=,a77b2063a64133d8dda638d5d602071429d7e2500576bfff5c1763f8572a8517
+github.com/couchbase/go-couchbase,v0.0.0-20191031153726-96c2e23d589a,h1:eKnoG+AQQQIxHEcBIbudmwLJv3S9UQU6oGHzvqhttqE=,5dd3e610f24adb44b31e7ecc6a80a8974b769bd622d569c69fb98bd02610bbef
+github.com/couchbase/gomemcached,v0.0.0-20191004160342-7b5da2ec40b2,h1:vZryARwW4PSFXd9arwegEywvMTvPuXL3/oa+4L5NTe8=,5b9a280cd2d546cd0d70fbd6828e73fa0b07fb9d3c0b6bff88d8e23d8e4256f4
+github.com/couchbase/goutils,v0.0.0-20190315194238-f9d42b11473b,h1:bZ9rKU2/V8sY+NulSfxDOnXTWcs1rySqdF1sVepihvo=,a2820e0f01d8c944b70c70515b9924f41b450f3688d19ad4d506b2b9b367c433
+github.com/couchbase/vellum,v0.0.0-20190111184608-e91b68ff3efe,h1:2o6Y7KMjJNsuMTF8f2H2eTKRhqH7+bQbjr+D+LnhE5M=,06e3ca28a98c95bcdfd909168e1dcf45a6667ef59ad59112a01e6bbdcf591e84
+github.com/couchbaselabs/go-couchbase,v0.0.0-20190708161019-23e7ca2ce2b7,h1:1XjEY/gnjQ+AfXef2U6dxCquhiRzkEpxZuWqs+QxTL8=,3429eb55dd38b07bab5e9a57a3e2451449b49bdbc6f16585f8b7557067572499
+github.com/cpu/goacmedns,v0.0.1,h1:GeIU5chKys9zmHgOAgP+bstRaLqcGQ6HJh/hLw9hrus=,12acca48bb444f3832a87b8d238e573bbfa60e5c25dfcf6787a003dfacaf055d
+github.com/cpuguy83/go-md2man,v1.0.10,h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=,b9b153bb97e2a702ec5c41f6815985d4295524cdf4f2a9e5633f98e9739f4d6e
+github.com/cpuguy83/go-md2man/v2,v2.0.0,h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=,f2fdd06287a80f1bea5552f572d7f2314ec829285a3040b63469e0635f66fb6d
+github.com/creack/goselect,v0.1.0,h1:4QiXIhcpSQF50XGaBsFzesjwX/1qOY5bOveQPmN9CXY=,24d8028970032b1a45091ad8ff9b9c280693def1433cb5948ed92c0c975226ea
+github.com/creack/pty,v1.1.7,h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A=,e7ea3403784d186aefbe84caed958f8cba2e72a04f30cdb291ece19bec39c8f3
+github.com/cskr/pubsub,v1.0.2,h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0=,39e40a42c10058c188f331ed0bb660a0504d7c2ddd9e835a9970786fdc35feb0
+github.com/cupcake/rdb,v0.0.0-20161107195141-43ba34106c76,h1:Lgdd/Qp96Qj8jqLpq2cI1I1X7BJnu06efS+XkhRoLUQ=,019a246ac0d7f6fcf3758587a031767730cfb824003c311686a4eb552a1dcc57
+github.com/cweill/gotests,v1.5.3,h1:k3t4wW/x/YNixWZJhUIn+mivmK5iV1tJVOwVYkx0UcU=,7ced96d4223a0afcd41922c4d3ae064493dd5bedbc72f6541716fce1cab24b7d
+github.com/cxr29/aliyun-openapi-go-sdk,v0.0.0-20151123082822-0b043e4d1e0c,h1:WEWetvNRZlk7JW3M4fycSA3f/2xZGxRdrwmpgRkGoQc=,6c80128745e3acdd01f59bc6c6e3a1f24193e89eb627ad6dcc615e763878b6e4
+github.com/cyphar/filepath-securejoin,v0.2.2,h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=,d022873dbb9e8d3b7a43c9dedbea54dfc9a6c15f9632ba522a1257e8b948c100
+github.com/cznic/b,v0.0.0-20181122101859-a26611c4d92d,h1:SwD98825d6bdB+pEuTxWOXiSjBrHdOl/UVp75eI7JT8=,1c34b27ce98f70cb0e97c2bbe0bdae216cc1ea6b2617b0e984e2ce30adc06338
+github.com/cznic/fileutil,v0.0.0-20181122101858-4d67cfea8c87,h1:94XgeeTZ+3Xi9zsdgBjP1Byx/wywCImjF8FzQ7OaKdU=,109b4c91722a0f9a4f941d77eff34270684e53ca36e7d14ab2cd4a4e80841d73
+github.com/cznic/golex,v0.0.0-20181122101858-9c343928389c,h1:G8zTsaqyVfIHpgMFcGgdbhHSFhlNc77rAKkhVbQ9kQg=,d2b11a6e0e1de5125a2d550650b4cbb7bf44280ebf1cda74ef4a63e3cfa11012
+github.com/cznic/internal,v0.0.0-20181122101858-3279554c546e,h1:58AcyflCe84EONph4gkyo3eDOEQcW5HIPfQBrD76W68=,bc177d001529bca3f46aa84855db4e783a041c188d3ba237f68fa4522bdca74b
+github.com/cznic/kv,v0.0.0-20181122101858-e9cdcade440e,h1:8ji4rZgRKWMQUJlPNEzfzCkX7yFAZFR829Mrh7PXxLA=,4f992bdaf6d17487c7b16669b6d55afa76b321e63f8e4b6a6d1126b44b18b0d9
+github.com/cznic/lldb,v1.1.0,h1:AIA+ham6TSJ+XkMe8imQ/g8KPzMUVWAwqUQQdtuMsHs=,ddec7228568547a5fbfbc6a91208cbcafeed4338a38c41d483448957e4bec186
+github.com/cznic/mathutil,v0.0.0-20181122101859-297441e03548,h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso=,8f69a36f60d885e011b0a90b91246a7e88223cb2883dc6e71eab3f42d653231b
+github.com/cznic/parser,v0.0.0-20181122101858-d773202d5b1f,h1:DUtr2TvhM9rmiHKVJWoLqDY2+MdxljW9hlaS/oYoi1c=,18b746a4090720bd9dfe219d0f7bb7fb28565df70417208d7e99dfd79f1ea264
+github.com/cznic/ql,v1.2.0,h1:lcKp95ZtdF0XkWhGnVIXGF8dVD2X+ClS08tglKtf+ak=,05164e379d43eaada0efdd763a50a9ef8f4b7f73a5de7ab866093bb25a4fb747
+github.com/cznic/sortutil,v0.0.0-20181122101858-f5f958428db8,h1:LpMLYGyy67BoAFGda1NeOBQwqlv7nUXpm+rIVHGxZZ4=,67783879c1ae4472fdabb377b1772e4e4c5ced181528c2fc4569b565cb47a57b
+github.com/cznic/strutil,v0.0.0-20181122101858-275e90344537,h1:MZRmHqDBd0vxNwenEbKSQqRVT24d3C05ft8kduSwlqM=,867902276444cbffca84d9d5f63754e8b22092d93a94480d8dfebd234ac8ffbd
+github.com/cznic/y,v0.0.0-20181122101901-b05e8c2e8d7b,h1:gvFsf4zJcnW6GRN+HPGTxwuw+7sTwzmoeoBQQCZDEnk=,8c84f5e4f9dc5f0809d8ad22d057e404c3e8644dc28e8fc52abbb1d2350f8d3e
+github.com/cznic/zappy,v0.0.0-20181122101859-ca47d358d4b1,h1:ytLS5Cgkxq6jObotJ+a13nsejdqzLFPliDf8CQ8OkAA=,505c19b52924ee21b65611bc45640d3ff4671e50ee04f7c17c38342190645595
+github.com/d2g/dhcp4,v0.0.0-20170904100407-a1d1b6c41b1c,h1:Xo2rK1pzOm0jO6abTPIQwbAmqBIOj132otexc1mmzFc=,15df9468cf548a626e1319e92d550432512c4319cf555bf278ea9215de3504e3
+github.com/daaku/go.zipexe,v1.0.0,h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY=,74d7a0242c03c3c03220e56a59da5f97d3478743250740df538e05e6b609f553
+github.com/danwakefield/fnmatch,v0.0.0-20160403171240-cbb64ac3d964,h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=,f601e8d25a43ed32e00851e1686a93b0175dadea8f4e32c8af2f1533f20736bc
+github.com/dave/jennifer,v1.2.0,h1:S15ZkFMRoJ36mGAQgWL1tnr0NQJh9rZ8qatseX/VbBc=,85b37a1b99b7d67664389b8c11b7174f521a396bb59d4e0e766df16336a7f112
+github.com/dave/services,v0.1.0,h1:7isGzpZHJWmOYTV+Pn3f6gpQUmrveJqsQpAkH0HXFbU=,e52a7ffba3aa07cca4888e08248771211abd139928b5cde9b228a61da88eddcc
+github.com/davecgh/go-spew,v1.1.1,h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=,6b44a843951f371b7010c754ecc3cabefe815d5ced1c5b9409fb2d697e8a890d
+github.com/davecgh/go-xdr,v0.0.0-20161123171359-e6a2ba005892,h1:qg9VbHo1TlL0KDM0vYvBG9EY0X0Yku5WYIPoFWt8f6o=,11cb87912b5288e13534cb396935694c257eb9164ffc20ce21e3bc9955edd82a
+github.com/daviddengcn/go-colortext,v0.0.0-20180409174941-186a3d44e920,h1:d/cVoZOrJPJHKH1NdeUjyVAWKp4OpOT+Q+6T1sH7jeU=,159d727adf4f0763ec3dc6156fd46531a2afbffdc17feeb6b5ffe2eb54b35d41
+github.com/davyxu/cellnet,v4.1.0+incompatible,h1:zDRqhkFRhBTD7ajra2888aoRLN1qlv8LV8+qHg/emO4=,f085f088b68b2e379a6dc37501ef2c9809836cfac147a30ed3025571c2d57df7
+github.com/davyxu/golog,v0.1.0,h1:SsV3m2x37sCzFaQzq5OHc5S+PE2VMiL7XUx34JCa7mo=,a3c240bc4b958fa4b4e73caa59c28fc658afbabdb1f28b237874803ca96dcb1f
+github.com/dchest/blake256,v1.0.0,h1:6gUgI5MHdz9g0TdrgKqXsoDX+Zjxmm1Sc6OsoGru50I=,9a9ed00a3024f2f7480b59c7b2ee1013cae3026d7dc2f065ce225dcce8cf357e
+github.com/dchest/siphash,v1.2.1,h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4=,877a468e533e28c777c59b3dfea175b38a1f0bc1f8551e3a9e1739b1821c7e3e
+github.com/dchest/uniuri,v0.0.0-20160212164326-8902c56451e9,h1:74lLNRzvsdIlkTgfDSMuaPjBr4cf6k7pwQQANm/yLKU=,41db9fb52a841d11d8592a1d4f56e8a440e3991b699ae0f95ab5f5a7b2aeb24c
+github.com/deckarep/golang-set,v1.7.1,h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=,86606609df42529fda55a15475b495f993f0c1cc4be6e1e50a9165a514d1ed71
+github.com/decker502/dnspod-go,v0.2.0,h1:6dwhUFCYbC5bgpebLKn7PrI43e/5mn9tpUL9YcYCdTU=,381fb0bb29ac973f318db3d464f76e5d3016d4963c78ccd7df7dbc4231a68455
+github.com/decred/base58,v1.0.0,h1:BVi1FQCThIjZ0ehG+I99NJ51o0xcc9A/fDKhmJxY6+w=,75b1a2c78759ee2e8755156806ce770c9199464c2d58541388d5ec7c000c99e1
+github.com/decred/dcrd/chaincfg,v1.5.1,h1:u1Xbq0VTnAXIHW5ECqrWe0VYSgf5vWHqpSiwoLBzxAQ=,7344cd4dc90a82342c90811c8180b1fef6c79e9c49caa38135f271cf0ecb056f
+github.com/decred/dcrd/chaincfg/chainhash,v1.0.2,h1:rt5Vlq/jM3ZawwiacWjPa+smINyLRN07EO0cNBV6DGU=,a8b24e2c4e64015430b8a6502f9e8c3eeea246021638884dc510508eccda31a0
+github.com/decred/dcrd/chaincfg/v2,v2.0.2,h1:VeGY52lHuYT01tIGbvYj+OO0GaGxGaJmnh+4vGca1+U=,906dec975cf574c55f2eb588dc91a4ddd6be273eaddfbeb45288ea6aebcc6306
+github.com/decred/dcrd/crypto/blake256,v1.0.0,h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=,cd8bbdae14641f0ba44430fc66990dd37bbfcf1e21a965a9fd1871d16cac127d
+github.com/decred/dcrd/dcrec,v1.0.0,h1:W+z6Es+Rai3MXYVoPAxYr5U1DGis0Co33scJ6uH2J6o=,a1e16c5ef3633f2dfa23c052778552cf9300821197f5b2dc547e20dd9d45756b
+github.com/decred/dcrd/dcrec/edwards,v1.0.0,h1:UDcPNzclKiJlWqV3x1Fl8xMCJrolo4PB4X9t8LwKDWU=,7ed52f3316f5a47c5925e23bebf5016ecfd75e7ac340714b4b94b0e25bdf0611
+github.com/decred/dcrd/dcrec/secp256k1,v1.0.2,h1:awk7sYJ4pGWmtkiGHFfctztJjHMKGLV8jctGQhAbKe0=,5fa2c17fd611665a39e6435283445ec3b46a5b52d14661e04bd1f7ef295ba9d3
+github.com/decred/dcrd/dcrutil,v1.4.0,h1:xD5aUqysGQnsnP1c9J0kGeW8lDIwFGC3ja/gE3HnpCs=,6de50428375fca174f4861f8aa45549360e7733bca0184a882448f0b9f94be2e
+github.com/decred/dcrd/dcrutil/v2,v2.0.0,h1:HTqn2tZ8eqBF4y3hJwjyKBmJt16y7/HjzpE82E/crhY=,fa91eb7c5062e0f3f6e7d1b9d8e1a89698f6ee6e7f8f4941929f6d89a293ec76
+github.com/decred/dcrd/wire,v1.3.0,h1:X76I2/a8esUmxXmFpJpAvXEi014IA4twgwcOBeIS8lE=,e17b78d19d0056503627826a0e599ed14a7a4fc8aa2c31c47b12ffc1864aedb1
+github.com/decred/slog,v1.0.0,h1:Dl+W8O6/JH6n2xIFN2p3DNjCmjYwvrXsjlSJTQQ4MhE=,1c27399a3f38fb7b581f4dbe11a0b3e3d5d8afcc8109880771c0e44135388bb0
+github.com/denisenkom/go-mssqldb,v0.0.0-20191001013358-cfbb681360f0,h1:epsH3lb7KVbXHYk7LYGN5EiE0MxcevHU85CKITJ0wUY=,ff2349c73cee9e54cd61e85af75d7d0537fb5f070da5a737b5abede1f7d579ac
+github.com/denkhaus/bitshares,v0.6.1-0.20190502142618-5ae8c00cb394,h1:PpFS6pvAoRwH13WlqnX/mrxesu6LNFtiVwoWgfNLCeY=,af76695d3e546cad6a8b56d9d5e431bfeb12bfce643a395fb45d8827409dd9ff
+github.com/denkhaus/gojson,v1.0.0,h1:p1hAlN/yAvRvzbdO1HNDQvmBslfyk64IMt3O3DtftPU=,5c0d8d98a53be88e2801d90124e28ba781d2c6a09aaf9a57272df92c5c0e0fe2
+github.com/denkhaus/logging,v0.0.0-20180714213349-14bfb935047c,h1:imM7UU8JD1sNuk2tVEk3QvrY2RZ5f/DOB+UA7c5ThGs=,5a1bb81f35dc7847b0cb8efe3f1e3bac3a34c9f11950a7c7643115c952fa3166
+github.com/denverdino/aliyungo,v0.0.0-20170926055100-d3308649c661,h1:lrWnAyy/F72MbxIxFUzKmcMCdt9Oi8RzpAxzTNQHD7o=,e6ca432bab5a7b1d233c9c1495d32668d31b18803d65f3af27f1d8240b6547d4
+github.com/detached/gorocket,v0.0.0-20170629192631-d44bbd3f26d2,h1:zwp9mAr+YvsgLCFIVJ3/m61Z+NRX35jbD0HBa62ryHY=,f54c9dc20ba925f0b2a726cc1a22466c6e05d7e0080f6e4b5f26e60c15938712
+github.com/detailyang/go-fallocate,v0.0.0-20180908115635-432fa640bd2e,h1:lj77EKYUpYXTd8CD/+QMIf8b6OIOTsfEBSXiAzuEHTU=,dcc45102d034d78825d1aa9d2f61720b4b0d9f76314a7a53b32cf032713a0bde
+github.com/devfeel/dotweb,v1.7.3,h1:tt7YtCIp9JPmAS2yksVIsw6CiUkUSz3kVLSiCzRaWDw=,7cdb6d4872bb4c82fc333722fb2be3e39fe391b121550421d240d3008c8e00a0
+github.com/devigned/tab,v0.1.1,h1:3mD6Kb1mUOYeLpJvTVSDwSg5ZsfSxfvxGRTxRsJsITA=,528e21b578f28a998453551c51abfdeed154c981486d49a8ad7c149743ea450f
+github.com/dghubble/oauth1,v0.6.0,h1:m1yC01Ohc/eF38jwZ8JUjL1a+XHHXtGQgK+MxQbmSx0=,6d4be6cfc2771fab15e47d2aa9c40d347dab7166f2cae3c248aeb51b10c88b4a
+github.com/dghubble/sling,v1.3.0,h1:pZHjCJq4zJvc6qVQ5wN1jo5oNZlNE0+8T/h0XeXBUKU=,880e7f44ee68eae979a34afb2f95ab1c7555712153c45be01d15cbc5991a5fe6
+github.com/dgraph-io/badger,v1.6.0,h1:DshxFxZWXUcO0xX476VJC07Xsr6ZCBVRHKZ93Oh7Evo=,8329ae390aebec6ae360356e77a2743357ad4e0d0bd4c3ae03b7d17e01ad70aa
+github.com/dgraph-io/dgo,v1.0.0,h1:DRuI66G+j0XWDOXly4v5PSk2dGkbIopAZIirRjq7lzI=,dae0ee7690b0c58d72be328263d55394f88a4924a8274017021736d702be9cee
+github.com/dgrijalva/jwt-go,v3.2.0+incompatible,h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=,26b028eb2d9ee3aef26a96d6790e101f4088ef901008ebab17096966bf6522ad
+github.com/dgryski/go-farm,v0.0.0-20190423205320-6a90982ecee2,h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=,d1fb60f1ce562acb07569d53b43353b73f439911c27eecef716305cd2d730258
+github.com/dgryski/go-jump,v0.0.0-20170409065014-e1f439676b57,h1:qZNIK8jjHgLFHAW2wzCWPEv0ZIgcBhU7X3oDt/p3Sv0=,92666f8caf4843c5a9b6bdb0f48f261922595683351958b0909884adf064cfb2
+github.com/dgryski/go-metro,v0.0.0-20180109044635-280f6062b5bc,h1:8WFBn63wegobsYAX0YjD+8suexZDga5CctH4CCTx2+8=,3f97b3cdeaee7b4fbf4fa06b7c52e3ee6bca461a100077892e861c6c8fc03722
+github.com/dgryski/go-sip13,v0.0.0-20190329191031-25c5027a8c7b,h1:Yqiad0+sloMPdd/0Fg22actpFx0dekpzt1xJmVNVkU0=,81d318bf94b85b240278c35d7ef6015510751e31ffa89eb6287d6d236493551e
+github.com/digitalocean/go-libvirt,v0.0.0-20190626172931-4d226dd6c437,h1:phR13shVFOIpa1pnLBmewI9p16NEladLPvVylLPeexo=,7748e819d19524170969d2a470c212bb3936778ff630f833adc286e8c21e37cc
+github.com/digitalocean/go-qemu,v0.0.0-20181112162955-dd7bb9c771b8,h1:N7nH2py78LcMqYY3rZjjrsX6N7uCN7sjvaosgpXN9Ow=,7530507881e53214ed3c0fb770fb3faed36a57ca6eb376bd2cec91a0e5d575a6
+github.com/digitalocean/godo,v1.11.1,h1:OsTh37YFKk+g6DnAOrkXJ9oDArTkRx5UTkBJ2EWAO38=,5d1ad5b25ad252fb1a02366087fe6e94845ec2dce64dc6e875ed3253a7e0f8ff
+github.com/dimchansky/utfbom,v1.1.0,h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=,27fed73a62fcf06d4ceb28846e5d40786b7e81213aa0d1f4d840e89d25f285f7
+github.com/dimfeld/httppath,v0.0.0-20170720192232-ee938bf73598,h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI=,ff59ff07643eccf8a166cc9693fbd18c42869e0bfcc0a9c979435847a7ae4fb1
+github.com/dimfeld/httptreemux,v5.0.1+incompatible,h1:Qj3gVcDNoOthBAqftuD596rm4wg/adLLz5xh5CmpiCA=,031da29a128234db595fdce84301cfe5ff13b4be03c1e344cfe7daadb68559e9
+github.com/disintegration/gift,v1.2.1,h1:Y005a1X4Z7Uc+0gLpSAsKhWi4qLtsdEcMIbbdvdZ6pc=,d9a688a552dc8f5b2319325541e2bbc5c0af66b6e78273058893b259fcca5a0f
+github.com/disintegration/imaging,v1.6.1,h1:JnBbK6ECIZb1NsWIikP9pd8gIlTIRx7fuDNpU9fsxOE=,209474c4c0348672c6747a7a73ff887a6d9458b67df78ff342ee3fd628156412
+github.com/djherbis/atime,v1.0.0,h1:ySLvBAM0EvOGaX7TI4dAM5lWj+RdJUCKtGSEHN8SGBg=,fe677e5c1a8bb168904c0856010bed33a770d49eda9edc6dc1b567940bf20afc
+github.com/dlclark/regexp2,v1.2.0,h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=,61054c243455e034d7a81e2f6a888cab5a81056a0cc43463cb3536b42cfe7cc1
+github.com/dmotylev/goproperties,v0.0.0-20140630191356-7cbffbaada47,h1:sP2APvSdZpfBiousrppBZNOvu+TE79Myq4kkmmrtSuI=,8afdf7b2989dff361cc80e560c1bd17e5c4ad37826b5caf4b65af8e152cdc6cb
+github.com/dnaeon/go-vcr,v1.0.1,h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=,8f586f95ce5567ef2ae702cf98e56a09ea0cc6171f5cd959e6fcf7502e00dabc
+github.com/dnsimple/dnsimple-go,v0.30.0,h1:IBIrn9jMKRMwporIRwdFyKdnHXVmwy6obnguB+ZMDIY=,5821d521b402f93dc19f6eb332d5f4159800336f53626c6dedd99ce4c351a55a
+github.com/dnstap/golang-dnstap,v0.1.0,h1:hKtRrSTEHuTmG0vCLgKU8WJkXCARoAJMDrlXHTTPBK8=,fe23fd626917c7f45ead63cef4a4bd1bb366bb30ba5873d9ee5432e79b971349
+github.com/docker/cli,v0.0.0-20191031185610-968ce1ae4d45,h1:KJ4FsevlLR30Q2H1aCACmL3CEoUTAZf16PMAJj+ofXI=,145fef54aa162edc123d514ed7a20bc14564581ad95bb6aae7294c3c08df55fd
+github.com/docker/distribution,v2.7.1+incompatible,h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=,be78bc43d74873b67afe05a6b244490088680dab75bdfaf26d0fd4d054595bc7
+github.com/docker/docker,v1.13.1,h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo=,1decea9f21d4165bc134de72c51055612ff6992409cd56f3c35b7f78f3b542bd
+github.com/docker/docker-ce,v0.0.0-20180924210327-f53bd8bb8e43,h1:gZ4lWixV821UVbYtr+oz1ZPCHkbtE+ivfmHyZRgyl2Y=,d670d1c5faec51ee82dbc5d479a7fca60916c1b30547994c206622ab338a735a
+github.com/docker/docker-credential-helpers,v0.6.3,h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=,4dd2971b28524442b7a01e118a8040c3ab90eca50d55a7a232af514d18187324
+github.com/docker/engine-api,v0.4.0,h1:D0Osr6+45yAlQqLyoczv5qJtAu+P0HB0rLCddck03wY=,0db5d01c8401192b4eee6d2f9c34aa297d1a892f25230b470efd73f8f7ab59a4
+github.com/docker/go,v1.5.1-1,h1:hr4w35acWBPhGBXlzPoHpmZ/ygPjnmFVxGxxGnMyP7k=,fd626ee84b1eaea11c2a374fda5ed5ca8ad820bb4746ee31519efeb5038077b5
+github.com/docker/go-connections,v0.4.0,h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=,570ebcee7e6fd844e00c89eeab2b1922081d6969df76078dfe4ffacd3db56ada
+github.com/docker/go-events,v0.0.0-20190806004212-e31b211e4f1c,h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=,0f654eb0e7e07c237a229935ea3488728ddb5b082af2918b64452a1129dccae3
+github.com/docker/go-metrics,v0.0.1,h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=,4efab3706215f5b2d29ba823d3991fd6e2f81c02ce45ef0c73c019ebc90e020b
+github.com/docker/go-units,v0.4.0,h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=,0f2be7dce7b1a0ba6a4a786eb144a3398e9a61afc0eec5799a1520d9906fc58c
+github.com/docker/libkv,v0.2.1,h1:PNXYaftMVCFS5CmnDtDWTg3wbBO61Q/cEo3KX1oKxto=,7a0c81782d38b550acc2c0ef0ce397adfc13716f483be6a47d0b97fbc6eea0d5
+github.com/docker/libnetwork,v0.5.6,h1:hnGiypBsZR6PW1I8lqaBHh06U6LCJbI3IhOvfsZiymY=,7aea42c405304c495bf159e5004674eb503eb0120eb4c5d1275fdba65d88cc53
+github.com/docker/libtrust,v0.0.0-20160708172513-aabc10ec26b7,h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=,bf1c1230a3b5c0dadb2c9366aabc99181e708369d735dc83c3eb89f597f42adb
+github.com/docker/machine,v0.16.2,h1:jyF9k3Zg+oIGxxSdYKPScyj3HqFZ6FjgA/3sblcASiU=,1c13210831cafddba1abbf9ef034135233252c62927df396fee6fa0a45efcb43
+github.com/docker/notary,v0.6.1,h1:6BO5SNujR+CIuj2jwT2/yD6LdD+N9f5VbzR+nfzB5ZA=,439fd6664fb75323d78c5a362483f3375a6ac61a3dd08438a503df470a34f300
+github.com/docker/spdystream,v0.0.0-20160310174837-449fdfce4d96,h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=,70964f9eef29843634539b8d6e09c8b51ed6aa96b5deda28b7a44613327a22f2
+github.com/docker/swarmkit,v1.12.0,h1:vcbNXevt9xOod0miQxkp9WZ70IsOCe8geXkmFnXP2e0=,b9d09ff080beb0db2d4d4ebca93438dd080769266eb7aab6d5182e1ad7ba2c3a
+github.com/docopt/docopt-go,v0.0.0-20180111231733-ee0de3bc6815,h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=,00aad861d150c62598ca4fb01cfbe15c2eefb5186df7e5d4a59286dcf09556c8
+github.com/documize/community,v3.2.0+incompatible,h1:ilePrhqxjc+BWpDRsXPyLyMEE1BrGlqCPMg3T577mzQ=,e9e06bdbef4500c0d2cc609164fe23bc05f8234c2c8483c8c9bc3ffffe22bbf7
+github.com/dogmatiq/dogma,v0.6.0,h1:HdJ0cTcORIxZRTB5Z7RdsBXEr18gB3so7FMIHYiAhEQ=,db91004377004aa3c5f0c462205beea995e93a0be13d7d99d3232dc03209f65c
+github.com/donovanhide/eventsource,v0.0.0-20171031113327-3ed64d21fb0b,h1:eR1P/A4QMYF2/LpHRhYAts9wyYEtF7qNk/tVNiYCWc8=,2b911efc5101522ce50399cd7831ef931896541893955441168783666811a1d1
+github.com/dop251/goja,v0.0.0-20190912223329-aa89e6a4c733,h1:cyNc40Dx5YNEO94idePU8rhVd3dn+sd04Arh0kDBAaw=,485156ad52ca9651f728a6039af63f9f11c5bf49846e513635d5fa35d8d39097
+github.com/dotcloud/docker,v1.13.1,h1:jjwxeyQYDwROaGy/YEodF+srQW5hJAnNnaTcfcKoU+0=,83884e41d26b32eae2387080b245792ac8fc0200f645aef02656cb5e4b3d0595
+github.com/drone/go-scm,v1.6.0,h1:PZZWLeSHHwdc6zbSQpg9n0CNoRB+8DAINzX9X/wJifY=,e26d2bc63c53a66252ab24a1b45ced06825bb4101cbd746c581683cf39e520b6
+github.com/dsnet/compress,v0.0.0-20171208185109-cc9eb1d7ad76,h1:eX+pdPPlD279OWgdx7f6KqIRSONuK7egk+jDx7OM3Ac=,25f6bcccb4c1cf6d97ad69253a394bd0a52a633caa623d75b30729aed495a73d
+github.com/dsnet/golib/unitconv,v0.0.0-20190531212259-571cdbcff553,h1:mE6azeVhLnKfk6DH3Zcg56L87yJ/uv9HZ5YJOQcPC4s=,603b60f7278fe7299f59d716da2bd287441f1321b5a663828d894e67bc274bed
+github.com/duosecurity/duo_api_golang,v0.0.0-20190308151101-6c680f768e74,h1:2MIhn2R6oXQbgW5yHfS+d6YqyMfXiu2L55rFZC4UD/M=,75c90bdd92362e2cc36297193a543fe0cd75c07f82182940ad6158a1d470cc8b
+github.com/dustin/go-humanize,v1.0.0,h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=,e01916e082a6646ea12d7800d77af43045c27284ff2a0a77e3484509989cc107
+github.com/dylanmei/iso8601,v0.1.0,h1:812NGQDBcqquTfH5Yeo7lwR0nzx/cKdsmf3qMjPURUI=,1e682968bfcac2115e1fd706ec6bd09a0b676d7d224514d8f8dff9cadbf87e79
+github.com/dylanmei/winrmtest,v0.0.0-20190225150635-99b7fe2fddf1,h1:r1oACdS2XYiAWcfF8BJXkoU8l1J71KehGR+d99yWEDA=,5607cb987ec0a699003eeec5952f0280792fd5db7099ca277bdfae26e93b0ef3
+github.com/eapache/go-resiliency,v1.1.0,h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU=,a64ebe539335e126b30f79f0f00f39ffe083e794995500a67e0a2156b334788e
+github.com/eapache/go-xerial-snappy,v0.0.0-20180814174437-776d5712da21,h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=,785264afffdcfe50573a1cb0df85ff4186e9e7e4e3a04513752f52d3da1054af
+github.com/eapache/queue,v1.1.0,h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=,1dc1b4972e8505c4763c65424b19604c65c944911d16c18c5cbd35aae45626fb
+github.com/eclipse/paho.mqtt.golang,v1.2.0,h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t2y2qayIX0=,d36337c4b5a2752b91bcd437bd74e0907bf6c9e6c611dab88407bcca8462e918
+github.com/edgexfoundry/go-mod-core-contracts,v0.1.33,h1:lQbLbRhymV0/QDDDGU26idZ9Kv+Q0IETn81hLpHxi68=,a7a8792a8692d64daea343577a49934be6ba64acbe114b3c24262537b5a9157f
+github.com/edsrzf/mmap-go,v1.0.0,h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=,851a1d4d6e30f97ab23b7e4a6a7da9d1842f126d738f7386010c6ee7bf82518e
+github.com/edwingeng/doublejump,v0.0.0-20190102103700-461a0155c7be,h1:FnUE/uuuegwvhGE9z61q9krL5km5Mnwlusq3BT06yy8=,a9cb92422f0bbdd56c80d9873a8f7af6fd2d8d8154a7a11d7cb9232d9146f07c
+github.com/efarrer/iothrottler,v0.0.0-20141121142253-60e7e547c7fe,h1:WAx1vRufH0I2pTWldQkXPzpc+jndCOi2FH334LFQ1PI=,04291e6136b933fd2cdcc29f3af78090a9d678534a94823590eb63f1f318db1d
+github.com/efritz/backoff,v1.0.0,h1:r1DfNhA1J7p8kZ185J/hLPz2Bl5ezTicUr9KamEAOYw=,064d92e7f3e46079d158cac717e1c9bf96a230a5f31bf28940bd4a99bb91657e
+github.com/efritz/glock,v0.0.0-20181228234553-f184d69dff2c,h1:Q3HKbZogL9GGZVdO3PiVCOxZmRCsQAgV1xfelXJF/dY=,716200eb117905f4df509b7260869bb97bf8833c160d2ff1d328d01aa3874bc9
+github.com/eknkc/amber,v0.0.0-20171010120322-cdade1c07385,h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o=,b1dde9f3713742ad0961825a2d962bd99d9390daf8596e7680dfb5f395e54e22
+github.com/elastic/go-sysinfo,v1.0.1,h1:lzGPX2sIXaETeMXitXL2XZU8K4B7k7JBhIKWxdOdUt8=,fe0cd64aa3ac73edbb4240dcbcb660c4ec004f07c36371be6d78543c3b215d92
+github.com/elastic/go-windows,v1.0.0,h1:qLURgZFkkrYyTTkvYpsZIgf83AUsdIHfvlJaqaZ7aSY=,e487e6f1e269766b5815c36e93614b87a185ddc33f7a6f4bf23e5ee6d0d0e3c1
+github.com/elastic/gosigar,v0.10.5,h1:GzPQ+78RaAb4J63unidA/JavQRKrB6s8IOzN6Ib59jo=,a139252942b5ca82ddc3d9ced1daa262de0149a413149d3f0234b43dc3635acf
+github.com/elazarl/go-bindata-assetfs,v1.0.0,h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=,3aa225ae5ae4a8059a671fa656d8567f09861f88b88dbef9e06a291efd90013a
+github.com/elazarl/goproxy,v0.0.0-20191011121108-aa519ddbe484,h1:pEtiCjIXx3RvGjlUJuCNxNOw0MNblyR9Wi+vJGBFh+8=,6c224ac5720959a46f6d88e0b15dda732c7eb180b3103a826cf6d5459a5e112f
+github.com/elazarl/goproxy/ext,v0.0.0-20190711103511-473e67f1d7d2,h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM=,7244c1fe7490460503559e24e0e478540bc10481d1d8f3afd0a1f6b1a470b52f
+github.com/emicklei/go-restful,v2.11.1+incompatible,h1:CjKsv3uWcCMvySPQYKxO8XX3f9zD4FeZRsW4G0B4ffE=,9befcac63629841301235124e728206a96170afd83c78b632d271acafc9acccf
+github.com/emicklei/go-restful-swagger12,v0.0.0-20170926063155-7524189396c6,h1:V94anc0ZG3Pa/cAMwP2m1aQW3+/FF8Qmw/GsFyTJAp4=,07fd41dbe765b7d340df21d6353db8bef782f9b6742a93696b6f4133ef1d8955
+github.com/emicklei/proto,v1.6.15,h1:XbpwxmuOPrdES97FrSfpyy67SSCV/wBIKXqgJzh6hNw=,162ad34010e5f81ebed962a33c91ee6356e19631c7a7030bc9b173e85ca34678
+github.com/emirpasic/gods,v1.12.0,h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=,729ea0bda86bf801b61ff66eb019e5b9adc559cd217944abf10bb103fca573ee
+github.com/endophage/gotuf,v0.0.0-20151124190824-3b700e20e376,h1:rPyHFhsuPZMEJAe1Oj2vpRC8277wpDJJ+aabkmlHF1A=,2cd5e6d0e748e0625e8c4a08a3b9f74e311e6654a1c5411fa3a9720f5f67cf40
+github.com/envoyproxy/go-control-plane,v0.9.0,h1:67WMNTvGrl7V1dWdKCeTwxDr7nio9clKoTlLhwIPnT4=,07b3a43081c9e1cdccb95c657cba7f483d5099f9ce07b5e3f3e28ce557687521
+github.com/envoyproxy/protoc-gen-validate,v0.1.0,h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=,ec5261f3bbc426d71e2be4c76063ba12460c5d27845d630763e9e911ec4768af
+github.com/eoscanada/eos-go,v0.8.10,h1:QUwHRBHEFag/qyW4PR2S9++0se0V4LjPLk1/KsNtXlo=,f1c48e793d1c7864288871a944af4b4ee3363ad6ae5298e9c2f9f42202e6d77c
+github.com/erikstmartin/go-testdb,v0.0.0-20160219214506-8d10e4a1bae5,h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=,471feb426b2a7ec1df29cc21c66aef34c9e7aabea751328644d1362593983d21
+github.com/ernesto-jimenez/gogen,v0.0.0-20180125220232-d7d4131e6607,h1:cTavhURetDkezJCvxFggiyLeP40Mrk/TtVg2+ycw1Es=,1f3030cfc89653ba791ae312b19e420dc8eaf1bef51f59dca6aa390f3cd1f3d0
+github.com/etcd-io/bbolt,v1.3.3,h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM=,6630d7aad4b10f76aea88ee6d9086a1edffe371651cc2432edfd0de6beb99120
+github.com/ethantkoenig/rupture,v0.0.0-20180203182544-0a76f03a811a,h1:M1bRpaZAn4GSsqu3hdK2R8H0AH9O6vqCTCbm2oAFGfE=,8559344c496621c06b612453de587e8e4c45c0fbc348a955f8eda7ea2b3d09c8
+github.com/ethereum/go-ethereum,v1.9.6,h1:EacwxMGKZezZi+m3in0Tlyk0veDQgnfZ9BjQqHAaQLM=,778c9bf77dd96bfaf5c3ea84498611490999782fb37edf8257680e27dd8976e8
+github.com/euank/go-kmsg-parser,v2.0.0+incompatible,h1:cHD53+PLQuuQyLZeriD1V/esuG4MuU0Pjs5y6iknohY=,43cadfa5ab226f89ca7a715add32ba23c554a5dfafd3a55449856a6b7012f946
+github.com/evanphx/json-patch,v4.5.0+incompatible,h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=,5508e810685a5081a3e880aeb24e501bd87920241baa317bfb5f3946b4fa417c
+github.com/exoscale/egoscale,v0.18.1,h1:1FNZVk8jHUx0AvWhOZxLEDNlacTU0chMXUUNkm9EZaI=,8cb4f10504b54d31c71bc4a670171a074f7abbab67d939fd404b62ad36cb6aed
+github.com/facebookgo/atomicfile,v0.0.0-20151019160806-2de1f203e7d5,h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A=,3c9bdee73452cc12c2936b4050d638d36302a958091ceb49c45ffbaff8954218
+github.com/facebookgo/clock,v0.0.0-20150410010913-600d898af40a,h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw=,5d6b671bd5afef8459fb7561d19bcf7c7f378da9943722d36676735b3c6272fa
+github.com/facebookgo/ensure,v0.0.0-20160127193407-b4ab57deab51,h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ=,a96c69c2b5902e0383139ee7089877a5ae2ddcd4eba42a595d13b570907d3fdc
+github.com/facebookgo/freeport,v0.0.0-20150612182905-d4adf43b75b9,h1:wWke/RUCl7VRjQhwPlR/v0glZXNYzBHdNUzf/Am2Nmg=,0f717d7eb52e276aec2138a971b091cd04da95826c8f451a20e8e78c4bb8f915
+github.com/facebookgo/grace,v0.0.0-20160926231715-5729e484473f,h1:0mlfEUWnUDVZnqWEVHGerL5bKYDKMEmT/Qk/W/3nGuo=,79f9f73ef925d457d2b70d37b12c3cec97a2e84e73a932397d2f569ec8702ee7
+github.com/facebookgo/httpdown,v0.0.0-20160323221027-a3b1354551a2,h1:3Zvf9wRhl1cOhckN1oRGWPOkIhOketmEcrQ4TeFAoR4=,dbbccf963238c5f80c54edb19aeb016f486f42dcd922fc0be5b832af9449ca4b
+github.com/facebookgo/inject,v0.0.0-20161006174721-cc1aa653e50f,h1:jK9r9Ofgc/Yzdlod77G23LfYtwqAmkQCZ9MaP6779OI=,6292702ff520e1fb14231f29bb2639d8f39edc08de479d76757ad97dafbb9174
+github.com/facebookgo/stack,v0.0.0-20160209184415-751773369052,h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=,0afd18a8394caa29e94bd58a42e0d2be07939f9daf190a9ba2a947f9cbd4ba1a
+github.com/facebookgo/stats,v0.0.0-20151006221625-1b76add642e4,h1:0YtRCqIZs2+Tz49QuH6cJVw/IFqzo39gEqZ0iYLxD2M=,d87443825721dc1dd5c358cd9e55b917ee1c3b6b10ab9557375f59d563b628cb
+github.com/facebookgo/structtag,v0.0.0-20150214074306-217e25fb9691,h1:KnnwHN59Jxec0htA2pe/i0/WI9vxXLQifdhBrP3lqcQ=,3a9c84e9dc2b9960f1de3cc7a61d91fe2978e64e4e4859a9383259092ec91c5e
+github.com/facebookgo/subset,v0.0.0-20150612182917-8dac2c3c4870,h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y=,bb18c678177e1aaaae209a2de9c28b5b7acc34e58fe00517b847a9460bd42df2
+github.com/farsightsec/golang-framestream,v0.0.0-20190425193708-fa4b164d59b8,h1:/iPdQppoAsTfML+yqFSq2EBChiEMnRkh5WvhFgtWwcU=,084f0ac3684b180e3d87db3e7b36a412c750397fbf009579e126c304528c1738
+github.com/fatih/camelcase,v1.0.0,h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=,54664f64f1f24097b80c64b9f606cbe8d8bc410a755ce6cda4f45e46f1141984
+github.com/fatih/color,v1.7.0,h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=,6036f0b31167280b696b5efb43603e71bce31420fb3428afdf74a68bb3a3ebef
+github.com/fatih/structs,v1.1.0,h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=,a361ecc95ad12000c66ee143d26b2aa0a4e5de3b045fd5d18a52564622a59148
+github.com/fatih/structtag,v1.0.0,h1:pTHj65+u3RKWYPSGaU290FpI/dXxTaHdVwVwbcPKmEc=,347fce3911900f5947735c12ccb4c6fbe0199c6df040bcaa4d74a8587af896d0
+github.com/fd/go-nat,v1.0.0,h1:DPyQ97sxA9ThrWYRPcWUz/z9TnpTIGRYODIQc/dy64M=,bdf011af97da57ef3c58a091ae760eb885a6322faa3539d3c37bf76d4fff536a
+github.com/fernet/fernet-go,v0.0.0-20180830025343-9eac43b88a5e,h1:P10tZmVD2XclAaT9l7OduMH1OLFzTa1wUuUqHZnEdI0=,a484a3172222095507a7f1901a91ab741c28278ea6b878c21c1151c0fd40f46d
+github.com/flosch/pongo2,v0.0.0-20190707114632-bbf5a6c351f4,h1:GY1+t5Dr9OKADM64SYnQjw/w99HMYvQ0A8/JoUkxVmc=,814b52f668d2e2528fe9af917506cda4894d22c927283cfb8aaf6857503dfc5a
+github.com/flynn/go-shlex,v0.0.0-20150515145356-3f9db97f8568,h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=,ea68a1d391e59ebc04ce986b88e000327bb141e5e8e80ef93af950bca42bb4cc
+github.com/fogleman/gg,v1.3.0,h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=,792f7a3ea9eea31b7947dabaf9d5a307389245069078e4bf435d76cb0505439c
+github.com/forestgiant/sliceutil,v0.0.0-20160425183142-94783f95db6c,h1:pBgVXWDXju1m8W4lnEeIqTHPOzhTUO81a7yknM/xQR4=,bedd47c23670847642576777cc8b53b9dd8a5a8e7b0a6f2299ebc6fa3b7b6f00
+github.com/fortytw2/leaktest,v1.3.0,h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=,867e6d131510751ba6055c51e7746b0056a6b3dcb1a1b2dfdc694251cd7eb8b3
+github.com/francoispqt/gojay,v1.2.13,h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=,f41e3e4f3086400448dbce1c06c59f5848a6c5983e5466689965e3a2cabcba7c
+github.com/frankban/quicktest,v1.5.0,h1:Tb4jWdSpdjKzTUicPnY61PZxKbDoGa7ABbrReT3gQVY=,515b5b2b9320b2982193ad6bd118907aaab9ff62189870e00be459cc4097073c
+github.com/fsnotify/fsnotify,v1.4.7,h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=,1d09ad8f3dc41cb6e0288023b47272c1c9393ca411e48f4b5009bca6662dc3ad
+github.com/fsouza/fake-gcs-server,v1.2.0,h1:FZUL/EJlyAlHxpUWZs23ae4zNwBwmHM1p5TykkoP85A=,83b547a0780693f154c30137b1eeaf0c0e9628798ae4b7e1d74ebfb8efaf61fc
+github.com/fsouza/go-dockerclient,v1.5.0,h1:7OtayOe5HnoG+KWMHgyyPymwaodnB2IDYuVfseKyxbA=,c7025b816e0ba28041a88b1063003f4e31097346d06cf69811f9d55505d3d46c
+github.com/fullsailor/pkcs7,v0.0.0-20190404230743-d7302db945fa,h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU=,ba36a8fc855d6eecef329d26f8e82132e38d45d06f79f88d3b0bde6d718c8fb2
+github.com/fuyufjh/splunk-hec-go,v0.3.3,h1:7PLVIODblK9FXfuAy8iPZg0lcw1YNzSQHfC+0NYgUxU=,9517f63386f64e0dceca9352f45eb7f160452682a07fa04d3c1ff90eb19ac83d
+github.com/gabriel-samfira/sys,v0.0.0-20150608132119-9ddc60d56b51,h1:rUp9t/FbeJM3R3BSYkJfViN3CNQcmk44H20SqkJ/y+k=,1be262d101bd9079bb859639ad6d5eaee80646b6db0fcbeb7146d9381949d2a8
+github.com/gammazero/deque,v0.0.0-20190130191400-2afb3858e9c7,h1:D2LrfOPgGHQprIxmsTpxtzhpmF66HoM6rXSmcqaX7h8=,a1fe4ec3258f68685ee45b68e1d9188d79726af46a1b93281cf11ddc6045a864
+github.com/gammazero/workerpool,v0.0.0-20190406235159-88d534f22b56,h1:VzbudKn/nvxYKOdzgkEBS6SSreRjAgoJ+ZeS4wPFkgc=,cbb92fdf8d457e27923dc6515af4458a55af932ccf468415c8b36bf49845fc00
+github.com/garyburd/go-oauth,v0.0.0-20180319155456-bca2e7f09a17,h1:GOfMz6cRgTJ9jWV0qAezv642OhPnKEG7gtUjJSdStHE=,be051ba0d52eaced1c1985ebdf2dece3f7127ad392645b42fd06c2af9c9caea2
+github.com/garyburd/redigo,v1.6.0,h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc=,68f0d2b454f7a9a000c3335fc0f409123637e4711c6461a4c75e2f128f68f283
+github.com/gavv/monotime,v0.0.0-20161010190848-47d58efa6955,h1:gmtGRvSexPU4B1T/yYo0sLOKzER1YT+b4kPxPpm0Ty4=,c97324768edc8170e05b8925b0551778909c8e15817d4327ac405a4e0b6071f4
+github.com/gcash/bchd,v0.14.7,h1:n3gMXCT4VhU/emiCq61kmKBPADLxBzpX5IlXPnGuR2c=,871644f504d6c3f19dcfc8a7a6e6aa623e6642275a48dfffe770ec61368c2032
+github.com/gcash/bchlog,v0.0.0-20180913005452-b4f036f92fa6,h1:3pZvWJ8MSfWstGrb8Hfh4ZpLyZNcXypcGx2Ju4ZibVM=,d400c8e944edf2a67f46e75335f55c14170c523691804ea71e1a348ad45bc7e7
+github.com/gcash/bchutil,v0.0.0-20191012211144-98e73ec336ba,h1:KVa96lSrJGMYZ414NtYuAlbtCgrmW9kDnjvYXcLrr5A=,7b829a35d22ead0ee82d8a98b1e06da5e63fd07b2798fce8ba87c8da670ef04a
+github.com/gcla/gowid,v1.0.0,h1:78Xf5G9+lb4/g3KCB3hX8UJ8VorymMH5PXu9Npvwf8s=,eaa7e0b7bb0912c6b24c98dee0073a2de754c24e1347ce7c5bfc63397ccf0fa6
+github.com/gdamore/encoding,v1.0.0,h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=,638a9832e2f62d118d7c511d86bdae1622a51f331de48a01d929fd24ebe6a2a6
+github.com/gdamore/tcell,v1.3.0,h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM=,97c1e828ff9de0cef3a5bbdb3f3def8a351ad6ca65a780d4dd4141b0ee23c88e
+github.com/genuinetools/pkg,v0.0.0-20180910213200-1c141f661797,h1:SGpZXDd/CFeDIY4Rq5cFO8K/uqDblHUxjlzOmjFpvRg=,c15cbe95e0a7e38cc0a790b0098170c103ba84d56e7cbaf744a6df10c00efa45
+github.com/genuinetools/reg,v0.16.0,h1:ZhLZPT+aUGHLfy45Ub5FLWik+3Dij1iwaj8A/GyAZBw=,a505ff5357d6095540c89ee27d207a3a4dc7c73840fb6bc9a2f0f3a81e498341
+github.com/gernest/wow,v0.1.0,h1:g9xdwCwP0+xgVYlA2sopI0gZHqXe7HjI/7/LykG4fks=,b49d5efc34e19469e7319df09b35438de307ba7cd8c9333ecba190f457ca8e22
+github.com/getgauge/common,v0.0.0-20190514095629-619e107433ce,h1:/ofMj8gIhPYdb/JEXKj8iYe5Yxl3mrK8YA7yl/06t6Y=,04ab4fb7e8dcf693c3b79028693130cd51fe54f5a16f12622975a7c3eb7705f7
+github.com/getlantern/context,v0.0.0-20190109183933-c447772a6520,h1:NRUJuo3v3WGC/g5YiyF790gut6oQr5f3FBI88Wv0dx4=,27515ae761018c4cfc83043194904170bef0cac037c48ff96fc497502b9bab14
+github.com/getlantern/errors,v0.0.0-20190325191628-abdb3e3e36f7,h1:6uJ+sZ/e03gkbqZ0kUG6mfKoqDb4XMAzMIwlajq19So=,a48d7684463e8c496fea4a2595ca71012c3b222bc77de7c2ddfbe78bc4595ac5
+github.com/getlantern/fdcount,v0.0.0-20170105153814-6a6cb5839bc5,h1:8Q9iN/V24EG01IgXEKVScth/rTXpplBxCYio/yIKtUw=,b24c26d5ede197fd6b7f981cf5db300124e22f48667942c948a9750f7a908c94
+github.com/getlantern/golog,v0.0.0-20190830074920-4ef2e798c2d7,h1:guBYzEaLz0Vfc/jv0czrr2z7qyzTOGC9hiQ0VC+hKjk=,1eeabfbc56105f3d751e1947405f5296db5ded7e25900209fe7327f1b5d785e6
+github.com/getlantern/hex,v0.0.0-20190417191902-c6586a6fe0b7,h1:micT5vkcr9tOVk1FiH8SWKID8ultN44Z+yzd2y/Vyb0=,ea5a13f98a82c1919c59b655de531cbb35ac7dfff3c99072b43b8bfd1c29b774
+github.com/getlantern/hidden,v0.0.0-20190325191715-f02dbb02be55,h1:XYzSdCbkzOC0FDNrgJqGRo8PCMFOBFL9py72DRs7bmc=,c901f2e702114d6268446a381a27737c6123e50191197fd84f17b339238191b4
+github.com/getlantern/idletiming,v0.0.0-20190529182719-d2fbc83372a5,h1:laM1s/bxUH8xbbC9TBGWsOc7A0KCAPZMa4pdwO5e6Vw=,35de51b383e926042d3f8f4859e2d961582cf9964d3b7bb513ac4733cc43162f
+github.com/getlantern/mockconn,v0.0.0-20190403061815-a8ffa60494a6,h1:+aO65ByJw74kV8vXqvkj49P5RtIqyUObyeRTIxMz218=,a4a1ccdc9ec68dea571d9603d4a36150b6ccaea447ca88965e088ff0b9eeaa0d
+github.com/getlantern/mtime,v0.0.0-20170117193331-ba114e4a82b0,h1:1VNkP55LM/W2IwWN+qi+5X3gZcEQHfj8X9E+FNxVgM4=,5af0b20838a808b86a2a9c87c254d47185d38d5935780dade3bc7a54dc2880f4
+github.com/getlantern/netx,v0.0.0-20190110220209-9912de6f94fd,h1:mn98vs69Kqw56iKhR82mjk16Q1q5aDFFW0E89/QbXkQ=,cb386d0527fb6f549fa0266c770a68d7d83a88bab2194d25b55355f59198fdf0
+github.com/getlantern/ops,v0.0.0-20190325191751-d70cb0d6f85f,h1:wrYrQttPS8FHIRSlsrcuKazukx/xqO/PpLZzZXsF+EA=,321694d3d2f31415653a7b9d97a4a701f36f10ccfbbdb94449f1211137d6f215
+github.com/getsentry/raven-go,v0.2.0,h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=,eaffe69939612cd05f95e1846b8ddb4043655571be34cdb6412a66b41b6826eb
+github.com/gf-third/mysql,v1.4.2,h1:f1M5CNFUG3WkE07UOomtu4o0n/KJKeuUUf5Nc9ZFXs4=,14a08134ce02bd0d07667da91a89c9098d18bad8c790414e37aba906895a5a3e
+github.com/gf-third/yaml,v1.0.1,h1:pqD4ix+65DqGphU1MDnToPZfGYk0tuuwRzuTSl3g0d0=,6354a95d7faa222d2e653485bc9dd555aad61a75eb5a5f970de531391ed77a2f
+github.com/ghetzel/go-defaults,v1.2.0,h1:U1T64bxhBc6nVZ68QXch1hoHq43h6isqgbvG7kxY9Uc=,f339e441d08af3af184a21f518227db7c705851be82f3fcea611e762ebb633a1
+github.com/ghetzel/go-stockutil,v1.8.6,h1:VgqpePUGGXMHjgArUH5mSAYFC35aiFgkU/TdTU/ts80=,aa0cce06af82b7d1f98a20deaafd6997fa7c3d36fba9a204a34e5d91a2096fa0
+github.com/ghetzel/testify,v1.4.1,h1:wpJirdM+znAnxWruGDBdIys5aU+wGJHNUTkgEo4PYwk=,90206efc10ad71a33bf314ef768d16c6186d23ccb5aa8172663437d497dbfdd7
+github.com/ghetzel/uuid,v0.0.0-20171129191014-dec09d789f3d,h1:YVJe7KwVYazt90hCc/q2dYJVS3062AY6QdT6iHd+Kh8=,924f39fe83589fa269e652c8ca4f7b0dbc59023baada8a55c24692fe5223b67a
+github.com/ghodss/yaml,v1.0.1-0.20190212211648-25d852aebe32,h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=,9771720da98bbdd80dacdefb47b9a0e36faa75caa4745149d150325ba5390e4b
+github.com/gin-contrib/gzip,v0.0.1,h1:ezvKOL6jH+jlzdHNE4h9h8q8uMpDQjyl0NN0Jd7jozc=,e994ecc5881938978d6d031e3d0c1bc5968bfe5de2a307aed7c63aecba459ecd
+github.com/gin-contrib/sse,v0.1.0,h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=,512c8672f26405172077e764c4817ed8f66edc632d1bed205b5e1b8d282816ab
+github.com/gin-gonic/gin,v1.4.0,h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ=,b9bc661bf658179d53fee9e7c587eba4df8326d0c26ad29f785739a78313fc4b
+github.com/glacjay/goini,v0.0.0-20161120062552-fd3024d87ee2,h1:+SEORW3KptcFnlhTbn7N0drG3AFnrcmBDWDyQ3Bt06o=,061319068788a9eeef67d4e5cf84a87c4649005aaa4f37c983a868c357e3df3c
+github.com/gliderlabs/ssh,v0.2.2,h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=,f9f12d766ceeab9e2134504520de75819d1eeb6733b8b619b7bcd4aac4cca983
+github.com/globalsign/mgo,v0.0.0-20181015135952-eeefdecb41b8,h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is=,c07f09e0c93e6410076edfd621d2decbd361361c536c3e33ba097fa51708f360
+github.com/glycerine/go-unsnap-stream,v0.0.0-20180323001048-9f0cb55181dd,h1:r04MMPyLHj/QwZuMJ5+7tJcBr1AQjpiAK/rZWRrQT7o=,9a66d6f9bb1a268f4b824d6fe7adcd55dc17ed504683bdf2dbf67b32028d9b88
+github.com/glycerine/goconvey,v0.0.0-20190315024820-982ee783a72e,h1:SiEs4J3BKVIeaWrH3tKaz3QLZhJ68iJ/A4xrzIoE5+Y=,344fb699344a5ab09464c0283a65402ae0fe6bd6fac7d40e9c4d403cf4a7714f
+github.com/gmallard/stompngo,v1.0.12,h1:uj1Bl9o+dqn0qSR33xHmaKw21W5LzhWo4Q4hS1MCpQU=,88498e4da4e0f7f3923d758a464d53f550921617b1047643def2a973c86dfd03
+github.com/go-aah/forge,v0.8.0,h1:sk4Z523B9ay3JQF4At97U7kecB5yTIm0J2UM/qRVXbQ=,e883adcfb380d6187de84c59a0f8bb3b34931487151873d7a326a1b4df556e48
+github.com/go-acme/lego,v2.7.2+incompatible,h1:ThhpPBgf6oa9X/vRd0kEmWOsX7+vmYdckmGZSb+FEp0=,1a597873ff61c0fbdab6b4f1027141d2e8dbe739bd2018473559bec954f3e651
+github.com/go-acme/lego/v3,v3.1.0,h1:yanYFoYW8azFkCvJfIk7edWWfjkYkhDxe45ZsxoW4Xk=,fbb3cfe2619281c3ccd456b213b5f8c7bf695f82ecac6c97f747dc4159dfe4b2
+github.com/go-ble/ble,v0.0.0-20190521171521-147700f13610,h1:eWay3GzFqTJUEYN1BrbqdDTFeFUGmYLps8SQkn1D7Yo=,a5fb6440935dd7ef8bb3569bc7260bd1ad44e01d41bbb684dbb96cc677fb2234
+github.com/go-chassis/foundation,v0.0.0-20190621030543-c3b63f787f4c,h1:p+Y6yq7RwHmYjEr/vwdVYGacBqFCc2lPQfNRIC3vRIs=,db38c108455e57b3f8f062c22872554d5af9dfa03a723c9fea263a009f3002e6
+github.com/go-chassis/go-archaius,v0.24.0,h1:ubNgs3Rv067PI7t37ZJoIMaPPHIBWV+ni/e7XAdW1hU=,37b0c60692eaed91abd3d2c6a0fc9366a54882f3a6b5ef81f3cc20d14882a13d
+github.com/go-chassis/go-chassis,v1.7.3,h1:7fcfaE9Ij+oBbf2lHoHHIvxT9objtt1EHpwRPBUkDhw=,38f8393558528b0212674268f6dc507d5db716fc5745eff09bccf1cd98b86eb7
+github.com/go-chassis/go-chassis-config,v0.14.0,h1:OnM9sx2GalDC7vEIhPecRpQlVa8hz10NOB41+9tii5A=,afc7506eec8591a5ccbb08f073ba19312bc03d87ec15c1532f5daba02f090e00
+github.com/go-chassis/go-restful-swagger20,v1.0.1,h1:HdGto0xroWGK504XN0Um7JBc0OPMHDlWwedkd2mTGII=,2c41388f71dc766088fc3e47e91a2f8c2d7936e40f6a64afff53a12ef73e0d05
+github.com/go-chassis/paas-lager,v1.0.2-0.20190328010332-cf506050ddb2,h1:iORWPbIQ81tJPKWs9TNvcjCQnqvyTlL41F9ILgiTcyM=,a74c06554cf6835e98c4fa548a4aa3dcc317ca93567af893b89a4dba88b783af
+github.com/go-chat-bot/bot,v0.0.0-20191022130543-3da6cae45477,h1:JfUELmxvEz/MXI3/iSn2UcB/5CCAvMsxKi88j783ssk=,a059cd1d050747bd0adcd3d4ba91e12b0ace2c038187484726c3d551169d9fa4
+github.com/go-chat-bot/plugins,v0.0.0-20181006134258-491b3f9878d6,h1:qNYjVQnDwznjLk+OnNdczA5SXwEa/RwjPTZSQCKofF4=,b19527108aef487fa1f4856e354f4777644a574248cc7e891bacf1bfb38bd12d
+github.com/go-chat-bot/plugins-br,v0.0.0-20170316122923-eb41b30907dc,h1:v/poG4Y4O/z1cUm2cWxiIkFFgRsT3Fe1u1A33evx89g=,6b613e62d3f389f3d6f8f262903bc31c4f1eb4b3ca8d192606f78199b1af0d43
+github.com/go-check/check,v0.0.0-20190902080502-41f04d3bba15,h1:xJdCV5uP69sUzCIIzmhAw6EKKdVk3Tu48oLzM86+XPI=,93bbc1f982dd553e279fb4c7fbc060032096e2b5d0537385ae80247492a6433e
+github.com/go-chi/chi,v4.0.2+incompatible,h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs=,25c94ccd43f18002c2dd07e87da1dc393ff87d615441e559bda425ea0979715b
+github.com/go-cmd/cmd,v1.0.5,h1:IK23uTRWxq6UJnNWp8nKO7mVCwnPfbaxA2lhzEKfNj0=,2623aa43dbf68c24362bcfb7a216b83c2e7473d4a3e49e7955c3fa5f28b4974c
+github.com/go-delve/delve,v1.3.2,h1:K8VjV+Q2YnBYlPq0ctjrvc9h7h03wXszlszzfGW5Tog=,b8a250f2b3ef87da34fbfc655bb23a051b43672bea7a8abc4e083a2b214faf09
+github.com/go-errors/errors,v1.0.1,h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=,bdbee3143e1798eadff4df919479c28ec2d3299a97d445917bc64d6eb6a3b95a
+github.com/go-gl/gl,v0.0.0-20181026044259-55b76b7df9d2,h1:78Hza2KHn2PX1jdydQnffaU2A/xM0g3Nx1xmMdep9Gk=,499822d1b3bcc34b82df0fcc13ac9a0ea273c5d68b3e183e18fa76dab9793954
+github.com/go-gl/glfw,v0.0.0-20190409004039-e6da0acd62b1,h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=,96c694c42e7b866ea8e26dc48b612c4daa8582ce61fdeefbe92c1a4c46163169
+github.com/go-gl/mathgl,v0.0.0-20190713194549-592312d8590a,h1:yoAEv7yeWqfL/l9A/J5QOndXIJCldv+uuQB1DSNQbS0=,39948d90a5672c7866b5b1c01e9e8ce6c80c099306ed80e9e138350840f82110
+github.com/go-ini/ini,v1.49.0,h1:ymWFBUkwN3JFPjvjcJJ5TSTwh84M66QrH+8vOytLgRY=,4820559fd3640c6b5361a7077e8b5c1a4318a06a59df7a095cbf96514d46d432
+github.com/go-kit/kit,v0.9.0,h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=,f3da9b35b100dd32e7b10c37a0630af60d54afa37c61291e7df94bc0ac31ed03
+github.com/go-ldap/ldap,v3.0.3+incompatible,h1:HTeSZO8hWMS1Rgb2Ziku6b8a7qRIZZMHjsvuZyatzwk=,4197e5fbebc7a1805be236cf75dea301f0b8e15a857e2373653b76157c649f93
+github.com/go-log/log,v0.1.0,h1:wudGTNsiGzrD5ZjgIkVZ517ugi2XRe9Q/xRCzwEO4/U=,ec5845d33a6d7ede81970833cfc3179d53b99019da1ebffef5e71005ff94be43
+github.com/go-logfmt/logfmt,v0.4.0,h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=,d678198dc0eeaed28736e0d71b919a0bd98501b7275c69a7917122f6de9e0d1c
+github.com/go-logr/logr,v0.1.0,h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg=,4c14b7c05eaa48b7f8dbf2ca38c3603dce446f4184a4c0af2f569b046d66201e
+github.com/go-logr/zapr,v0.1.0,h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54=,7b60c74f722b8f215711503dd63576845987eff81ef5f9dc052fc9158d1c57e2
+github.com/go-macaron/binding,v1.0.0,h1:ILEIP1e9GaXz//fZIl1zXgHVbM9j1SN89aTGOq8340Y=,3887f50d442cd8f9eeeb0e7710c7cba41c185d8e5a82404ff33e7cbd4e16d0c7
+github.com/go-macaron/cache,v0.0.0-20151013081102-561735312776,h1:UYIHS1r0WotqB5cIa0PAiV0m6GzD9rDBcn4alp5JgCw=,a854b7844fff9ec69025db12a2b03834a2eac570a366962c4eb83984813a9fdb
+github.com/go-macaron/captcha,v0.0.0-20190710000913-8dc5911259df,h1:MdgvtI3Y1u/DHNj7xUGOqAv+KGoTikjy8xQtCm12L78=,fb1c643c72ba9ef2c5d613e324e47dbb17ce45a28cbee8cb540ea48a0b3d6a23
+github.com/go-macaron/cors,v0.0.0-20190418220122-6fd6a9bfe14e,h1:auESkcVctNZnNl4EH0TuoCSJMJ7Q7ShU8FS6lDEsAC4=,0f3043631d54efca5615fe7ed819523bbe0c18726ce9e4b0cdc0ef2879aa6044
+github.com/go-macaron/csrf,v0.0.0-20180426211211-503617c6b372,h1:acrx8CnDmlKl+BPoOOLEK9Ko+SrWFB5pxRuGkKj4iqo=,90b5cbd86ff3708d41be70ad3cde77fdedd5ef485b960cc3a9ffea6f0a14902c
+github.com/go-macaron/gzip,v0.0.0-20191101043656-b5609500c6fc,h1:z3gfrCJUPhdRHtd8kftnNBzI5ayZ1zQhWARPeL83JNQ=,dfcc1200b66bcb581c6984da9fa4aefc92facc3a07d182c7c37f0978b41b868f
+github.com/go-macaron/i18n,v0.0.0-20160612092837-ef57533c3b0f,h1:wDKrZFc9pYJlqFOf7EzGbFMrSFFtyHt3plr2uTdo8Rg=,6c1d5fe7ed23e05ca1af7462e6deac2d993ddacd099ad794faad5c685337742d
+github.com/go-macaron/inject,v0.0.0-20160627170012-d8a0b8677191,h1:NjHlg70DuOkcAMqgt0+XA+NHwtu66MkTVVgR4fFWbcI=,666bb04a5df1271326b4fcdbbdc3276400ae7e54f4ed6233792cd6e519676491
+github.com/go-macaron/session,v0.0.0-20191101041208-c5d57a35f512,h1:7ndsXTX42iYHryQz98zUsBJfStJ0kXFKgDrPmRvR400=,3581a7eb19a2a60d41aba7e85afa576c35a97659e162b83292ff67396f899845
+github.com/go-macaron/toolbox,v0.0.0-20180818072302-a77f45a7ce90,h1:3wYKrRg9IjUMfaf3H0Hh7M5Li9ge79Y7aw2yujHa2jQ=,43f2a06502408404c3b1231c3642693632cf20bc4f2cb45881bd2292b1eed714
+github.com/go-martini/martini,v0.0.0-20170121215854-22fa46961aab,h1:xveKWz2iaueeTaUgdetzel+U7exyigDYBryyVfV/rZk=,0561a4dadd68dbc1b38c09ed95bbfc5073b0a7708b9a787d38533ebd48040ec2
+github.com/go-mesh/openlogging,v1.0.1,h1:6raaXo8SK+wuQX1VoNi6QJCSf1fTOFWh7f5f6b2ZEmY=,3606bad571f959cc24382381f7d50fb321819958df37911f6ad6aa5ac3e02181
+github.com/go-ole/go-ole,v1.2.4,h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=,c8b3ef1187d2d7dbfddc4badefcc992c029cd377ae07bff2fa05ec8972836612
+github.com/go-openapi/analysis,v0.19.5,h1:8b2ZgKfKIUTVQpTb77MoRDIMEIwvDVw40o3aOXdfYzI=,22e5ff3f88802059aa86835d8f7c25386afed1159d4e951ef0f87ef62ab4a253
+github.com/go-openapi/errors,v0.19.2,h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY=,e02e448e5a2c1ff2a011f74d41d505a2f32b369551064940630d6660c600bf3d
+github.com/go-openapi/inflect,v0.19.0,h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=,fbcca36e347a2f560f50ac1c9c63f7d6cd97c8dff9800f08f370b5ce09b77c57
+github.com/go-openapi/jsonpointer,v0.19.3,h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=,1fe6122c9c9d10837439398976a2ff55e8ed905fa7e4a66f3fb0e857c6e06582
+github.com/go-openapi/jsonreference,v0.19.2,h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=,00b2457c2d091a9817f91f55655a334bed8f75b2d6499ba9192f12564dd51dd9
+github.com/go-openapi/loads,v0.19.4,h1:5I4CCSqoWzT+82bBkNIvmLc0UOsoKKQ4Fz+3VxOB7SY=,adffcd0e2900bf0cca893e6bf014db55ebf161476367ac4dd365f8481c12616f
+github.com/go-openapi/runtime,v0.19.7,h1:b2zcE9GCjDVtguugU7+S95vkHjwQEjz/lB+8LOuA9Nw=,4017d9c69d9d2789d0a3b50c6af509831c0f24bfc545f1b43224df2fc5194dbd
+github.com/go-openapi/spec,v0.19.4,h1:ixzUSnHTd6hCemgtAJgluaTSGYpLNpJY4mA2DIkdOAo=,7c12cf07de1b65175474fdde12110716ab237fa862694e4e5051eb15541a964e
+github.com/go-openapi/strfmt,v0.19.3,h1:eRfyY5SkaNJCAwmmMcADjY31ow9+N7MCLW7oRkbsINA=,07b9c9b2da9dffc0a830e6536b705282fd17023fe8d04aa909fe1e4e3b6306f5
+github.com/go-openapi/swag,v0.19.5,h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=,54aec6bdc63d1d6609c32b140fe74d099f8b9628d362689556537506724eaeda
+github.com/go-openapi/validate,v0.19.4,h1:LGjO87VyXY3bIKjlYpXSFuLRG2mTeuYlZyeNwFFWpyM=,2b1b2612db93ed3fb411cc798150821af5c031b120097bbe6578dc4ce2d6d1df
+github.com/go-playground/locales,v0.13.0,h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=,9c4b65273e135b1bdb9bafc7c0b5180a6c5936f54edecbc8807c57a9d107c6b9
+github.com/go-playground/overalls,v0.0.0-20180201144345-22ec1a223b7c,h1:3bjbKXoj7jBYdHpQFbKL2546c4dtltTHzjo+5i4CHBU=,7972d7c49470ee2e187868b30d3157ca58201f50a934caa75ce4d5b134a2a644
+github.com/go-playground/universal-translator,v0.16.0,h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM=,316fba5fa26a586e39fc11698c16e67edabd122efe26f7fff71091a00a59883a
+github.com/go-redis/redis,v6.15.6+incompatible,h1:H9evprGPLI8+ci7fxQx6WNZHJSb7be8FqJQRhdQZ5Sg=,e277bbc2acb8462aca5e20ef7569a733501bc765f65303a6e5153a86e6e3090c
+github.com/go-sourcemap/sourcemap,v2.1.2+incompatible,h1:0b/xya7BKGhXuqFESKM4oIiRo9WOt2ebz7KxfreD6ug=,1bdaec84a31896eee149acb563f8af0b3ce7899d916383e0b597d6b480b6a622
+github.com/go-sql-driver/mysql,v1.4.1,h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=,f128045df19d340743a155ef282116130d27e27cbc62de160b6072c751b435ba
+github.com/go-stack/stack,v1.8.0,h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=,78c2667c710f811307038634ffa43af442619acfeaf1efb593aa4e0ded9df48f
+github.com/go-swagger/go-swagger,v0.20.1,h1:37XFujv7lYHLOKawfzLDg4STwwgB5zhPjodN33asJto=,79cc2c57c4e9d03a9399577b942eface46073ee6fa289b86651f1c5d0c513484
+github.com/go-swagger/scan-repo-boundary,v0.0.0-20180623220736-973b3573c013,h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0=,51aed4b67bce9d988d64ca6be9de2169f709a29d5ea83e78ffb1c2432b346ec6
+github.com/go-telegram-bot-api/telegram-bot-api,v4.6.4+incompatible,h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU=,a0d2549e07c67e066337cc6eadd8be2a961d13b493d4325603010d4e35e519df
+github.com/go-test/deep,v1.0.3,h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=,d199ce762552766bd3baf37ae4b0255bb6a6fecf144e8ae5fa3a94f1ce30a180
+github.com/go-xorm/builder,v0.3.4,h1:FxkeGB4Cggdw3tPwutLCpfjng2jugfkg6LDMrd/KsoY=,81028f69e261c29566c24f4717458d04dbe92aebc4eb93a41c1cfeef13b7c5dd
+github.com/go-xorm/core,v0.6.0,h1:tp6hX+ku4OD9khFZS8VGBDRY3kfVCtelPfmkgCyHxL0=,8a8c43c039422f38e1775a835bda46e62f4a055b4b38d57967c0e7a6c9b21d23
+github.com/go-xorm/sqlfiddle,v0.0.0-20180821085327-62ce714f951a,h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=,e539a37b8fb0d23c21e9eb1fe34db0ffcf19e5e4ae3d3b7049bb23c722c4b382
+github.com/go-xorm/xorm,v0.7.9,h1:LZze6n1UvRmM5gpL9/U9Gucwqo6aWlFVlfcHKH10qA0=,8836904c60cf227804fc843c707cd3e99122b95a97801d09dd2bddce4ed5a29f
+github.com/go-yaml/yaml,v2.1.0+incompatible,h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=,842989ea2e54ba8e4ef49cca914a5cd37176c44ccd3bb3e8c44fcbc10cb7832e
+github.com/gobuffalo/attrs,v0.1.0,h1:LY6/rbhPD/hfa+AfviaMXBmZBGb0fGHF12yg7f3dPQA=,06c6c210a26c85ae291efe9d54cab9cab26fd1453f4f48962e04c89760e775d0
+github.com/gobuffalo/buffalo,v0.15.0,h1:VsxIcfJaDm4u2UirLHGgMfQpfHVwJP3JoDmGyeeNnc0=,f4553c8809a6764cefac8eefce9a868a42ee7538bdef4eadfcc06075b865a087
+github.com/gobuffalo/buffalo-docker,v1.0.7,h1:kj+AfChcev54v4N8N6PzNFWyiVSenzu6djrgxTBvbTk=,d84d8bea93f017e3ff07eddab57e0fd7007cf2516250d6fea86c8811c36cf786
+github.com/gobuffalo/buffalo-plugins,v1.14.1,h1:ZL22sNZif+k/0I9X7LB8cpVMWh7zcVjfpiqxFlH4xSY=,556641c2c1b3a9d679a3fc46727d41da225f33c63cfbf1ff721203b24e0a9b82
+github.com/gobuffalo/buffalo-pop,v1.23.1,h1:AnxJQZu/ZN7HCm3L8YBJoNWc2UiwSe6UHv5S4DfXUDA=,00dea8b0e63d3f4110b8bd9d32c086163229f56845a9f8b221e0093876065a05
+github.com/gobuffalo/clara,v0.9.1,h1:LYjwmKG0VwwW/nOG2f5jNamvAcfdm2Ysokc/eoVhtZ8=,319f607092c02686dfed2eb047d500c332ddd962341012bdcd91202bb46d37a9
+github.com/gobuffalo/depgen,v0.2.0,h1:CYuqsR8sq+L9G9+A6uUcTEuaK8AGenAjtYOm238fN3M=,efb3db0d05f712580bc8d3dce2967bd09d6c90140ac7bca1fbd5c5c4a28e1836
+github.com/gobuffalo/envy,v1.7.1,h1:OQl5ys5MBea7OGCdvPbBJWRgnhC/fGona6QKfvFeau8=,14ac6a5cd617dc05abfcb136586800f05f861d4a03d8fa66819a18c0d9eddeec
+github.com/gobuffalo/events,v1.4.0,h1:Vje/vgTWs+dyhIS0U03oLpvx1SUdAqutv/hDWIz2ErM=,f6d99c722115631805f04fcf22e8edb7a4116bc65d698ac05c58b6a7f768efdc
+github.com/gobuffalo/fizz,v1.9.5,h1:Qh0GkP7MYtJs9RZwBkPJ0CzEXynVowdNfrjg8b+TOxA=,2f645d789550f8f97039e1c4ce3e3f09dfeec28d85c8977c2b20caa06cd75b0c
+github.com/gobuffalo/flect,v0.1.6,h1:D7KWNRFiCknJKA495/e1BO7oxqf8tbieaLv/ehoZ/+g=,a7011c8d3f59bac18512c76de610bf1a1f022a01ac6695e0c5af7498d33be613
+github.com/gobuffalo/genny,v0.4.1,h1:ylgRyFoVGtfq92Ziq0kyi0Sdwh//pqWEwg+vD3eK1ZA=,4ecf29587a8cbe069fc6b298d9a3cb674a8008ca4e08233904a8cba91d1ba21b
+github.com/gobuffalo/gitgen,v0.0.0-20190315122116-cc086187d211,h1:mSVZ4vj4khv+oThUfS+SQU3UuFIZ5Zo6UNcvK8E8Mz8=,c79975f91dd2fd691d70e29678034eb2dc94b5da2f01b0790a919de9d2a632ac
+github.com/gobuffalo/github_flavored_markdown,v1.1.0,h1:8Zzj4fTRl/OP2R7sGerzSf6g2nEJnaBEJe7UAOiEvbQ=,2d73a2baad09dc0d0f0c01549c35e83ab0c18c97f859191e54a632c2fb0eaad2
+github.com/gobuffalo/gogen,v0.2.0,h1:Xx7NCe+/y++eII2aWAFZ09/81MhDCsZwvMzIFJoQRnU=,f60900e595a3779b95b299ca9e74c517523860994a0477b360ac447d3318ccbd
+github.com/gobuffalo/helpers,v0.4.0,h1:DR/iYihrVCXv1cYeIGSK3EZz2CljO+DqDLQPWZAod9c=,17ae2b069c0ca73b11b4ace6793617e0620f8d8ef171b0010b91e243c4a3bbe3
+github.com/gobuffalo/here,v0.2.3,h1:1xamq7i4CKjGgICCXY0qpxPeXGdB8oVNSevkpqwd5X4=,3808d0fbc11c58cfb0e7b430b9fc30024ba3781febe8e2601a8e2b8f76e48c00
+github.com/gobuffalo/httptest,v1.4.0,h1:DaoTl/2iFRTk9Uau6b0Lh644tcbRtBNMHcWg6WhieS8=,9d1b48f3e525ab4661d02b3fac86f89fe27f648b1ff8e607f39a353c60c0f315
+github.com/gobuffalo/licenser,v1.4.0,h1:S8WY0nLT9zkBTjFYcbJ0E9MEK7SgE86aMfjsnuThQjY=,3e126adeb06dcaee29376804b463ed33af2b821579162039e8a16e45d0334cdc
+github.com/gobuffalo/logger,v1.0.1,h1:ZEgyRGgAm4ZAhAO45YXMs5Fp+bzGLESFewzAVBMKuTg=,43510255e52f7472ec17a76847ca42cebab6efe0b573a5dcfd8261e00d86d3b7
+github.com/gobuffalo/makr,v1.2.0,h1:TA6ThoZEcq0F9FCrc/7xS1ycdCIL0K6Ux+5wmwYV7BY=,113259ce8e945acf3dd184534ab6135240fde6b57d5c6ee3787e7c124e313502
+github.com/gobuffalo/mapi,v1.1.0,h1:VEhxtd2aoPXFqVmliLXGSmqPh541OprxYYZFwgNcjn4=,162640cc01d04543030d55ed51841d673cb8257fd78b069a79010e52ec996b73
+github.com/gobuffalo/meta,v0.2.0,h1:QSDlR2nbGewl0OVL9kqtU8SeKq6zSonrKWB6G3EgADs=,6a44e2a02126c65d2e2f09de5f732327001ac05d542abcabb8dc286422469e9a
+github.com/gobuffalo/mw-basicauth,v1.0.7,h1:9zTxCpu0ozzwpwvw5MO31w8nEoySNRNfZwM1YAWfGZs=,da5e2767a9d91e14efb25209c9b9dcf5ad07b551d6d54670c43c6225c8e94084
+github.com/gobuffalo/mw-contenttype,v0.0.0-20190129203934-2554e742333b,h1:6LKJWRvshByPo/dvV4B1E2wvsqXp1uoynVndvuuOZZc=,f9e2f7cce4e88ff8d6f86bc61076179b4f23a85eb5fd0a5f28793ef1e7889fab
+github.com/gobuffalo/mw-csrf,v0.0.0-20190129204204-25460a055517,h1:pOOXwl1xPLLP8oZw3e3t2wwrc/KSzmlRBcaQwGpG9oo=,b47a0879eadba5c6774ad37c66afea4998767d9df1295b7b17f3469282cc92f2
+github.com/gobuffalo/mw-forcessl,v0.0.0-20180802152810-73921ae7a130,h1:v94+IGhlBro0Lz1gOR3lrdAVSZ0mJF2NxsdppKd7FnI=,533187beeb18b977c8436d0a5596c1bd420b30cce55589cb11af592df063470c
+github.com/gobuffalo/mw-i18n,v0.0.0-20190129204410-552713a3ebb4,h1:c1fFPCxA7SozZPqMhpfZoOVa3wUpCl11gyCEZ4nYqUE=,96a1754eff9c9a75c6b48fc3bc9ab102bbf5d23c103b37a82cc88c666c0dbf9b
+github.com/gobuffalo/mw-paramlogger,v0.0.0-20190129202837-395da1998525,h1:2QoD5giw2UrYJu65UKDEo9HFcz9yun387twL2zzn+/Q=,d2e3b1baa234032585cc0e7dc1950681dbc05d960ee958578e470df9fa3b8f18
+github.com/gobuffalo/mw-tokenauth,v0.0.0-20190129201951-95847f29c5c8,h1:dqwRMSzfhe3rL0vMDaRvc2ozLqxapWFBEDH6/f0nQT0=,eb6f82200a81da34baa366475479069f08ed797d5edd4976c9f2af1027d37f1c
+github.com/gobuffalo/nulls,v0.1.0,h1:pR3SDzXyFcQrzyPreZj+OzNHSxI4DphSOFaQuidxrfw=,a77a09fd75234e7e5589640fae5d261c03ede9ab5ec626406f24c89dfeba2b38
+github.com/gobuffalo/packd,v0.3.0,h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4=,c7a9263fd464b9f5629bf161521f420b2c40f7780ed6a9ce88184dc4136787a5
+github.com/gobuffalo/packr,v1.30.1,h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg=,20aeea726f6db2ffc8b6dd90b1dce8991f0fd66152a270efdd21c0905b12d5f5
+github.com/gobuffalo/packr/v2,v2.7.1,h1:n3CIW5T17T8v4GGK5sWXLVWJhCz7b5aNLSxW6gYim4o=,60cd83772938a617b37c26a4924ee1f95008d53481724f801eee647e68ce22b1
+github.com/gobuffalo/plush,v3.8.3+incompatible,h1:kzvUTnFPhwyfPEsx7U7LI05/IIslZVGnAlMA1heWub8=,312e219c9827bb7d2dfc954f03fcaa275a3d9eb70687a62ecebad84ede4c51a7
+github.com/gobuffalo/plushgen,v0.1.2,h1:s4yAgNdfNMyMQ7o+Is4f1VlH2L1tKosT+m7BF28C8H4=,0efa90fac0c464409201fa74cace63c4307ac3700a23b3df7c9a9c1c976f0875
+github.com/gobuffalo/pop,v4.12.2+incompatible,h1:WFHMzzHbVLulZnEium1VlYRnWkzHz39FzVLov6rZdDI=,de2837b63e54b15d99234202839e0394183c4ff7c45b9d99162a407c95574003
+github.com/gobuffalo/release,v1.14.0,h1:+Jy7eLN5md6Fg+AMuFRUiK4sTNq4+zXxRho7/wJe1HU=,a0f34f0d3f02ea43434436936766f185b97204a073a605e720190c433c30aaa5
+github.com/gobuffalo/shoulders,v1.2.0,h1:XcPmWbzN7944VXS/I//R7o2eupUHEp3mLFWbUlk1Sco=,4c129ae195bd14520a38c608ba3a27aca674745c1f79fbcce03dacf829802ac6
+github.com/gobuffalo/syncx,v0.0.0-20190224160051-33c29581e754,h1:tpom+2CJmpzAWj5/VEHync2rJGi+epHNIeRSWjzGA+4=,ad9a571b43d72ecce24b8bed85636091710f22d8b06051e1e19ef2051f3e00da
+github.com/gobuffalo/tags,v2.1.6+incompatible,h1:xaWOM48Xz8lBh+C8l5R7vSmLAZJK4KeWcLo+0pJ516g=,99bd74d4144bcdfba45fa501cd8d6dec78dc5b0404bbbfebf5bced5b976bb911
+github.com/gobuffalo/uuid,v2.0.5+incompatible,h1:c5uWRuEnYggYCrT9AJm0U2v1QTG7OVDAvxhj8tIV5Gc=,6ab82616cbb02ddd78b9b7db14f580e2e212ceeadcfccff387a973b04be8db37
+github.com/gobuffalo/validate,v2.0.3+incompatible,h1:6f4JCEz11Zi6iIlexMv7Jz10RBPvgI795AOaubtCwTE=,53d876ba454e5e0604ab8078bfb1fca54dcd3ddd859c850cafce757c5f40153d
+github.com/gobuffalo/x,v0.0.0-20190224155809-6bb134105960,h1:DoUD23uwnzKJ3t5HH2SeTIszWmc13AV9TAdMhtXQts8=,2435ac54f3ea5c024aea1d4db42a87011bb877f18f0f273f7b3e19b7093c3cfd
+github.com/gobwas/glob,v0.2.3,h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=,0cfe486cd63d45ed4cb5863ff1cbd14b15e4b9380dcbf80ff26991b4049f4fdf
+github.com/gobwas/httphead,v0.0.0-20180130184737-2c6c146eadee,h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=,5a43ed4a7cd2b063b634f0df5311c0dfa6576683bfc1339f2c5b1b1127fc392b
+github.com/gobwas/pool,v0.2.0,h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=,52604b1456b92bb310461167a3e6515562f0f4214f01ed6440e3105f78be188f
+github.com/gobwas/ws,v1.0.2,h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=,f9e5c26e83278f19958c68be7b76ad6711c806b6dae766fad7692d2af867bedd
+github.com/gocolly/colly,v1.2.0,h1:qRz9YAn8FIH0qzgNUw+HT9UN7wm1oF9OBAilwEWpyrI=,82f210242c4efda461bb6d2cd0543bbadf322c23b840043f236dc1fd74af9325
+github.com/gocql/gocql,v0.0.0-20191018090344-07ace3bab0f8,h1:ZyxBBeTImqFLu9mLtQUnXrO8K/SryXE/xjG/ygl0DxQ=,d38e5bd51d411bc942f295950d87d80e607a8eb186d51b445cc6c2b985681b18
+github.com/godbus/dbus,v4.1.0+incompatible,h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=,107ef979cca9f2720633f118263afeb9acb0bf0703cc1e860098d5ec48efccb8
+github.com/gofrs/flock,v0.7.1,h1:DP+LD/t0njgoPBvT5MJLeliUIVQR03hiKR6vezdwHlc=,ee433032ec18df1e38d2385d7f9448820c5a017d895cb930cd8801401940137c
+github.com/gofrs/uuid,v3.2.0+incompatible,h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=,4139fd148a7a9389629659253722b302791146583e0db94e351a325ecd06abbf
+github.com/gogf/gf,v1.9.10,h1:lPBf0EOxv6AXVWN46EKLID0GMHDGOrs4ZAi/RUJbt+c=,83a8cf0cc2557c1e1b3cdb2112953ca303a09cb6d457d2102b3921db1bfd6fe5
+github.com/gogits/chardet,v0.0.0-20150115103509-2404f7772561,h1:deE7ritpK04PgtpyVOS2TYcQEld9qLCD5b5EbVNOuLA=,4b5c6d4b26d381d37b9a5538b9f2dc29d11f422653b19a2047e439a268c3f5ba
+github.com/gogits/cron,v0.0.0-20160810035002-7f3990acf183,h1:EBTlva3AOSb80G3JSwY6ZMdILEZJ1JKuewrbqrNjWuE=,746b3b98243fc5ae7127c5102f9ba4f0b88238d081e9cb113d61be2ec16a6241
+github.com/gogo/googleapis,v1.3.0,h1:M695OaDJ5ipWvDPcoAg/YL9c3uORAegkEfBqTQF/fTQ=,ee9e1dda02a5a415c41b5bdff7f6835e929ea89ff3dc1c766510ee909e03c6c3
+github.com/gogo/protobuf,v1.3.1,h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=,4b63e18981e30565f60b7305e3de71ff9aa42cfccf15b88b3813dd2ba6c27be1
+github.com/gogs/chardet,v0.0.0-20150115103509-2404f7772561,h1:aBzukfDxQlCTVS0NBUjI5YA3iVeaZ9Tb5PxNrrIP1xs=,53b6234983c0828d620ba418be5b4e467ef8c9d634bb3d0a2bd4056e3dfa38b3
+github.com/gogs/cron,v0.0.0-20171120032916-9f6c956d3e14,h1:yXtpJr/LV6PFu4nTLgfjQdcMdzjbqqXMEnHfq0Or6p8=,913889f3018853808015c9198e6d3a25f586d88d88493c3de36530eef967664c
+github.com/gogs/git-module,v0.8.2,h1:fCi0Lt8VZuFgjCXeLpkhC3irKLArK4oZ69gFvrDXx/s=,e4010dd8fdfe88a65fa8af6ecf97d7e16d4235d0eeb6a0b4b1f4e4d201c70d23
+github.com/gogs/go-gogs-client,v0.0.0-20190710002546-4c3c18947c15,h1:tgEyCCe4+o8A2K/PEi9lF0QMA6XK+Y/j/WN01LnNbbo=,cc5dcea1cca3d3d3e90a0ad548a660250b1299a61519f6dda5dcd7f2f1412daf
+github.com/gogs/go-libravatar,v0.0.0-20161120025154-cd1abbd55d09,h1:UdOSIHZpkYcajRbfebBYzFDsL3SuqObH3bvKYBqgKmI=,f81991af4a649aa273bc0c3e7251f107ba0967f5d83553f5a18ed688d937eff0
+github.com/gogs/gogs,v0.11.91,h1:p8kTD9Sn6a/14u6ain6j0dPENMZ0gVEiM7phSIAL29E=,b41695c115f4e2dfc96bfbc7443fa6f91a6d2c8b32d32db4262e6977f5d55fa7
+github.com/gogs/minwinsvc,v0.0.0-20170301035411-95be6356811a,h1:8DZwxETOVWIinYxDK+i6L+rMb7eGATGaakD6ZucfHVk=,fb48a56a9f610b061af186008072fbd6e51055a12c168e1e347ecf9a05f25767
+github.com/gohugoio/hugo,v0.59.1,h1:nxaeKEY52cdpx3wZN/EcY6dEqbgeFsZaeNkDL8azeZ8=,508257b11bfc1ec77d3993a13929de63fa08e70ae26cd7c53f03857b3db9bbdf
+github.com/gohugoio/testmodBuilder/mods,v0.0.0-20190520184928-c56af20f2e95,h1:sgew0XCnZwnzpWxTt3V8LLiCO7OQi3C6dycaE67wfkU=,0d6eabbeb381b08c84e7191fcecc49027ad3382997441180b2d6eea3fafc81b6
+github.com/goji/httpauth,v0.0.0-20160601135302-2da839ab0f4d,h1:lBXNCxVENCipq4D1Is42JVOP4eQjlB8TQ6H69Yx5J9Q=,8467ed1df8ffba8da7ead144b656b6281469ab4d122adf3edf496175ad870192
+github.com/goki/freetype,v0.0.0-20181231101311-fa8a33aabaff,h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8=,80884151cd73d38904e4370afba3b870345a883a77c395194582202d805d7d74
+github.com/goki/ki,v0.9.8,h1:SzVTxJrd0ZcnkRTinZdbc41nIFmocJ7pyllEyBzNmys=,ce62e162090d566e2f9cb5b1659327a84c646dced32729e24b420cde4d5cb714
+github.com/goki/prof,v0.0.0-20180502205428-54bc71b5d09b,h1:3zU6niF8uvEaNtRBhOkmgbE/Fx7D6xuALotArTpycNc=,f46b93b6c42a97f06a2f658e49243972f4bd469b296f1010609c8d649163b73f
+github.com/golang-collections/collections,v0.0.0-20130729185459-604e922904d3,h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=,7847b09c355215616db6309597757ff6be2cf44781d800cdad1628f141dc82ee
+github.com/golang-migrate/migrate/v3,v3.5.2,h1:SUWSv6PD8Lr2TGx1lmVW7W2lRoQiVny3stM4He6jczQ=,5086537ee116e958cf9647e28f843a0ac17f5de75ab642e5aef1fe2b360b0e30
+github.com/golang-sql/civil,v0.0.0-20190719163853-cb61b32ac6fe,h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=,22fcd1e01cabf6ec75c6b6c8e443de029611c9dd5cc4673818d52dac465ac688
+github.com/golang/freetype,v0.0.0-20170609003504-e2365dfdc4a0,h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=,cdcb9e6a14933dcbf167b44dcd5083fc6a2e52c4fae8fb79747c691efeb7d84e
+github.com/golang/gddo,v0.0.0-20180828051604-96d2a289f41e,h1:8sV50nrSGwclVxkCGHxgWfJhY6cyXS2plGjGvUzrMIw=,9a0683005c7700bb1b7ac155597592d15d02f510a0d2c334f8564c43b9072107
+github.com/golang/glog,v0.0.0-20160126235308-23def4e6c14b,h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=,36b3c522c8102dfe74ca96e474c4c361750bf2bb85bc3cefe4f074c07d6825a9
+github.com/golang/groupcache,v0.0.0-20191027212112-611e8accdfc9,h1:uHTyIjqVhYRhLbJ8nIiOJHkEZZ+5YoOsAbD3sk82NiE=,a4815d7048e9a1dd79a72a09d4c9a946ccff837695d046c7f0f5c24037ce18b3
+github.com/golang/lint,v0.0.0-20180702182130-06c8688daad7,h1:2hRPrmiwPrp3fQX967rNJIhQPtiGXdlQWAxKbKw3VHA=,66e95adf2c1feb4de316d2c0ba9e04a22322df010a67b1054ad3d4fb2f9a1791
+github.com/golang/mock,v1.3.1,h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=,3209f2030646855a3644736b5d7ce2cd9076856cac2f50360805a19c38b7bc45
+github.com/golang/protobuf,v1.3.2,h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=,a004ba3acb85e012cb9e468e1d445a81cfeeb4b4db7e9802f30aa500a8341851
+github.com/golang/snappy,v0.0.1,h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=,0a9a73d55340a8e6d17e72684cf90618b275b6034ce83299abb55ed8fb3860bd
+github.com/golangplus/bytes,v0.0.0-20160111154220-45c989fe5450,h1:7xqw01UYS+KCI25bMrPxwNYkSns2Db1ziQPpVq99FpE=,2904c49772d1bade7c81ddae2fa70e42bdce7b006c871c8106d1feb14fe2982b
+github.com/golangplus/fmt,v0.0.0-20150411045040-2a5d6d7d2995,h1:f5gsjBiF9tRRVomCvrkGMMWI8W1f2OBFar2c5oakAP0=,2afd341a4d32c84532d6d44574718e1b8000aa57cfc21ced284612fc92b61217
+github.com/golangplus/testing,v0.0.0-20180327235837-af21d9c3145e,h1:KhcknUwkWHKZPbFy2P7jH5LKJ3La+0ZeknkkmrSgqb0=,fc111aa59d03741dad00f05ce869fcb44f5d75b841413e21e7301bc538a0255e
+github.com/gomodule/redigo,v2.0.0+incompatible,h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=,77342da7b962489363b3661803ee2fba72b23b8e97af0241877ce6ab8a95d194
+github.com/gonum/blas,v0.0.0-20181208220705-f22b278b28ac,h1:Q0Jsdxl5jbxouNs1TQYt0gxesYMU4VXRbsTlgDloZ50=,bfcad082317ace0d0bdc0832f0835d95aaa90f91cf3fce5d2d81ccdd70c38620
+github.com/gonum/floats,v0.0.0-20181209220543-c233463c7e82,h1:EvokxLQsaaQjcWVWSV38221VAK7qc2zhaO17bKys/18=,52afb5e33a03b027f8f451e23618c2decbe4443f996a203e332858c1a348a627
+github.com/gonum/graph,v0.0.0-20190426092945-678096d81a4b,h1:LilU5ERRFWL+2D6yR1PL2oeS4n+xyTq1vfv39LFVaeE=,411fd86d898ad7ea8c1145610a27f0f13153c86b3ef5e78cb80431125082b5a6
+github.com/gonum/internal,v0.0.0-20181124074243-f884aa714029,h1:8jtTdc+Nfj9AR+0soOeia9UZSvYBvETVHZrugUowJ7M=,e7f40a97eee3574c826a1e75f80ecd94c27853feaab5c43fde7dd95ba516c9dc
+github.com/gonum/lapack,v0.0.0-20181123203213-e4cdc5a0bff9,h1:7qnwS9+oeSiOIsiUMajT+0R7HR6hw5NegnKPmn/94oI=,f38b72e072728121b9acf5ae26d947aacc0024dddc09d19e382bacd8669f5997
+github.com/gonum/matrix,v0.0.0-20181209220409-c518dec07be9,h1:V2IgdyerlBa/MxaEFRbV5juy/C3MGdj4ePi+g6ePIp4=,9cea355e35e3f5718b2c69f65712b2c08a1bec13b3cfadf168d98b41b043dd63
+github.com/google/btree,v1.0.0,h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=,8dbcb36f92c7a6dc5f6aef5c26358d98b72caee69829b5b33dddabada2047785
+github.com/google/cadvisor,v0.34.0,h1:No7G6U/TasplR9uNqyc5Jj0Bet5VSYsK5xLygOf4pUw=,5a3807f43a14e6a03b7ceb9ea11f8ac241a42286be90c3b2cba49ee811111848
+github.com/google/certificate-transparency-go,v1.0.21,h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE=,7ddb21b272632236d5fb35b35c837f39d38390ea8dcb97c9f0f5d5aa561c3366
+github.com/google/flatbuffers,v1.11.0,h1:O7CEyB8Cb3/DmtxODGtLHcEvpr81Jm5qLg/hsHnxA2A=,ff61e5077ecc7d46a2020c1b42e0a6405b50271f396d4dcc50c683345059af76
+github.com/google/go-cmp,v0.3.2-0.20191028172631-481baca67f93,h1:VvBteXw2zOXEgm0o3PgONTWf+bhUGsCaiNn3pbkU9LA=,6682f890f076aaa03f2c2afb6bc7304c9d602b9e23ff212f8a9a64f44f432dbc
+github.com/google/go-containerregistry,v0.0.0-20191029173801-50b26ee28691,h1:9fkqC5Bq8l2FQgcW6FQbPDUeZvExyg7okl+s4Gg9Jrs=,7bef2c87f7ca8a39e04c770b38160dd5cfdd508546f96fab427225d12d40d85a
+github.com/google/go-github,v17.0.0+incompatible,h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=,9831222a466bec73a21627e0c3525da9cadd969468e31d10ecae8580b0568d0e
+github.com/google/go-github/v21,v21.0.0,h1:tn4/tmCgPAsezJFwZcMnE7U0R9/AtKRBGX4s4LFdDzI=,0b25aebca5386cdb52515402b81a8e0a676ac30f9843feb0a47a1944b7c8b527
+github.com/google/go-github/v24,v24.0.1,h1:KCt1LjMJEey1qvPXxa9SjaWxwTsCWSq6p2Ju57UR4Q4=,4dd0a57a527a1cc52e6619e9d2e1936534439426f0eb065bfbe1e7c03b60d465
+github.com/google/go-github/v28,v28.1.1,h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo=,621cca7f4889897317c18ed021fe0f55c279769f11357d90eb21a29c5ea78d04
+github.com/google/go-querystring,v1.0.0,h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=,1c0a0b81b921ee270e47e05cf0bf8df4475de850671e553c07740849068d4f9f
+github.com/google/go-replayers/grpcreplay,v0.1.0,h1:eNb1y9rZFmY4ax45uEEECSa8fsxGRU+8Bil52ASAwic=,794ad7fb2669ea1d1305cf7717a1329146635637739bf2e26d858a318e87f99b
+github.com/google/go-replayers/httpreplay,v0.1.0,h1:AX7FUb4BjrrzNvblr/OlgwrmFiep6soj5K2QSDW7BGk=,cf6d3e2262e94db5bad86d944f2f97507b1ffc2943e4385f140eb6f9a01f8e7b
+github.com/google/go-tpm,v0.2.0,h1:3Z5ZjNRQ0CsUj3yWXtbbx4Vfb/sQapdSeZJvuaKuQzc=,7e90cb155fa3e7759caa1fe5df1ca43520a7f8e1a31e540573cc8290ff523a23
+github.com/google/go-tpm-tools,v0.0.0-20190906225433-1614c142f845,h1:2WNNKKRI+a5OZi5xiJVfDoOiUyfK/BU1D4w+N6967F4=,2e41ca1e24a1ba5eedf980331527d6a5ad09b8ef653bbd040321572899eff8a2
+github.com/google/gofuzz,v1.0.0,h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=,752570262575bbcb5f0107dbd80a463abacaf51e94e15f96f5bc4166ff2d33e1
+github.com/google/gopacket,v1.1.17,h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY=,008645038244e12a1bfbda2317372ec34a514250741139b8e4842de7f98639d4
+github.com/google/gxui,v0.0.0-20151028112939-f85e0a97b3a4,h1:OL2d27ueTKnlQJoqLW2fc9pWYulFnJYLWzomGV7HqZo=,be209ad45b16077b010faef4a7bcbf0723dfbe47869a6f4c0aacd534e7fcbfb1
+github.com/google/martian,v2.1.1-0.20190517191504-25dcb96d9e51+incompatible,h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE=,dfc5eac3877863c1f231457f96c54c915ea1c86f86c590710b7477f96e1ba0f3
+github.com/google/netstack,v0.0.0-20191031000057-4787376a6744,h1:wKeh74w+ydKcE1Eo44WDzIOcPHWmxxmtAzkAL0Mlspc=,dd74d0c9fadfb29db3bd09da657cb95300255d562ce596e88c865a71ee5d2519
+github.com/google/pprof,v0.0.0-20191028172815-5e965273ee43,h1:59gkLC5pLENSgzw9Gx73BQQho5i//80XwgIIYWxZjp4=,667012da0f67eb7822d16f532e850091a58c1efebeef5047df9a02e972112484
+github.com/google/readahead,v0.0.0-20161222183148-eaceba169032,h1:6Be3nkuJFyRfCgr6qTIzmRp8y9QwDIbqy/nYr9WDPos=,3a2435123538463dc3412a2eb1be033b7cf8105775c1ff3524351ec405fa1469
+github.com/google/renameio,v0.1.0,h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=,b8510bb34078691a20b8e4902d371afe0eb171b2daf953f67cb3960d1926ccf3
+github.com/google/rpmpack,v0.0.0-20191101142923-13d81472ccfe,h1:P1WflKHEgTAYe39btxYzeds84DhxQSLj4hfoNn0tCyQ=,5144bdeda051f10f407f1f798502ec0d7599f9c4a7e0a79c3711fe2b79f5cae4
+github.com/google/shlex,v0.0.0-20181106134648-c34317bd91bf,h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=,250fc48c105475c54cc8c9fe5c110e31986590433de2608740d6592d0dc0a4c6
+github.com/google/subcommands,v1.0.1,h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k=,de4249d9823a0509df32ebad2787d5e54c9b53c1059592bd9a3bb0c4cf58034d
+github.com/google/uuid,v1.1.1,h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=,2b0cbc45fb0e21c8bfebbae9b04babc196d9f06d9f3b9dec5e2adc8cfd0c1b81
+github.com/google/wire,v0.3.0,h1:imGQZGEVEHpje5056+K+cgdO72p0LQv2xIIFXNGUf60=,38eb402dbe84aee2f891df0e62623f9ff5615dfeb1e4f631eaac5cf1859c9ea6
+github.com/googleapis/gax-go,v2.0.2+incompatible,h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww=,36fe8c993c8f90067bffbba78f1325ff45ae60c8a85b778d798c56067e55c19e
+github.com/googleapis/gax-go/v2,v2.0.5,h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=,846b017e21fc01f408774051d4a10bfccd7c294e10a1ad5d725278889d5f1d42
+github.com/googleapis/gnostic,v0.3.1,h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk=,33277bd9aab84cf04d058a5e2e1dbb5f3c023ba30c6127b4cc8a6662a776de53
+github.com/gopackage/ddp,v0.0.0-20170117053602-652027933df4,h1:4EZlYQIiyecYJlUbVkFXCXHz1QPhVXcHnQKAzBTPfQo=,76b2493aae8a5513b707e4f6c529f57175cca6c834dd19072a51ed3974cd77bc
+github.com/gophercloud/gophercloud,v0.6.0,h1:Xb2lcqZtml1XjgYZxbeayEemq7ASbeTp09m36gQFpEU=,f5be75a3b128c9de7385dd7e2a8ec9fba18fb46dcf57624d88249ae99e188ed2
+github.com/gophercloud/utils,v0.0.0-20190128072930-fbb6ab446f01,h1:OgCNGSnEalfkRpn//WGJHhpo7fkP+LhTpvEITZ7CkK4=,c98b6d529b47679302d175f04d7b635824c292edc8a5ede807f9ba8145517ce7
+github.com/gopherjs/gopherjs,v0.0.0-20190915194858-d3ddacdb130f,h1:TyqzGm2z1h3AGhjOoRYyeLcW4WlW81MDQkWa+rx/000=,ff395ad20350783713974a6b4d03254b811d83c0c0caa13bcb329462a7263f70
+github.com/gopherjs/jquery,v0.0.0-20180404123100-3ba2b901425e,h1:Tf0PnEo36tq56/JezxbbiFpEce0pmK6tY7hS6PNS7tI=,26fb481ef7f7010ec901990527d7ef7b06bc18c38cb617db77f8b61263b5b453
+github.com/gopherjs/jsbuiltin,v0.0.0-20180426082241-50091555e127,h1:atBEgNR1C5+LFkl8ipQtLee9RStheS8YeCSkiYqBhOg=,603151a77e4be25c8389014b06449520c2ad5856f0161590a5de5f01bee28912
+github.com/goreleaser/goreleaser,v0.120.5,h1:N3VirNAK9u30Wj7xulfE9/cCvptO0vl+CLhaMEVGbGs=,9c516d6e8db8c6800102ca68e3f674a62dd42877d7785607f56c22f6dc9b5a9e
+github.com/goreleaser/nfpm,v1.1.2,h1:9+hnNm/h/ANQWLxZixNO562w4tIO/8VlgCwOKwwZTX4=,9781a05527458d352a744a524c94473d2a72694fd54bc559a5888158bb4fa1fb
+github.com/gorhill/cronexpr,v0.0.0-20180427100037-88b0669f7d75,h1:f0n1xnMSmBLzVfsMMvriDyA75NB/oBgILX2GcHXIQzY=,742d8957d3f9fe773150fb3164868a755b2af5b705b38c72c45ca5386715c617
+github.com/gorilla/context,v1.1.1,h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=,4ec8e01fe741a931edeebdee9348ffb49b5cc565ca245551d0d20b67062e6f0b
+github.com/gorilla/csrf,v1.6.0,h1:60oN1cFdncCE8tjwQ3QEkFND5k37lQPcRjnlvm7CIJ0=,6fa6b9d34ba1c2409e6575db396f57607c5283e397d38a271b6930c666f166b0
+github.com/gorilla/handlers,v1.4.2,h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=,9e47491112a46d32e372be827899e8678a881f6407f290564c63e8725b5e9a19
+github.com/gorilla/mux,v1.7.3,h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=,9ffc6c6c1194cb2b9f39237ff90b20eb4a55273404c97364ed9a6500e9571fe3
+github.com/gorilla/pat,v1.0.1,h1:OeSoj6sffw4/majibAY2BAUsXjNP7fEE+w30KickaL4=,e0dedacf6f405854b94932a59b410bbda64d4fff8111b674db987ce242bc9d57
+github.com/gorilla/rpc,v1.1.0,h1:marKfvVP0Gpd/jHlVBKCQ8RAoUPdX7K1Nuh6l1BNh7A=,0e83ae0cbc4164cdaf0b808413f97fed7a90e2096095c14f5495b6dbfaa34266
+github.com/gorilla/schema,v1.1.0,h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY=,42a6d7dc873e8ba1822551b4e15304d5654a11f6da3cccdc270be847148bbfaf
+github.com/gorilla/securecookie,v1.1.1,h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=,dd83a4230e11568159756bbea4d343c88df0cd1415bbbc7cd5badad6cd2ed903
+github.com/gorilla/sessions,v1.2.0,h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ=,8753d00ae6cf8ea0e28c195d4b87875384e2ed79df7eba4cf210fdf9ab0294df
+github.com/gorilla/websocket,v1.4.1,h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=,86eb427567de9e2dc84da52ee4f4315496c5ffc2152928df0e3ac4ce8a359ff7
+github.com/gosimple/slug,v1.9.0,h1:r5vDcYrFz9BmfIAMC829un9hq7hKM4cHUrsv36LbEqs=,0f72d897e3decea434cdc68c7d0226afbda7d6b1908e955bf406333e7d6bb4a7
+github.com/gosuri/uitable,v0.0.3,h1:9ZY4qCODg6JL1Ui4dL9LqCF4ghWnAOSV2h7xG98SkHE=,1316f88b6b2689d941a4727889818705a289c72d7f1f4d2d9cf5cd06fecd0b7b
+github.com/gotestyourself/gotestyourself,v2.2.0+incompatible,h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI=,653f8ec3ed62f8d235ab67cfc56e7c814d4ac6f56f24000802b32728523c074c
+github.com/gotnospirit/makeplural,v0.0.0-20180622080156-a5f48d94d976,h1:b70jEaX2iaJSPZULSUxKtm73LBfsCrMsIlYCUgNGSIs=,5750c916115b851f4881b76d90128802d090558958aa821c691d4fa378018093
+github.com/gotnospirit/messageformat,v0.0.0-20180622080451-0eab1176a3fb,h1:akgcoKcMcMOlzb6fdycEck1Vc3+y7ubUjO6hgAOyqC8=,7189231c806aa1988b50a82019c5f972a5f1b82e61c94776999728ec1894cd29
+github.com/graarh/golang-socketio,v0.0.0-20170510162725-2c44953b9b5f,h1:utzdm9zUvVWGRtIpkdE4+36n+Gv60kNb7mFvgGxLElY=,f41faefdf625d1c04113636d467a9fa47fe083148d7393fa65c0f08e3a4078c3
+github.com/grafana/globalconf,v0.0.0-20181214112547-7a1aae0695d9,h1:2/Bz5A5zR4TMGd9yvgGMal7nhQwHBt5/dfp0sbJFfes=,0393f4fa690096ea26c76373e99f9d9f3bfc9b34e5acd08d639b68f68af7b5e2
+github.com/grandcat/zeroconf,v0.0.0-20190424104450-85eadb44205c,h1:svzQzfVE9t7Y1CGULS5PsMWs4/H4Au/ZTJzU/0CKgqc=,2d364bea1939e3ec55b732cae452feb3182fc1d8ffa30f35aa42c0181709d138
+github.com/graph-gophers/graphql-go,v0.0.0-20190225005345-3e8838d4614c,h1:YyFUsspLqAt3noyPCLz7EFK/o1LpC1j/6MjU0bSVOQ4=,fad60e1061e15848aff79c6620f1cf55a9dd87d58ca2f57fea50c35322c817ac
+github.com/graphql-go/graphql,v0.7.9-0.20190403165646-199d20bbfed7,h1:E45QFM7IqRdFnuyFk8GSamb42EckUSyJ55rtVB/w8VQ=,6e9d51c4dc431d2d7c1348fa2b3358ed8e57338a07750177698bde29c913e786
+github.com/gravitational/trace,v0.0.0-20190726142706-a535a178675f,h1:68WxnfBzJRYktZ30fmIjGQ74RsXYLoeH2/NITPktTMY=,6fb8317692ac3aa8280cd4b4749970ec6652ecbe2c629cd43b52005f9a992197
+github.com/graymeta/stow,v0.2.4,h1:qDGstknYXqcnmBQ5TRJtxD9Qv1MuRbYRhLoSMeUDs7U=,67b4e728448b89c2233da14c22f18fe6c720e88a858dff2cd3c7405c7ea10493
+github.com/gregjones/httpcache,v0.0.0-20190611155906-901d90724c79,h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=,73d773791d582cad0d90942e7d92f52d82f13119dd78e849bbd77fae2acc0276
+github.com/grokify/html-strip-tags-go,v0.0.0-20190921062105-daaa06bf1aaf,h1:wIOAyJMMen0ELGiFzlmqxdcV1yGbkyHBAB6PolcNbLA=,0bb5eaff16e4119a9251bb0a26b4190a8e36cbacce8daee8c77df76022e1087c
+github.com/grpc-ecosystem/go-grpc-middleware,v1.1.0,h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg=,def2c3ec1d07264489b79fa0e8e7a5c23545f16ba3c6e613f5cdba2ae8fe2768
+github.com/grpc-ecosystem/go-grpc-prometheus,v1.2.1-0.20191002090509-6af20e3a5340,h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=,bca256c9eee3d43fe310c205866c69de454e71346f18ea2b05a32bd2f6018c84
+github.com/grpc-ecosystem/grpc-gateway,v1.11.3,h1:h8+NsYENhxNTuq+dobk3+ODoJtwY4Fu0WQXsxJfL8aM=,d96a88c820576b8b6989944cbe15f4f2d94d2884f29f2f683b975a03a5bdc5fc
+github.com/grpc-ecosystem/grpc-opentracing,v0.0.0-20180507213350-8e809c8a8645,h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU=,0606bde24e978e9cd91ae45ca9e5222ce695c21a07ae02e77546496bf23b1c62
+github.com/gucumber/gucumber,v0.0.0-20180127021336-7d5c79e832a2,h1:iR8wSrr/JCzL1Ul+dRVxtIOnP8DGg/m02nHZJ9PH6P0=,4feb5116e650552868f056ee74d179e91239bf166d365267f32e903ccc495dbb
+github.com/guptarohit/asciigraph,v0.4.1,h1:YHmCMN8VH81BIUIgTg2Fs3B52QDxNZw2RQ6j5pGoSxo=,976279cdbc5425609c272b2116a92fb5871a40164ae64c51dedffea7b550d2d4
+github.com/guregu/null,v2.1.3-0.20151024101046-79c5bd36b615+incompatible,h1:SZmF1M6CdAm4MmTPYYTG+x9EC8D3FOxUq9S4D37irQg=,1adcbf87f6c55963b0d020ccbac0ebd07e8aca5e0ff22469ac708c6574d7333f
+github.com/gxed/go-shellwords,v1.0.3,h1:2TP32H4TAklZUdz84oj95BJhVnIrRasyx2j1cqH5K38=,c63674c66949c0442402bceca8b7768684875a667140ea0b32afdd46fc094a7f
+github.com/gxed/hashland/keccakpg,v0.0.1,h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU=,c77522ff0820feb7b5be4e1c74d7c64b3aa5afe3452e1dd2f54d1ffa067c6b2d
+github.com/gxed/hashland/murmur3,v0.0.1,h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc=,4576d7ae9b5d2f4ebd238de84f3b52b9d4ae4d41822ac0eabd404d346eace067
+github.com/gxed/pubsub,v0.0.0-20180201040156-26ebdf44f824,h1:TF4mX7zXpeyz/xintezebSa7ZDxAGBnqDwcoobvaz2o=,718b183cca4e30a97d3fa06457060b4d3be66742838d98a39b02ea710693d9eb
+github.com/h2non/filetype,v1.0.8,h1:le8gpf+FQA0/DlDABbtisA1KiTS0Xi+YSC/E8yY3Y14=,534a477c811032fceb0c8e1ad7a15f35ff95f1d038d41164bb4d265860cc42c3
+github.com/h2non/gock,v1.0.9,h1:17gCehSo8ZOgEsFKpQgqHiR7VLyjxdAG3lkhVvO9QZU=,ab5679329b0c26b523254dd728cad1b4e6e2e7bf11569df73a1dcaa468a46cd6
+github.com/h2non/parth,v0.0.0-20190131123155-b4df798d6542,h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=,3b7b7e4bb3c2d0e22075e13443af78d03fb2ed54b3eb5bb1fa6f528c7ebe3ac0
+github.com/hailocab/go-hostpool,v0.0.0-20160125115350-e80d13ce29ed,h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=,faf2b985681cda77ab928976b620b790585e364b6aff351483227d474db85e9a
+github.com/hanwen/go-fuse,v1.0.0,h1:GxS9Zrn6c35/BnfiVsZVWmsG803xwE7eVRDvcf/BEVc=,4b94d038e80959f816a18b34cdcbb5244e87b73956b220aac213483999b54c84
+github.com/hashicorp/aws-sdk-go-base,v0.4.0,h1:zH9hNUdsS+2G0zJaU85ul8D59BGnZBaKM+KMNPAHGwk=,967c057aecede32de140c88b6527149d2441216569620b9d9350522d0f309bdc
+github.com/hashicorp/consul,v1.6.1,h1:ISPgwOO8/vPYrCXQNyx63eJAYjPGRnmFsXK7aj2XICs=,0ca8c5046df99a7a6607ab68b6604340af58d1696c7901088adfd9618850629f
+github.com/hashicorp/consul/api,v1.2.0,h1:oPsuzLp2uk7I7rojPKuncWbZ+m5TMoD4Ivs+2Rkeh4Y=,2833a78c39a4fa869a928e1218f3aa83130e4f5c03b4d4e355fb76b91fa75946
+github.com/hashicorp/consul/sdk,v0.2.0,h1:GWFYFmry/k4b1hEoy7kSkmU8e30GAyI4VZHk0fRxeL4=,3f0b677061f7e79191cc0d2f8184895c20051166959566a2e48e511b1fab222c
+github.com/hashicorp/errwrap,v1.0.0,h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=,ccdf4c90f894d8a5fde4e79d5828c5d27a13e9f7ce3006dd72ce76e6e17cdeb2
+github.com/hashicorp/go-azure-helpers,v0.0.0-20190129193224-166dfd221bb2,h1:VBRx+yPYUZaobnn5ANBcOUf4hhWpTHSQgftG4TcDkhI=,dd17ed56e4b541cffa69679557074071372ab70682f695d8b61126c9393f92dc
+github.com/hashicorp/go-bexpr,v0.1.2,h1:ijMXI4qERbzxbCnkxmfUtwMyjrrk3y+Vt0MxojNCbBs=,ac79086a2900ebf2f5414fe54b5799f24b3ddf953a28299f46831a11b10b1df0
+github.com/hashicorp/go-checkpoint,v0.5.0,h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=,1baf63010271d6c8abc0f4edc9e9d41483cb55218e4e399ca4c70ef225415f36
+github.com/hashicorp/go-cleanhttp,v0.5.1,h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=,e3cc9964b0bc80c6156d6fb064abcb62ff8c00df8be8009b6f6d3aefc2776a23
+github.com/hashicorp/go-discover,v0.0.0-20190403160810-22221edb15cd,h1:SynRxs8h2h7lLSA5py5a3WWkYpImhREtju0CuRd97wc=,c58ed5375890c98a836234f5166cf88b73ad7595899edaa43c775d650043b4b3
+github.com/hashicorp/go-gcp-common,v0.5.0,h1:kkIQTjNTopn4eXQ1+lCiHYZXUtgIZvbc6YtAQkMnTos=,a1fee55619b3579e5fe89b6f944dce87e190b8ea1526f24622ba5941d664b639
+github.com/hashicorp/go-getter,v1.4.0,h1:ENHNi8494porjD0ZhIrjlAHnveSFhY7hvOJrV/fsKkw=,cbae7b8a5f018c78bb304c47840c390b3c3be98b712b90b33d16304f1b427eb1
+github.com/hashicorp/go-hclog,v0.9.2,h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=,e1a873d9fa828038b5b2c93e0f49f9e8187b4f5255d0a3d7989d3ac178807af4
+github.com/hashicorp/go-immutable-radix,v1.1.0,h1:vN9wG1D6KG6YHRTWr8512cxGOVgTMEfgEdSj/hr8MPc=,c23ca92f0fb7dce35b86d35ccf9cfa871db97379d2ca8a0fcc15fde32ff369bb
+github.com/hashicorp/go-memdb,v1.0.4,h1:sIdJHAEtV3//iXcUb4LumSQeorYos5V0ptvqvQvFgDA=,c3eedd68e60f3db16499dff27fe4d4e874978c250bab152044965a475cb47c72
+github.com/hashicorp/go-msgpack,v0.5.5,h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI=,fb47605669b0ddd75292aac788208475fecd54e0ea3e9a282d8a98ae8c60d1f5
+github.com/hashicorp/go-multierror,v1.0.0,h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=,a66a1b9dff26a9a7fcaa5aa5e658c13f94c0daeb572536b1ecc7ebe51f4d0be7
+github.com/hashicorp/go-oracle-terraform,v0.0.0-20181016190316-007121241b79,h1:RKu7yAXZTaQsxj1K9GDsh+QVw0+Wu1SWHxtbFN0n+hE=,5b3ab30e1aef56e38d750a5dc344f1ab996859408a6b76a9f48f5f75747fd712
+github.com/hashicorp/go-plugin,v1.0.1,h1:4OtAfUGbnKC6yS48p0CtMX2oFYtzFZVv6rok3cRWgnE=,0853effcccdb7bfac1c122f72cd3a1241b4e0934609541c409e9f59b441ae01e
+github.com/hashicorp/go-raftchunking,v0.6.2,h1:imj6CVkwXj6VzgXZQvzS+fSrkbFCzlJ2t00F3PacnuU=,f5c55a3679c8a8f63d798d2b67552bfcd198dc5b9473d81c3ce1b353a055bc5c
+github.com/hashicorp/go-retryablehttp,v0.6.3,h1:tuulM+WnToeqa05z83YLmKabZxrySOmJAd4mJ+s2Nfg=,69cb67f4821e97ca8f04b0cb710c61a5acfaa948dda59b949b40fd6fae8e7dec
+github.com/hashicorp/go-rootcerts,v1.0.1,h1:DMo4fmknnz0E0evoNYnV48RjWndOsmd6OW+09R3cEP8=,3f558b1a436ed6fb15872383545109227f9552bf5daa95583e9402bbd3a24fff
+github.com/hashicorp/go-safetemp,v1.0.0,h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=,6843a6b60d650ae9be836add0ab5ac1b1719a101bf12fe4ca6678fcd87baa19a
+github.com/hashicorp/go-slug,v0.4.0,h1:YSz3afoEZZJVVB46NITf0+opd2cHpaYJ1XSojOyP0x8=,b6a027a2d69ae8786a6830239a79ceac487463237b49e03250a9b1e116f0a5ac
+github.com/hashicorp/go-sockaddr,v1.0.2,h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=,50c1b60863b0cd31d03b26d3975f76cab55466666c067cd1823481a61f19af33
+github.com/hashicorp/go-syslog,v1.0.0,h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE=,a0ca8b61ea365e9ecdca513b94f200aef3ff68b4c95d9dabc88ca25fcb33bce6
+github.com/hashicorp/go-tfe,v0.3.25,h1:4rPk/9rSYuRoujKk5FsxSvtC/AjJCQphLS/57yr6wUM=,5ade1d16517697c7bd04b556f852264eef33906c52d32bd6702c47838c1c1c04
+github.com/hashicorp/go-uuid,v1.0.1,h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=,a05417b988b047d55fca8ad4fec6bde56c3907f679fece48f97d608e61e82a5c
+github.com/hashicorp/go-version,v1.2.0,h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=,a3231adb6bf029750970de2955e82e41e4c062b94eb73683e9111aa0c0841008
+github.com/hashicorp/go.net,v0.0.1,h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw=,71564aa3cb6e2820ee31e4d9e264e4ed889c7916f958b2f54c6f3004d4fcd8d2
+github.com/hashicorp/golang-lru,v0.5.3,h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk=,ac6e8bdc76a1275e3496f1ab2484e28ab4be2c81e2da78b8cdd1c2d269b931e4
+github.com/hashicorp/hcl,v1.0.0,h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=,54149a2e5121b3e81f961c79210e63d6798eb63de28d2599ee59ade1fa76c82b
+github.com/hashicorp/hcl/v2,v2.0.0,h1:efQznTz+ydmQXq3BOnRa3AXzvCeTq1P4dKj/z5GLlY8=,6275e2af8b3247c6de72baab13b3be531431f695e001e4d36c920e412a715032
+github.com/hashicorp/hcl2,v0.0.0-20191002203319-fb75b3253c80,h1:PFfGModn55JA0oBsvFghhj0v93me+Ctr3uHC/UmFAls=,42811f77c4da1d31371c51076cbcecc99042fc7a74c6e2622b11bea96043a777
+github.com/hashicorp/hil,v0.0.0-20190212112733-ab17b08d6590,h1:2yzhWGdgQUWZUCNK+AoO35V+HTsgEmcM4J9IkArh7PI=,cb2b110c86a312b7c60094c9b11853ae288945c34fa5861b67ff2d97edaab292
+github.com/hashicorp/logutils,v1.0.0,h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=,0e88424578d1d6b7793b63d30c180a353ce8041701d25dc7c3bcd9841c36db5b
+github.com/hashicorp/mdns,v1.0.1,h1:XFSOubp8KWB+Jd2PDyaX5xUd5bhSP/+pTDZVDMzZJM8=,0f4b33961638b1273ace80b64c6fc7e54a1064484b2a1e182ab3d38a35dbc94f
+github.com/hashicorp/memberlist,v0.1.5,h1:AYBsgJOW9gab/toO5tEB8lWetVgDKZycqkebJ8xxpqM=,51054573cad1655b1b349553a8d455eedc15b49f0277edd2e693bc5d0503af62
+github.com/hashicorp/net-rpc-msgpackrpc,v0.0.0-20151116020338-a14192a58a69,h1:lc3c72qGlIMDqQpQH82Y4vaglRMMFdJbziYWriR4UcE=,b0c3a5ec955b0dfb85b39a6aa1d10fe0e810dd78493c0a14ea5760bac1cadd32
+github.com/hashicorp/nomad/api,v0.0.0-20190412184103-1c38ced33adf,h1:U/40PQvWkaXCDdK9QHKf1pVDVcA+NIDVbzzonFGkgIA=,b9e994cd47eed80531b93d9f64be426cbdc6fc6e58323f6b26ae53b1fd692bbd
+github.com/hashicorp/packer,v1.4.4,h1:ee+jewbEfTKV77+YtRR0m2Q8suTiXnr010bBFt5vJSA=,d2fc7c22b3528a4acb321fda24575cf2f88df8f5085b3b5da559e44d8b12295a
+github.com/hashicorp/raft,v1.1.1,h1:HJr7UE1x/JrJSc9Oy6aDBHtNHUUBHjcQjTgvUVihoZs=,b6a10aa04b5f45486a6111d4a50cb65ee179b091f04a047e316b85f38ebbf873
+github.com/hashicorp/raft-boltdb,v0.0.0-20191021154308-4207f1bf0617,h1:CJDRE/2tBNFOrcoexD2nvTRbQEox3FDxl4NxIezp1b8=,e2008570aed06ba72cd783d6bc729b67b7e0cecd2219a8420dd24dcef82e64f8
+github.com/hashicorp/raft-snapshot,v1.0.1,h1:cx002JsTEAfAP0pIuANlDtTXg/pi2Db6YbRRmLQTQKw=,3d40d03f6793fe87464359f28b136b920daf7aa8544a98270470d04cef132a77
+github.com/hashicorp/serf,v0.8.5,h1:ZynDUIQiA8usmRgPdGPHFdPnb1wgGI9tK3mO9hcAJjc=,88623d0f1a155bb2fe254210f68f1603b42162f031fbf51256f1465b36bc7769
+github.com/hashicorp/terraform,v0.12.13,h1:LACXUTZvAGf8W/6wehHjOgi6YEMN7ejDUpnpll2qbJ0=,4dbe6d0c15f4d934fd583fc20bec55326ffc79cf0d5b7fd28978ba14d178fe8d
+github.com/hashicorp/terraform-config-inspect,v0.0.0-20190821133035-82a99dc22ef4,h1:fTkL0YwjohGyN7AqsDhz6bwcGBpT+xBqi3Qhpw58Juw=,1261dc9b65805f9be029f6a42d9e0ddccc89c4d0c50e5fa2895b1b53198195c3
+github.com/hashicorp/terraform-svchost,v0.0.0-20191011084731-65d371908596,h1:hjyO2JsNZUKT1ym+FAdlBEkGPevazYsmVgIMw7dVELg=,8055e9f82b0484eb70594ca682bcf4401d2286c2021ffc72c6c3b6ad9ac9a024
+github.com/hashicorp/vault,v1.2.0-rc1,h1:GFYP6ck5f0EaJsGMD4PARIX5HaHREUxMbTaVPy+dFEg=,89c84474c97b1400ca858fe1b6e0eb3bd91dac17a4aff4336bd95104381e8b2b
+github.com/hashicorp/vault-plugin-auth-alicloud,v0.5.2-0.20190725165955-db428c1b0976,h1:f+r1gXVvQJ0+2pfxgBDP1zZUC6lUmPNM0xp7AKupyBg=,3bc95606713215c3ae25f9be06ed2186f8f2e5e9ad8e025fafd332d97045ed09
+github.com/hashicorp/vault-plugin-auth-azure,v0.5.2-0.20190725170003-0fc4bd518aa2,h1:Ua6AFhJYkdNGC5s4uDL7EGVBD/jPUOcnubDkPsaG7K8=,bfa988cf4a3e33e7db3caf2ecad55c2f7c2e3f39088243767927ac8ed8d2556e
+github.com/hashicorp/vault-plugin-auth-centrify,v0.5.2-0.20190725170023-9d8d5e0b03e6,h1:UXM3yxzNaruvgaccRjFXKcKnsTTHzp213MJ045wto6A=,165cf5f7daa0e4c286bad12f09eeac648062554399f18890bf35789b6b16e9c7
+github.com/hashicorp/vault-plugin-auth-gcp,v0.5.2-0.20190725170032-0aa7d1c92039,h1:uqYbah1dntV8OccHCbY3bBzYX/zLtjmG0ZIZPV+x6EM=,e9f9ccc7ca02c40291bb27012f2dd1fead86d2de2ab85a6d07b0aa7d98533f49
+github.com/hashicorp/vault-plugin-auth-jwt,v0.5.2-0.20190725170041-1cfee03e8d3a,h1:zdhacnLMH4P47PdSPJo0omNh+IkSvPj0LbiHLQu0aVk=,2b04c80c6d2000558b63ced2c9ba60a4a2ffe4c76d2d58d5fe121f714a3cf291
+github.com/hashicorp/vault-plugin-auth-kubernetes,v0.5.2-0.20190725170047-354505be0ecf,h1:il4UUQC9zfsSRNR2EAQVqC+DzrvzZpFmJReQ7p6/bKw=,d95794ab78e644a95799a3505a83af58a83c6bf775e69832b3660ca47c042d5a
+github.com/hashicorp/vault-plugin-auth-oci,v0.0.0-20190904175623-97c0c0187c5c,h1:z6LQZvs1OtoVy2XgbgNhiDgp0U62Xbstn7/cgNZvh6g=,b23f2afa7fab5368d83a01be865e2dddf7ba6c7e8804ac205ccc1701a9239d51
+github.com/hashicorp/vault-plugin-auth-pcf,v0.0.0-20190725170053-826a135618c1,h1:mPyQ1+jB/ztcqebEdmNhSuYq4XVOpB5TUyyi0118T40=,c444159df670a1aba7e59029bf928989091886fa45970f751fe644d243d43744
+github.com/hashicorp/vault-plugin-database-elasticsearch,v0.0.0-20190725170059-5c0d558eb59d,h1:VUD1T3aI5GL8uoSSDhHncHP8ksgepZsvSLhsRG8MJ3s=,b151c27f632b8e05686473b4936b480cec694498c1e446dc5208b4db05c559f1
+github.com/hashicorp/vault-plugin-secrets-ad,v0.5.3-0.20190725170108-e1b17ad0c772,h1:N219G3MUxPRhtOBMFVdsSQWU47MrvivSHLmTAPpHcs4=,c8801ee5f030fa6cb36045f1e321d964224f9a2b4a17100140cafca7a6d8daf5
+github.com/hashicorp/vault-plugin-secrets-alicloud,v0.5.2-0.20190725170114-7d66a3fa0600,h1:kyHR0JOKFDAaC4sjQ3iD1lTH6uaIfmTk4rQ+JOGW5Zo=,f816c029601c9e7235f798e9591246ac935d3b1e330abfb23af59afa6bc08e0d
+github.com/hashicorp/vault-plugin-secrets-azure,v0.5.2-0.20190725170121-541440395211,h1:hZ21h0DWWKkoeMW7zkYaPVLxGZtKfYyIcE9G8xug4YQ=,5d71ad3ef26fd40b3afaf852913f38e5be0a1db8844bf21cb787e204cdbc48e4
+github.com/hashicorp/vault-plugin-secrets-gcp,v0.5.3-0.20190725170127-aa49df112140,h1:gSvWU9aYAsHxqKU0ohJD9njlNQ1/qLFPRs85u+xJFv4=,9b209e3ef7b8d7c41e823705cc190699540bbd2076f82344a83c106fa7e4ac98
+github.com/hashicorp/vault-plugin-secrets-gcpkms,v0.5.2-0.20190725170135-aaf270943731,h1:zP2vqetYhON59Mf5FTV9KmyKSnY1cLFzdNW0YYnNKbo=,5d3bc6de4bdad4725c4348a0d6861bce3e80a9eb13d4b05179cd663b47f46545
+github.com/hashicorp/vault-plugin-secrets-kv,v0.5.2-0.20190725170141-1c4dac87f383,h1:4IqT7JQt/GyYKr0HGemkUlYpF45ZALHSN9rHy7Sipos=,10f03c6d8a51714692b43ab69c2cb5f041ac611210aa9804237a9345e930f018
+github.com/hashicorp/vault/api,v1.0.4,h1:j08Or/wryXT4AcHj1oCbMd7IijXcKzYUGw59LGu9onU=,a885d16e067a5586e55914cd8e40f250a28fe94b3b864de47d495ad1f71c4251
+github.com/hashicorp/vault/sdk,v0.1.14-0.20190909201848-e0fbf9b652e2,h1:b65cSyZqljnCPzzsUXvR4P0eXypo1xahQyG809+IySk=,0aca8708570b724605514cab6dbbc9cc7bce5d27786a4b2da87553c437c42463
+github.com/hashicorp/vic,v1.5.1-0.20190403131502-bbfe86ec9443,h1:O/pT5C1Q3mVXMyuqg7yuAWUg/jMZR1/0QTzTRdNR6Uw=,9c09a35b14d797812e6714073471b3472c16f9cb4deb430f9e2dd15fa8d25e32
+github.com/hashicorp/yamux,v0.0.0-20190923154419-df201c70410d,h1:W+SIwDdl3+jXWeidYySAgzytE3piq6GumXeBjFBG67c=,d8a888d6a4ecbc09f2f3663cb47aa2d064298eeb1491f4761a43ae95e93ba035
+github.com/herenow/go-crate,v0.0.0-20190617151714-6f2215a33eca,h1:kk1qCxy+FS5McLJ69dSpB6Y6kHCMa23UwHyglIzJ/bk=,aa618858b9c03e47962afb2a4098ad6cca8ecd09904cdbc5eb62c5a1d74befca
+github.com/hetznercloud/hcloud-go,v1.15.1,h1:G8Q+xyAqQ5IUY7yq4HKZgkabFa0S/VXJXq3TGCeT8JM=,028402928c1bc1db686cab5738e6fb91a61252c1236258e2d911dd8da21f8af5
+github.com/hinshun/vt10x,v0.0.0-20180616224451-1954e6464174,h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=,4afc77bd4950db746c68d23e6ed681d31cd952559d712c1400da476084567cf6
+github.com/hjfreyer/taglib-go,v0.0.0-20151027170453-0ef8bba9c41b,h1:Q4OOFmH18aIjnDJlvYm4BXmpHKXk1zTJP0QZ0otNwPs=,e7735f2cdbb7441dbe6bbc303cff9b9a20d9845dc901e31f6e29e3ef83613390
+github.com/howeyc/fsnotify,v0.9.0,h1:0gtV5JmOKH4A8SsFxG2BczSeXWWPvcMT0euZt5gDAxY=,a72f2f092433c8b53e095d6db3d3e18517db1a5a9814a78ed97194239145740f
+github.com/howeyc/gopass,v0.0.0-20190910152052-7cb4b85ec19c,h1:aY2hhxLhjEAbfXOx2nRJxCXezC6CO2V/yN+OCr1srtk=,83560b6c9a6220bcbb4ad2f043e5a190ab11a013b77c1bbff9a3a67ed74d4b37
+github.com/hpcloud/tail,v1.0.0,h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=,3cba484748e2e2919d72663599b8cc6454058976fbca96f9ac78d84f195b922a
+github.com/huandu/xstrings,v1.2.0,h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0=,fe7011ad569e464d6ff81bdb1d80c4ebdb5baac5c89d17c1644a23cac0c48828
+github.com/huin/goupnp,v1.0.0,h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=,9685536729d9860766846ad4e56fb961b246d5afa209e4058ee0d021aec37827
+github.com/huin/goutil,v0.0.0-20170803182201-1ca381bf3150,h1:vlNjIqmUZ9CMAWsbURYl3a6wZbw7q5RHVvlXTNS/Bs8=,d887199bd2f388075ff7aaf1d3061b13b92c20e01ccd6337c864fd409fe78831
+github.com/hybridgroup/go-ardrone,v0.0.0-20140402002621-b9750d8d7b78,h1:7of6LJZ4LF9AvF4bTiMr2I72KxodBf1BXrSD9Tz0lWU=,997e0efef1b73cc1930ad67cd649268ff864393fa85dedf32672ecca78647021
+github.com/hybridgroup/mjpeg,v0.0.0-20140228234708-4680f319790e,h1:xCcwD5FOXul+j1dn8xD16nbrhJkkum/Cn+jTd/u1LhY=,d9134203da596f895c55c3a9fd0aea32ad26501ca88e646cbe9f82136f592c0f
+github.com/hyperledger/fabric,v1.4.3,h1:6MmYhcDbxhd0TvpvHLR3c5m3fVjaX97690H8TRjpJNA=,067d2bd69094dc9f693d9b00c8bea810f61f6a8a3d0ac640830b468934e22023
+github.com/hyperonecom/h1-client-go,v0.0.0-20190122232013-cf38e8387775,h1:MIteIoIQ5nFoOmwEHPDsqng8d0dtKj3lCnQCwGvtxXc=,135625f81c1c6c62b296269829a74f1266928600545fedec0825cb97284264f6
+github.com/iancoleman/strcase,v0.0.0-20190422225806-e506e3ef7365,h1:ECW73yc9MY7935nNYXUkK7Dz17YuSUI9yqRqYS8aBww=,f93e74faf2e05699180c40ef21204629a1c6bd382658f1059c80631c377c5246
+github.com/ianlancetaylor/demangle,v0.0.0-20181102032728-5e5cf60278f6,h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c=,73ae40ed96af2703f85cd4c552cf6b14551ceb782348be8185b730f44c842ab9
+github.com/iij/doapi,v0.0.0-20190504054126-0bbf12d6d7df,h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E=,7e33155961c2cba072047deb34d19a7d863a713e502abe8bdc31ab91424bd226
+github.com/ijc/Gotty,v0.0.0-20170406111628-a8b993ba6abd,h1:anPrsicrIi2ColgWTVPk+TrN42hJIWlfPHSBP9S0ZkM=,b8b9a99b3632feb3449d1fb8950d292333f8a7f494b182320ecdb0479d78442f
+github.com/imdario/mergo,v0.3.8,h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ=,579cad1ed913cfcb424deb97e7016749abcc9d585bad07d14f19550df052cec5
+github.com/imkira/go-interpol,v1.1.0,h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=,de5111f7694700ea056beeb7c1ca1a827075d423422f251076ee17bd869477d9
+github.com/improbable-eng/grpc-web,v0.9.1,h1:tenDg9Lg+zYXeS/ojbKyfwVO5TVYh5FFGsrXNAblF1o=,3a287ae758b41feea9f26ec1b8757628d4742b87376fa40b29d878ee651bfe62
+github.com/imroc/req,v0.2.3,h1:ElMCifcqg/1GonGloyyTUrj6D6IITL6EiNEKHUl4xZM=,951172f0969fa0bad31ebbe9b17699ea3909b09eaf8df39ccd78e48097682c78
+github.com/inconshreveable/go-update,v0.0.0-20160112193335-8152e7eb6ccf,h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8=,adf856fb49e7c5059b2edb42a31daf4a536dc698fe0728835b018150a884b678
+github.com/inconshreveable/log15,v0.0.0-20180818164646-67afb5ed74ec,h1:CGkYB1Q7DSsH/ku+to+foV4agt2F2miquaLUgF6L178=,31875747bcd198c39714d38747ac77e585620f2f37d1b1e1a03b164af6762995
+github.com/inconshreveable/mousetrap,v1.0.0,h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=,c3fa0813e78f5cef10dc0e9912c43e68e06ff970a98e98c4050fe14dbbfd18c7
+github.com/influxdata/changelog,v1.1.0,h1:HXhmLZDrbuC+Ca5YX7g8B8cH5DmJpaOjd844d9Y7aTQ=,19e60d9b658aaecca4e075126c996c1abd5e369003c14bbe575edc4ba2b9c182
+github.com/influxdata/flux,v0.52.0,h1:R91uUXbHzoiyYF7Xhm+wP3a0iSnl43iYJrN93nBhuP0=,e0121889c46cc4ad22f1662e68df7dbdfbb361c3da6809add4d1409cef764be9
+github.com/influxdata/influxdb,v1.7.9,h1:uSeBTNO4rBkbp1Be5FKRsAmglM9nlx25TzVQRQt1An4=,b49a72374a14f726229e71152e74e8a132c2913137c4457f31bae8c7735e812c
+github.com/influxdata/influxdb1-client,v0.0.0-20190809212627-fc22c7df067e,h1:txQltCyjXAqVVSZDArPEhUTg35hKwVIuXwtQo7eAMNQ=,fc41ea93bf2b06b231823b116dc11b0ed89badf1ce6a4c848a33c77dcf2c123a
+github.com/influxdata/influxql,v1.0.1,h1:6PGG0SunRmptIMIreNRolhQ38Sq4qDfi2dS3BS1YD8Y=,2a697984d1cd82656f69901bfe1771676493411c1370d77271bde3ab3c917a1e
+github.com/influxdata/line-protocol,v0.0.0-20180522152040-32c6aa80de5e,h1:/o3vQtpWJhvnIbXley4/jwzzqNeigJK9z+LZcJZ9zfM=,6111b5e459106f7003477186aa2e34423dbe0c53983944a07d8b835ff8c7757c
+github.com/influxdata/promql/v2,v2.12.0,h1:kXn3p0D7zPw16rOtfDR+wo6aaiH8tSMfhPwONTxrlEc=,b928626f2eb81eed0046ef23a83a77a28dd140d369a0d2538c94e85d1055877f
+github.com/influxdata/tdigest,v0.0.0-20181121200506-bf2b5ad3c0a9,h1:MHTrDWmQpHq/hkq+7cw9oYAt2PqUw52TZazRA0N7PGE=,5d6b056d98d1e7e9cd884aea4e73934cc8ea89218eb43ee1d5140d3ccb34ed52
+github.com/influxdb/influxdb,v1.7.9,h1:KMBwwvyJyBppIwrg5t0662p+Yei/ucnIkqUl8txiQdQ=,ad251d4cc00aec767465dc60d6b702a3635b68402123a4ee5d1ee2b5006310b3
+github.com/iotexproject/go-pkgs,v0.1.1,h1:AyWJf8jqOg4aMSrxi+MInFFBZhTvSm0LCu1o08heijk=,c5099edde7450b4f8b9a0f49c42697f5e9bcb92d2bf58395aa0681f3ef6b583d
+github.com/iotexproject/iotex-address,v0.2.1,h1:ZJH2ajx5OBrbaRJ0ZWlWUo685zr5kjWijVjtmUrm42E=,53c7ce4d7fbc55ee79e92e9e0b31ee3b3ba0e6e5d3e24cd43e0a58c766568c9d
+github.com/iotexproject/iotex-proto,v0.2.5,h1:SYdl9Lqb0LYfFf3sfw92fN8GY3bthfCvGmltz+2uvDQ=,546cb070e92286601aee16d03383712172061c8fe78e53cf04498a9358470a78
+github.com/ipfs/bbloom,v0.0.4,h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=,92993c175552cc626ef6b1ab6cf887f0f640311748c47e7615df29a966c1b774
+github.com/ipfs/go-bitswap,v0.1.3,h1:jAl9Z/TYObpGeGATUemnOZ7RYb0F/kzNVlhcYZesz+0=,ee26d57b2765f808ebebca8aa18695bfa02b738f47b4b5db5efce5c91f28fbcd
+github.com/ipfs/go-block-format,v0.0.2,h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE=,02ad9fa29f97073ece45a5da7a92e59e6c6b856e9a03bd853361b8107296c020
+github.com/ipfs/go-blockservice,v0.1.2,h1:fqFeeu1EG0lGVrqUo+BVJv7LZV31I4ZsyNthCOMAJRc=,31c5ff02d71ee454bebea3944d7e06c2ffd6f1c4cfdddf71c5122e982f261c7d
+github.com/ipfs/go-cid,v0.0.3,h1:UIAh32wymBpStoe83YCzwVQQ5Oy/H0FdxvUS6DJDzms=,f8bd60f8bbd79ed1fa5c8c113f6e17addb12257b0d925d3327ee7c25a7733591
+github.com/ipfs/go-datastore,v0.1.1,h1:F4k0TkTAZGLFzBOrVKDAvch6JZtuN4NHkfdcEZL50aI=,be724f5e3a459cf6ae9e68d2fa14e27cc92c53ae775979f2412b4f5b3f2b0336
+github.com/ipfs/go-detect-race,v0.0.1,h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=,c00c97cacb355cb0569bee75775eff6b656d95dd7d0855ed97c2ee44666b72cd
+github.com/ipfs/go-ds-badger,v0.0.7,h1:NMyh88Q50HG6/S2YD58DLkq0c0/ZQPMbSojONH+PRf4=,26a453fc19eb26fe6077f12310ff1ad7230fe31b31a0c17fb47abba75379ee61
+github.com/ipfs/go-ds-leveldb,v0.1.0,h1:OsCuIIh1LMTk4WIQ1UJH7e3j01qlOP+KWVhNS6lBDZY=,43085f79b999edef0b8b49dea1ed35d47cc1c453ef401634825c0be5b62ac6d9
+github.com/ipfs/go-hamt-ipld,v0.0.13,h1:Jbt5ALTYnrzbcOBka11kAkgn3auvkQBGkKWjGRsQrio=,e16acbc3f203616ccd9119415b9db28a6f18c72f053259842f7db50aa1193cf8
+github.com/ipfs/go-ipfs-blockstore,v0.1.0,h1:V1GZorHFUIB6YgTJQdq7mcaIpUfCM3fCyVi+MTo9O88=,19a45734b2615632b180b59032d39c04c50fc735c7f9fd27c5547b0facb4ef8f
+github.com/ipfs/go-ipfs-blocksutil,v0.0.1,h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ=,3fcf4221d4d59af5807040f209ff0d28d81f6974d61ac279b43a44b2f46d8182
+github.com/ipfs/go-ipfs-chunker,v0.0.1,h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE27SEw=,02a0e4766162345a5bea8962c315b4bab8f2550aa1b760dcece96794b3ba22ef
+github.com/ipfs/go-ipfs-config,v0.0.11,h1:5/4nas2CQXiKr2/MLxU24GDGTBvtstQIQezuk7ltOQQ=,e26bdd6db98c4ccf932440aa22a1aa2d550903a0f6f9da82f1ff5902ebbe260e
+github.com/ipfs/go-ipfs-delay,v0.0.1,h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ=,bc3a4494d27cd7fabdeb7036e2edadd27f0edbd2b7d3cf49d14e3402c17c3ab6
+github.com/ipfs/go-ipfs-ds-help,v0.0.1,h1:QBg+Ts2zgeemK/dB0saiF/ykzRGgfoFMT90Rzo0OnVU=,52d0d886ebb65366abb35f19b76c4f6f349464eaedf092da95c661a451b2bf06
+github.com/ipfs/go-ipfs-exchange-interface,v0.0.1,h1:LJXIo9W7CAmugqI+uofioIpRb6rY30GUu7G6LUfpMvM=,0a593df65586ff592255eb69923a43d413b24ad56454e14e94f5e722756fb102
+github.com/ipfs/go-ipfs-exchange-offline,v0.0.1,h1:P56jYKZF7lDDOLx5SotVh5KFxoY6C81I1NSHW1FxGew=,04b69dc6dd34a2c5c2d1f0df8777fcaa8590aa528b960cc26178af6f609e29cf
+github.com/ipfs/go-ipfs-files,v0.0.6,h1:sMRtPiSmDrTA2FEiFTtk1vWgO2Dkg7bxXKJ+s8/cDAc=,442fa790aba0beff3a79503064a35dceab2a29dc4ab8edcca690c7f61ef6c6c0
+github.com/ipfs/go-ipfs-flags,v0.0.1,h1:OH5cEkJYL0QgA+bvD55TNG9ud8HA2Nqaav47b2c/UJk=,61ac13bc74f89286ac30db2ce79b26adfba63a0676cbc430ad750df2d516565a
+github.com/ipfs/go-ipfs-posinfo,v0.0.1,h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs=,149f52f33d8ffd4f82056b4ea1dae2f25024a2e8df0ff555789c549468d998e7
+github.com/ipfs/go-ipfs-pq,v0.0.1,h1:zgUotX8dcAB/w/HidJh1zzc1yFq6Vm8J7T2F4itj/RU=,4eda59f4f898933265b82d381cc1ea5a3d3c75752618f46496a2d150c09aeb2d
+github.com/ipfs/go-ipfs-routing,v0.1.0,h1:gAJTT1cEeeLj6/DlLX6t+NxD9fQe2ymTO6qWRDI/HQQ=,e2281e568eed0ee5621886d28802eefd8a9d0806cbd1db80c01550ad59ec54c7
+github.com/ipfs/go-ipfs-util,v0.0.1,h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50=,6d3af4d6dcb95047b64fc74972cdcd84f199c6bad467a7de3543c3eaa0d4ee49
+github.com/ipfs/go-ipld-cbor,v0.0.3,h1:ENsxvybwkmke7Z/QJOmeJfoguj6GH3Y0YOaGrfy9Q0I=,4087b9930a8e2899c3540e61bd8e7f04c8bdd8670f68ddbfcf10f45a0e619cef
+github.com/ipfs/go-ipld-format,v0.0.2,h1:OVAGlyYT6JPZ0pEfGntFPS40lfrDmaDbQwNHEY2G9Zs=,3da08ede588080b6ec81c5ad8fbfb1c9ea306a038be41dc06b1f3a1a101ebe50
+github.com/ipfs/go-log,v0.0.1,h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc=,9165a91716b11b432f8bf303d59fc019bf91872f1b9ca7e12d666c11ba6e6676
+github.com/ipfs/go-merkledag,v0.2.4,h1:ZSHQSe9BENfixUjT+MaLeHEeZGxrZQfgo3KT3SLosF8=,ed269e045c613cc7b9bba3593797fe09cdf84c906726bef9261c74bd8c470404
+github.com/ipfs/go-metrics-interface,v0.0.1,h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg=,e83f0c01b084000492db0c0e1a28ff900c3f6d11eea8defdbe8bdd1a04c33fd0
+github.com/ipfs/go-mfs,v0.1.1,h1:tjYEWFIl0W6vRFuM/EnySHaaYzPmDcQWwTjtYWMGQ1A=,1db35113aff60e645544cc64cbbddbf0608332b1f2208615744098af59b97fee
+github.com/ipfs/go-path,v0.0.7,h1:H06hKMquQ0aYtHiHryOMLpQC1qC3QwXwkahcEVD51Ho=,96c607c0253c24ed0cb37016007f34420a3a83c37cdd68b6d4391126418835c4
+github.com/ipfs/go-peertaskqueue,v0.1.1,h1:+gPjbI+V3NktXZOqJA1kzbms2pYmhjgQQal0MzZrOAY=,5fa92b0302d8e72e8c4d74517a68fad04c1d89d90f0a6314a5e30662dda5d359
+github.com/ipfs/go-unixfs,v0.2.2,h1:eTkDT9F0dn4qHmBMVRMZbziwyqLRcogjtPYqMgZYmQs=,77f7f6b2de604b592018dd914a6606084069d22efa70ea95e0dd623a04e4453c
+github.com/ipfs/go-verifcid,v0.0.1,h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E=,1f808a29fcd38406325435c7a6a02b253aee28832704f0032600c2b41ef3b8f1
+github.com/ipfs/interface-go-ipfs-core,v0.2.4,h1:oQiJ3Mj3rqVJohdi316K3+VSyiADto3Z35ukj7z+UGg=,e1030de5fc1ee1868a87386708be313fc0fcbbe137d5a71d71f28621393f70a2
+github.com/ipfs/iptb,v1.4.0,h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo=,0b00d0279c700ad687cfbba073f504cc4c8a17ff731550c3784fcb3e24b0c6d5
+github.com/iris-contrib/blackfriday,v2.0.0+incompatible,h1:o5sHQHHm0ToHUlAJSTjW9UWicjJSDDauOOQ2AHuIVp4=,936679f49251da75fde84b8f38884dbce89747b96f8206f7a4675bfcc7dd165d
+github.com/iris-contrib/formBinder,v5.0.0+incompatible,h1:jL+H+cCSEV8yzLwVbBI+tLRN/PpVatZtUZGK9ldi3bU=,6f1fef9e533a1f57a8b033f8c0a135ed038524d7535dd16ba22e9494e3096e3b
+github.com/iris-contrib/go.uuid,v2.0.0+incompatible,h1:XZubAYg61/JwnJNbZilGjf3b3pB80+OQg2qf6c8BfWE=,c6bae86643c2d6047c68c25226a1e75c5331c03466532ee6c943705743949bd9
+github.com/issue9/assert,v1.3.2,h1:IaTa37u4m1fUuTH9K9ldO5IONKVDXjLiUO1T9vj0OF0=,f4349cbd5af134fce10b399717aa4b455b5c73df6c20c1057c6e45973f24a06d
+github.com/issue9/identicon,v0.0.0-20160320065130-d36b54562f4c,h1:A/PDn117UYld5mlxe58EpMguqpkeTMw5/FCo0ZPS/Ko=,5a837560a10469ab524b185a092edf67be85aff5ed794e1fcaaa084cf4540336
+github.com/itchio/arkive,v0.0.0-20190702114012-1bb6c7241ec3,h1:UcZnU7qzWTmZf8v7F3mC79H98I0b77pZz+99vqHFwtI=,dad4e3a988e6834d4ce1c3fb650a8dbb9aedd116ba8b3556c8f8babecdd17ead
+github.com/itchio/dskompress,v0.0.0-20190702113811-5e6f499be697,h1:u3Q2WkrIPYlGEw4fjcImSOrkivWd6SVb0BF0Ehoih9c=,d8379b7e4219f001b61e5c2b3b34b2a6b69f8a55dc1acde2919be3050a7c84f5
+github.com/itchio/go-brotli,v0.0.0-20190702114328-3f28d645a45c,h1:Jf20xV/yR/O6eSUqLTuXhka/+54YR59sGwN7b3MkxYk=,6bab2adfb10a8ae7132e02ed10823df2e91c42dd08a1f3e1835679390ea69927
+github.com/itchio/headway,v0.0.0-20190702175331-a4c65c5306de,h1:RQW9xPqYtvjdHHRZR95XsaEA9B4URCuNHK78IuJcc+Y=,54e63fd6f25217e272e196f6213915515196a5b17a1923a666c05b4f49c82ef3
+github.com/itchio/httpkit,v0.0.0-20190702184704-639fe5edf1f1,h1:mViP/A8hAP04YWbbZR7Kcm7rTkUeT2HLcn3BBiK+CwM=,e56bf70a53a305f6866631d1272a3f3543abd45a68c50d202ddc80796b58c461
+github.com/itchio/kompress,v0.0.0-20190702090658-5e2558a00102,h1:QXEwRXrrx+7CxU+Y+G4GpDk4mUeHbP7grMXHhydk8qU=,cadec4996aed4026c0e0321f90b5bb11d9b8d1de3665752b2e862c6ddbfa229d
+github.com/itchio/ox,v0.0.0-20190925154941-b613e528fc7d,h1:EcmVffUYduCSFCEM12YpSXoVXvyeq8Ro4Q+rwc60TIo=,81c3dfe8e91eb13815bf5b7f159f24a3cb1bd7028a395f691e9cefc1c3a71d01
+github.com/itchio/randsource,v0.0.0-20190702184213-a7635a4cb94b,h1:fG+9RlMeggMG/C2FH80HTfJmm+eOjAve2pFSv6Uio8A=,2375b07785c2738527c864dfb1bee0082b1f89c51e200157165bcd36f5c2933f
+github.com/itchio/savior,v0.0.0-20190925162935-b92976a0b402,h1:a51wRxkLoJWu5NqnVDkI6cE50S0mDpJfOXkCp4ltvr8=,1454524a51fa6492ee593fb7d648dc037fec7c32d90e2d21c149b6e724a74838
+github.com/iwind/TeaGo,v0.0.0-20191007090339-daba0bb6607e,h1:bxD34HpyJWx6bnGdahZo6uN6XnuOvMa8LrzfC+eZqes=,bec78c179e2676d51bb1a07122896661d4ae7727d325e9fa91682361e0321161
+github.com/jackc/chunkreader,v1.0.0,h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=,e204c917e2652ffe047f5c8b031192757321f568654e3df8408bf04178df1408
+github.com/jackc/chunkreader/v2,v2.0.0,h1:DUwgMQuuPnS0rhMXenUtZpqZqrR/30NWY+qQvTpSvEs=,cae1df6cc4f52abdf31d9c7c9869714f5c2e2dddc8047eb6d335409489e76031
+github.com/jackc/fake,v0.0.0-20150926172116-812a484cc733,h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc=,bf8b5b51ae03f572a70a0582dc663c5733bba9aca785d39bb0367797148e6d64
+github.com/jackc/pgconn,v1.0.1,h1:ZANo4pIkeHKIVD1cQMcxu8fwrwIICLblzi9HCjooZeQ=,4b7e033c80207f032275845f7d366b51b46e3434cafebd13599a351f01f68b86
+github.com/jackc/pgio,v1.0.0,h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=,1a83c03d53f6a40339364cafcbbabb44238203c79ca0c9b98bf582d0df0e0468
+github.com/jackc/pgmock,v0.0.0-20190831213851-13a1b77aafa2,h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA=,5d8117d8fb79d3a41998bec8dca93d450eba9edf3cf0b8c36881e0ea6140b406
+github.com/jackc/pgpassfile,v1.0.0,h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=,1cc79fb0b80f54b568afd3f4648dd1c349f746ad7c379df8d7f9e0eb1cac938b
+github.com/jackc/pgproto3,v1.1.0,h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=,e3766bee50ed74e49a067b2c4797a2c69015cf104bf3f3624cd483a9e940b4ee
+github.com/jackc/pgproto3/v2,v2.0.0,h1:FApgMJ/GtaXfI0s8Lvd0kaLaRwMOhs4VH92pwkwQQvU=,22635755552d1363817a9c9f192cf464034dfc31593e4975982a85de8295dcf4
+github.com/jackc/pgtype,v0.0.0-20190828014616-a8802b16cc59,h1:xOamcCJ9MFJTxR5bvw3ZXmiP8evQMohdt2VJ57C0W8Q=,30822259b27010e41850fde5f75166abc90028b9c57e2a77976cab119e01295f
+github.com/jackc/pgx,v3.6.0+incompatible,h1:bJeo4JdVbDAW8KB2m8XkFeo8CPipREoG37BwEoKGz+Q=,07a0cc87069e38acac988cc48e5a6cfd1bfd02b4b843d0e8931e48bb8c25d821
+github.com/jackc/pgx/v4,v4.0.0-pre1.0.20190824185557-6972a5742186,h1:ZQM8qLT/E/CGD6XX0E6q9FAwxJYmWpJufzmLMaFuzgQ=,1782863d2118cd0e63cc50cca24bd79cbea5674bac3b798bf12148400590128d
+github.com/jackc/puddle,v0.0.0-20190608224051-11cab39313c9,h1:KLBBPU++1T3DHtm1B1QaIHy80Vhu0wNMErIFCNgAL8Y=,a780306bb3ad76174eca1d83a6d925fb3f7a13981cda6249e51be64476c76f15
+github.com/jackmordaunt/icns,v0.0.0-20181231085925-4f16af745526,h1:NfuKjkj/Xc2z1xZIj+EmNCm5p1nKJPyw3F4E20usXvg=,06f511df7637fd1424b6f099d7ce7ecf7378e62adc9d13133ce7df419e51faf0
+github.com/jackpal/gateway,v1.0.5,h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc=,adab846630d73763e5a3b984c8264d6503c8cb0b2914df559dacd41f6380e4ef
+github.com/jackpal/go-nat-pmp,v1.0.1,h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA=,d7f2409f72895a01e0d11b457eac015dbcd94c2657f95d508e53867ca6b07db1
+github.com/jacobsa/crypto,v0.0.0-20190317225127-9f44e2d11115,h1:YuDUUFNM21CAbyPOpOP8BicaTD/0klJEKt5p8yuw+uY=,ec4d2a1fc28e1d99c68557e38cd77527df5a9f5090aa12876ab4aa6f9137a3d5
+github.com/jacobsa/oglematchers,v0.0.0-20150720000706-141901ea67cd,h1:9GCSedGjMcLZCrusBZuo4tyKLpKUPenUUqi34AkuFmA=,bcd70357107c45c3177c913b718624376b692d39672c157708fe2cd9aa78fcb5
+github.com/jacobsa/oglemock,v0.0.0-20150831005832-e94d794d06ff,h1:2xRHTvkpJ5zJmglXLRqHiZQNjUoOkhUyhTAhEQvPAWw=,5159f5f22d0e130b1fbfdbc96eb9d4653b32bd463439cb0f3c98e179de5daf80
+github.com/jacobsa/ogletest,v0.0.0-20170503003838-80d50a735a11,h1:BMb8s3ENQLt5ulwVIHVDWFHp8eIXmbfSExkvdn9qMXI=,69d96e3ea6e055d68ed46c0c1044a5dfa18064c9d45bc68d5946aa55e048af6b
+github.com/jacobsa/reqtrace,v0.0.0-20150505043853-245c9e0234cb,h1:uSWBjJdMf47kQlXMwWEfmc864bA1wAC+Kl3ApryuG9Y=,a7efb54142e39f4acab39d22db692d5734f818723783646f6727269228deea83
+github.com/jaegertracing/jaeger,v1.14.0,h1:C0En+gfcxf3NsAriMAvQ6LcSFrQ5VQGXddqfty1EpTI=,5f6245d1b0c986c44cc37c7c950f3cf9c2cfd1e0d540905cd4fab9a164684ecd
+github.com/jarcoal/httpmock,v1.0.4,h1:jp+dy/+nonJE4g4xbVtl9QdrUNbn6/3hDT5R4nDIZnA=,5c7d051f237633573a168713760758005724c268242484d982cb0c76dc3f3ee7
+github.com/jaytaylor/html2text,v0.0.0-20190408195923-01ec452cbe43,h1:jTkyeF7NZ5oIr0ESmcrpiDgAfoidCBF4F5kJhjtaRwE=,2369830967f1c18c382cbee77a510431b42275f1f368e3b5cbbdaa782ae24c0d
+github.com/jbenet/go-base58,v0.0.0-20150317085156-6237cf65f3a6,h1:4zOlv2my+vf98jT1nQt4bT/yKWUImevYPJ2H344CloE=,e686d369d490d6728f6e63b1680db3b567c9e884545f8c47ca656f0d944299b7
+github.com/jbenet/go-cienv,v0.1.0,h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc=,3de5dadf2add50bf7fbdf88db4e6d008ba1848516585f7f9dfbf53cb6dc1705c
+github.com/jbenet/go-context,v0.0.0-20150711004518-d14ea06fba99,h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=,4cd0955abeea43dc4b5a08b8769e696109e0376f2a113a9b8eff13cc90cac1c7
+github.com/jbenet/go-temp-err-catcher,v0.0.0-20150120210811-aac704a3f4f2,h1:vhC1OXXiT9R2pczegwz6moDvuRpggaroAXhPIseh57A=,9299671a264400f8f0e145da442aa3216394f324c50f045ef2ed2b898b3945c9
+github.com/jbenet/goprocess,v0.1.3,h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10=,026bb36c2d4316ad327f8b2e623f172c01140f699d57ec8609f702df5cdf021d
+github.com/jcmturner/gofork,v1.0.0,h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8=,5e015dd9b038f1dded0b2ded77e529d2f6ba0bed228a98831af5a3610eefcb52
+github.com/jdcloud-api/jdcloud-sdk-go,v1.9.1-0.20190605102154-3d81a50ca961,h1:a2/K4HRhg31A5vafiz5yYiGMjaCxwRpyjJStfVquKds=,93754c3fe6c00591fcd499cf73ad7f66e4ed864619579ff726872a2f50b53dfa
+github.com/jdkato/prose,v1.1.0,h1:LpvmDGwbKGTgdCH3a8VJL56sr7p/wOFPw/R4lM4PfFg=,4e07b4f2012b46465fcc262d907b1cb81699bc61e6fb7a59ee47ea262e4986d1
+github.com/jeffchao/backoff,v0.0.0-20140404060208-9d7fd7aa17f2,h1:mex1izRBCD+7WjieGgRdy7e651vD/lvB1bD9vNE/3K4=,e6daeed2ffbf793cbdab5e21e9ba47ced708e7c594d4155e1964109903bd199f
+github.com/jefferai/isbadcipher,v0.0.0-20190226160619-51d2077c035f,h1:E87tDTVS5W65euzixn7clSzK66puSt1H4I5SC0EmHH4=,c438b15316e4af2487ba2c818288aa15ba19e39b3bf2f83651dcc9d451af6c5b
+github.com/jefferai/jsonx,v1.0.0,h1:Xoz0ZbmkpBvED5W9W1B5B/zc3Oiq7oXqiW7iRV3B6EI=,e8ccf27ffc8d4560e7db02f8a1663fd4605c5996a025f90721f8157fde332be7
+github.com/jellevandenhooff/dkim,v0.0.0-20150330215556-f50fe3d243e1,h1:ujPKutqRlJtcfWk6toYVYagwra7HQHbXOaS171b4Tg8=,8a3ba94d93fb61070bee24ffca5043eb32b4a6aafa9b84e4950a5f8f34328659
+github.com/jessevdk/go-flags,v1.4.0,h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=,a26e72c3f4c220df8b65ac6eb3d358a8ad2efc300b212318582893ea882726f9
+github.com/jfrazelle/go,v1.5.1-1,h1:EJWkn/L/VOoena+VQryO7xEkxz7J6lHvPXAe+Z3Q6Gc=,ff67181f47086da85e0d0896aeffb52142f6f45bd3bbf75b94cd7546365bf140
+github.com/jfrog/gofrog,v1.0.5,h1:pEJmKZ9XgvQH2a8WCqAEeUDSXBCKBMN90QzOiOhBTIs=,bb6267655de882922977dca0860020c4c781bf7b3d6aba3fddc206a21c13784c
+github.com/jfrog/jfrog-client-go,v0.5.5,h1:dYoajyMXcmc13YpZ/NLye0KL7r+QfpP9l8+WriZNZbE=,3d62cf613d821eb41b8b62ff01e09d8d4eed781f4deb52d3dd96e5a636967732
+github.com/jhump/protoreflect,v1.5.0,h1:NgpVT+dX71c8hZnxHof2M7QDK7QtohIJ7DYycjnkyfc=,a6f0926d31ed98d63d04f2aa60a5579cca471e7544cb701202ba5a5fd3134256
+github.com/jimstudt/http-authentication,v0.0.0-20140401203705-3eca13d6893a,h1:BcF8coBl0QFVhe8vAMMlD+CV8EISiu9MGKLoj6ZEyJA=,0bcf35e1ca69658b70fe05050f436b18ae141a08863cf6011afb39edef5c4013
+github.com/jinzhu/copier,v0.0.0-20190924061706-b57f9002281a,h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o=,c05742c031370bace7c0d5b4101d437e59ad4613bb707fda49c365b3e6af8ad2
+github.com/jinzhu/gorm,v1.9.11,h1:gaHGvE+UnWGlbWG4Y3FUwY1EcZ5n6S9WtqBA/uySMLE=,87f36225e1108c93f299d9b7e4cda23c2f9469ce3db0de59df90691c1e740565
+github.com/jinzhu/inflection,v1.0.0,h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=,cf1087a6f6653ed5f366f85cf0110bbbf581d4e9bc8a4d1a9b56765d94b546c3
+github.com/jinzhu/now,v1.0.1,h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=,5900b34a1d8daa959798e342e684c4237f60ffaebd1aa4201e29a7d3a98d32b7
+github.com/jlaffaye/ftp,v0.0.0-20190126081051-8019e6774408,h1:9AeqmB6KVEJ7GQU985MGQc7Mtxz1+C+JZkgqBnUWqMU=,b1b8b0e10084219eaf1a829778c1b53c049eeb77249a5660b62291cc3b454e6b
+github.com/jmcvetta/neoism,v1.3.1,h1:GCFSl/90OYwEQH5LML/Vy6UlwK4SZ2OIO278UI4K7DE=,93e9ce5946ab71d9d0970e3709716a2b9cc96b4d03cfc708dfba8f062e870885
+github.com/jmcvetta/randutil,v0.0.0-20150817122601-2bb1b664bcff,h1:6NvhExg4omUC9NfA+l4Oq3ibNNeJUdiAF3iBVB0PlDk=,742cb157c8eb74da05a7972de646034cf0ddaba7c89d8aac625ed73027e778c1
+github.com/jmespath/go-jmespath,v0.0.0-20180206201540-c2b33e8439af,h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=,5c18f15c2bcfbbdb4fd15c0598ea5d3a373991a7b46a8f2405d00ac8b6121629
+github.com/jmhodges/clock,v0.0.0-20160418191101-880ee4c33548,h1:dYTbLf4m0a5u0KLmPfB6mgxbcV7588bOCx79hxa5Sr4=,f66a541ce3f97b4696d65282a332e8d08dee3f15271b7c2066050aeb5b7334b7
+github.com/jmhodges/levigo,v1.0.0,h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=,7f43feb409c9650336152a959d7dc4d8e5a260c92e0212b1d2e0f0a7d3de6d87
+github.com/jmoiron/sqlx,v1.2.0,h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=,c8000fe80e86eea575e0d3dd0737f6399c1880a420ce2a9d833ca0e0cfc9c875
+github.com/joefitzgerald/rainbow-reporter,v0.1.0,h1:AuMG652zjdzI0YCCnXAqATtRBpGXMcAnrajcaTrSeuo=,889ea7a751c043bd0ea0ee31734011938be19ecbf08e652d53fc41f3eade9435
+github.com/joeshaw/multierror,v0.0.0-20140124173710-69b34d4ec901,h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4=,e31f735c5f42ac65aef51a70ba1a32b5ac34067a7ba0624192dd41e5ea03aa1e
+github.com/joho/godotenv,v1.3.0,h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=,acef5a394fbd1193f52d0d19690b0bfe82728d18dd3bf67730dc5031c22d563f
+github.com/jonas-p/go-shp,v0.1.1,h1:LY81nN67DBCz6VNFn2kS64CjmnDo9IP8rmSkTvhO9jE=,ac1706c486b7ea7e83eecd1f773259098569d2fe3ad2a53cc32ff89a68915a8f
+github.com/jonboulle/clockwork,v0.1.0,h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=,930d355d1ced60a668bcbca6154bb5671120ba11a34119505d1c0677f7bbbf97
+github.com/joncalhoun/qson,v0.0.0-20170526102502-8a9cab3a62b1,h1:lnrOS18wZBYrzdDmnUeg1OVk+kQ3rxG8mZWU89DpMIA=,062b14a6986be3fb833eb9dd907acb7e563d5b6cfcaee1a04120a9b1fcc2d451
+github.com/josephspurrier/goversioninfo,v0.0.0-20190124120936-8611f5a5ff3f,h1:wBb8/KQrr2tWYffdugrpxOdWyOPSBRNzAR76aF9Nn3Y=,50be4b48f9fb8fbe79a013a791c015c13d7294c5de8f9bee586eaadd6f479459
+github.com/joyent/triton-go,v0.0.0-20190112182421-51ffac552869,h1:BvV6PYcRz0yGnWXNZrd5wginNT1GfFfPvvWpPbjfFL8=,5e875a04efd7f844211b68657d21313ae16b479cb01dc7161811c2c39ac19b18
+github.com/jpillora/backoff,v1.0.0,h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=,f856692c725143c49b9cceabfbca8bc93d3dbde84a0aaa53fb26ed3774c220cc
+github.com/jrick/logrotate,v1.0.0,h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=,b87ee434f9e2cfda719b639cd5bd0a52523f920f64d23336f88070e9d3765d54
+github.com/jsimonetti/rtnetlink,v0.0.0-20190606172950-9527aa82566a,h1:84IpUNXj4mCR9CuCEvSiCArMbzr/TMbuPIadKDwypkI=,97d995d4ca858da8955aefcead01425d12a91188d6f9b36b5cb63aa35a4ea674
+github.com/json-iterator/go,v1.1.8,h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=,0de8f316729fb05ba608361323b178aa32944154e77aa208ad2818848b0628e2
+github.com/jstemmer/go-junit-report,v0.0.0-20190106144839-af01ea7f8024,h1:rBMNdlhTLzJjJSDIjNEXX1Pz3Hmwmz91v+zycvx9PJc=,b623acfae0dcc440f81ae14f3c5bc3ca40b1a674660ad549127980f892ab165e
+github.com/jteeuwen/go-bindata,v3.0.7+incompatible,h1:91Uy4d9SYVr1kyTJ15wJsog+esAZZl7JmEfTkwmhJts=,03f794b47c49da98a4eab6c3a7cc49d286f012d64ab832f783b76b9fcd3bd8b2
+github.com/jtolds/gls,v4.20.0+incompatible,h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=,2f51f8cb610e846dc4bd9b3c0fbf6bebab24bb06d866db7804e123a61b0bd9ec
+github.com/jtolds/go-luar,v0.0.0-20170419063437-0786921db8c0,h1:UyVaeqfY1fLPMt1iUTaWsxUNxYAzZVyK+7G+a3sRfhk=,1ed97930b5dfc7f89c84ff3c5ea5a7de9964ccca970f45853d42a13a138b644e
+github.com/jtolds/monkit-hw,v0.0.0-20190108155550-0f753668cf20,h1:XK96humQhnPbQ24uKtSHKbdShDgrKYqlWBNKJTcIKbg=,5d84e6f3f559b67e00b08a5e93e1017866695a4590b97ccb23a82e3ce792ad04
+github.com/juju/ansiterm,v0.0.0-20180109212912-720a0952cc2a,h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=,17d1e05fd6f1c8fdce7ba7495af54f4dac1e155febff56bd6450593b016655c2
+github.com/juju/clock,v0.0.0-20190205081909-9c5c9712527c,h1:3UvYABOQRhJAApj9MdCN+Ydv841ETSoy6xLzdmmr/9A=,f57579c0c104add5228b279c4673f592d5756033d33b085185ef72a3d2f83bfe
+github.com/juju/cmd,v0.0.0-20190815094254-0c5c82a8dfc6,h1:rPqkdymtMRLcCSYKOeIxuw5mmd8dWx8jSq+t9EGBgtA=,c603f2311cf6524a74535eb9d416a83959c03e6ad52ab4ec081cbc7343734af6
+github.com/juju/collections,v0.0.0-20180717171555-9be91dc79b7c,h1:m/Uo8B7nrH3K6nvk66Y67T7cbHcyY101rW24vGuMON8=,18275066d75835f37845565980c0ac818f9c29145f756b1eeacb6496dac3ebd3
+github.com/juju/errors,v0.0.0-20190930114154-d42613fe1ab9,h1:hJix6idebFclqlfZCHE7EUX7uqLCyb70nHNHH1XKGBg=,2519c885f89cfba663da3bd9a1ff2532e3ae948bdea3e44b42603d8f91cc0796
+github.com/juju/gnuflag,v0.0.0-20171113085948-2ce1bb71843d,h1:c93kUJDtVAXFEhsCh5jSxyOJmFHuzcihnslQiX8Urwo=,47cdfb1bf94a2719e97e03caf4e0dc1cb89ba27c35ed7ce7020701fe8ee2c353
+github.com/juju/gojsonpointer,v0.0.0-20150204194629-afe8b77aa08f,h1:QzpKmMsaP06HVZnYNlcy1CLIXPytsj2NuzfCHitxuus=,0e75303c5dc230f30a629963589376030c3c2a1152a40b9e2075a084224eb173
+github.com/juju/gojsonreference,v0.0.0-20150204194633-f0d24ac5ee33,h1:huRsqE0iXmVPTML75YvFBOiaNj4ZiCZgKVnkRQ06d3w=,d1648b2f71dfbb02acc4a18c55711c721e0f6b50a5280d852cd9c0a639e8ebe6
+github.com/juju/gojsonschema,v0.0.0-20150312170016-e1ad140384f2,h1:VqIDC6dRE0C7wEtTdT6zx2zP5omaoJiZXp2g/dBHRcE=,a9f736e7cb462ccf3b2cb03aa8a133db13dc8d938a2753329a7a1274bdca2656
+github.com/juju/httpprof,v0.0.0-20141217160036-14bf14c30767,h1:COsaGcfAONDdIDnGS8yFdxOyReP7zKQEr7jFzCHKDkM=,9a8c77f887765536c312c89d73d7568126393c7d38c473a50addbec30f8c80ec
+github.com/juju/httprequest,v2.0.0+incompatible,h1:+WtiSbRkEwdqKRBi+4JH8PTdNxBa/h8U8RIzdYaMENI=,0d2ae765c01f7956da6896b7c7d8bb1ad4065e960b93c09a644e2e61a0acaa52
+github.com/juju/jsonschema,v0.0.0-20161102181919-a0ef8b74ebcf,h1:SGTxyCG74uh2dYdBJCUJOo2FSx0fRHP7nMRH7s5JVeQ=,a5681c88d87b34d10dcf701b10d149303fa6d152ee224dc1bd7bd7680da80bfa
+github.com/juju/loggo,v0.0.0-20190526231331-6e530bcce5d8,h1:UUHMLvzt/31azWTN/ifGWef4WUqvXk0iRqdhdy/2uzI=,3db058c07ced25b8689f5d3e462d344ffb965c6f371eabc0396ce94d927e6206
+github.com/juju/lru,v0.0.0-20190314140547-92a0afabdc41,h1:/ucixsNZ+l94agL5LZioJ4ECyOz7kOYY+DKb/0NN6ME=,8f41907249beb66ba4dee5df1f53c37f387506e21568cc89db4b72493b970e85
+github.com/juju/os,v0.0.0-20191022170002-da411304426c,h1:iJZl5krsl2AqkgU7IiJ2/jNAchctLFa3BiKdyOUvK+g=,b236cb3d90b3fae0f83e767feef3a17b472ab0fe238ac08810c4f9c1d683c14d
+github.com/juju/proxy,v0.0.0-20180523025733-5f8741c297b4,h1:y2eoq0Uof/dWLAXRyKKGOJuF0TEkauPscQI7Q1XQqvM=,443cd58a22392e66576d883b9d04c17faebafa37a406a346b671f7e994436c34
+github.com/juju/pubsub,v0.0.0-20190419131051-c1f7536b9cc6,h1:2aARJxmMC2IF9GqVtt5PYcIy4jyuAcR44byqwXKTK0o=,b908f7985f6250270708c2c46ca0ccfc17a3705fea4a27da6f1277a9f6b5404c
+github.com/juju/qthttptest,v0.0.1,h1:pR8nTl6Uo/iI6/ynQf5Cxy9FEICXzaa83NtrBdGMCVQ=,4ba292a46e27af468c181118214f7eb1bfc015f289e90841d7746b954f20ba49
+github.com/juju/ratelimit,v1.0.1,h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY=,c9af5c6719ce3b6912579a029cb2a651707aa25daa1921488f9cae9c4f8ed334
+github.com/juju/retry,v0.0.0-20180821225755-9058e192b216,h1:/eQL7EJQKFHByJe3DeE8Z36yqManj9UY5zppDoQi4FU=,c5b2437ff128cf13f2d6f3cc3b7e226f2c0119e22caed286946245150b9428e7
+github.com/juju/schema,v1.0.0,h1:sZvJ7iQXHhMw/lJ4YfUmq+fe7R2ZSUzZzd/eSokaB3M=,746bcab557bed4e05456419e5012573dc8481dc8740309100e4bd901ff282a39
+github.com/juju/testing,v0.0.0-20191001232224-ce9dec17d28b,h1:Rrp0ByJXEjhREMPGTt3aWYjoIsUGCbt21ekbeJcTWv0=,317de254f343f9aff6e1226b4ea225cab92fee84667db8e72d541667715ea610
+github.com/juju/txn,v0.0.0-20190612234757-afeb83d59782,h1:FcaMWAFKHuxS7UAaB/GuLWrqI9L7f20m6aXaxg+t5lY=,4656c1c5f0e3dac641999feba77879c7206aff1d606513d7bdb3be7d17a6635c
+github.com/juju/utils,v0.0.0-20180820210520-bf9cc5bdd62d,h1:irPlN9z5VCe6BTsqVsxheCZH99OFSmqSVyTigW4mEoY=,8edd8a74c692eb717156a2bb689e1e24a446656677760dc7dc06b761ee451df5
+github.com/juju/version,v0.0.0-20180108022336-b64dbd566305,h1:lQxPJ1URr2fjsKnJRt/BxiIxjLt9IKGvS+0injMHbag=,73312c50c8b4f6f8644aaccc09b71a2235c8083cfc6c99425540f3c0a3c29e64
+github.com/juju/webbrowser,v1.0.0,h1:JLdmbFtCGY6Qf2jmS6bVaenJFGIFkdF1/BjUm76af78=,7b38f053656e4a883bc122589994e4ec34eae3f833e899450650752d5b72eec8
+github.com/juliangruber/go-intersect,v1.0.0,h1:0XNPNaEoPd7PZljVNZLk4qrRkR153Sjk2ZL1426zFQ0=,e7f539e6b13470da34009d3ab44c6ba84a6b9bb9f6e92d315551919287a25e3c
+github.com/julienschmidt/httprouter,v1.3.0,h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=,e457dccd7015f340664e3b8cfd41997471382da2f4a743ee55be539abc6ca1f9
+github.com/jung-kurt/gofpdf,v1.0.3-0.20190309125859-24315acbbda5,h1:PJr+ZMXIecYc1Ey2zucXdR73SMBtgjPgwa31099IMv0=,f0fa70ade137185bbff2f016831a2a456eaadc8d14bc7bf24f0229211820c078
+github.com/justinas/alice,v0.0.0-20171023064455-03f45bd4b7da,h1:5y58+OCjoHCYB8182mpf/dEsq0vwTKPOo4zGfH0xW9A=,3d6623831901bb973db882bbaffcff3f55849724100ee72c5bf8d0fdfa927ae4
+github.com/jzelinskie/whirlpool,v0.0.0-20170603002051-c19460b8caa6,h1:RyOL4+OIUc6u5ac2LclitlZvFES6k+sg18fBMfxFUUs=,ca0115fcfaaa03f1973f65d05c6d6aefdbdeca6507cdda4359fdf55fd0be2c48
+github.com/k0kubun/colorstring,v0.0.0-20150214042306-9440f1994b88,h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM=,32a2eac0ffb69c6882b32ccfcdd76968cb9dfee9d9dc3d469fc405775399167c
+github.com/k0kubun/pp,v3.0.1+incompatible,h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd9g2S9Z40=,2b91f559df17a49554094e4befd7e1c7d32ba4519417b1b36796d9b49d7328c5
+github.com/kami-zh/go-capturer,v0.0.0-20171211120116-e492ea43421d,h1:cVtBfNW5XTHiKQe7jDaDBSh/EVM4XLPutLAGboIXuM0=,fb1ef7d18f4cec39e9115fb200fbf7d5cff65674afe6ecc63ad57d413f503830
+github.com/kamilsk/retry/v4,v4.3.1,h1:hNQmK1xAgybAVsadNAGvCNutFLS2h+Ycpw317u4d+i0=,74181d82f9bba5b7c313c6b338f127668fffbede70f5495a4a2ef8fddaa6c20f
+github.com/kardianos/osext,v0.0.0-20190222173326-2bc1f35cddc0,h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=,10976c39b58f218a6e29687d19763845e7650d04ac86096cd67ace58f4e56346
+github.com/karrick/godirwalk,v1.13.0,h1:GJq8GHQEAPsjwqfGhLNXBO5P0dS2HYdDRVWe+P4E/EQ=,9652ac9eb85bf13594ba9c41a86864ec5236e429a65f6bbb19c6897d1e335092
+github.com/kataras/golog,v0.0.9,h1:J7Dl82843nbKQDrQM/abbNJZvQjS6PfmkkffhOTXEpM=,bb4d1476d5cbe33088190116a5af7b355fd62858127a8ea9d30d77701279350e
+github.com/kataras/iris,v11.1.1+incompatible,h1:c2iRKvKLpTYMXKdVB8YP/+A67NtZFt9kFFy+ZwBhWD0=,9aba6b1128d42ee2b63a9319e28c1b665b7e82dde1b10763ee7510bcc6427a25
+github.com/kataras/pio,v0.0.0-20190103105442-ea782b38602d,h1:V5Rs9ztEWdp58oayPq/ulmlqJJZeJP6pP79uP3qjcao=,70a50855f07ff59d96db9633a0cf729280a8b9f7af72b936fe8a28e48406432f
+github.com/kavu/go_reuseport,v1.4.0,h1:YIp/96RZ3sJfn0LN+FFkkXIq3H3dfVOdRUtNejhDcxc=,b08d4f774766e1136fd256484f2584d42cd568b5edc7dbc7b19e1259b5dbb75c
+github.com/kballard/go-shellquote,v0.0.0-20180428030007-95032a82bc51,h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=,ae4cb7b097dc4eb0c248dff00ed3bbf0f36984c4162ad1d615266084e58bd6cc
+github.com/kellydunn/golang-geo,v0.7.0,h1:A5j0/BvNgGwY6Yb6inXQxzYwlPHc6WVZR+MrarZYNNg=,4f4699636a450e20bd107fb81894fcdcc8ceeddbac7062e9457c67326c1fb036
+github.com/kelseyhightower/envconfig,v1.4.0,h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=,af674112c38290862e5f59fc2867b81f7b0e623ec2fd1465cd3812e538b351d3
+github.com/kennygrant/sanitize,v1.2.4,h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=,733211913a22ff6eb5843455345fde8c0c3cff25cc5e8e8225c330fb4c6a72df
+github.com/kevinburke/ssh_config,v0.0.0-20190725054713-01f96b0aa0cd,h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=,ebd98d4bfd0deb1825d9a54689560b42a17d87385222971117ad72e7ad2f36fa
+github.com/keybase/go-crypto,v0.0.0-20190403132359-d65b6b94177f,h1:Gsc9mVHLRqBjMgdQCghN9NObCcRncDqxJvBvEaIIQEo=,a839bacd8eb0a61a72f84678d568d8df899b512510a326e06db0f191e8c1c5a1
+github.com/kisielk/errcheck,v1.2.0,h1:reN85Pxc5larApoH1keMBiu2GWtPqXQ1nc9gx+jOU+E=,709eeca978804f41720a94bc69ee3cfa8277f7d15016478a3ebda86606a286c5
+github.com/kisielk/gotool,v1.0.0,h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=,089dbba6e3aa09944fdb40d72acc86694e8bdde01cfc0f40fe0248309eb80a3f
+github.com/kisielk/sqlstruct,v0.0.0-20150923205031-648daed35d49,h1:o/c0aWEP/m6n61xlYW2QP4t9424qlJOsxugn5Zds2Rg=,dbff9241f676de69e88bc006004da6087576433457b306f53cb952d0313ccb78
+github.com/kisom/goutils,v1.1.0,h1:z4HEOgAnFq+e1+O4QdVsyDPatJDu5Ei/7w7DRbYjsIA=,a0b58731f8e1144c013107294885891c44b7fd3235da0ec20776f4d644b4eaa4
+github.com/kkdai/bstream,v1.0.0,h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8=,dc1d546e0df6ef040963bc9d483834d6e56c77e0e4f6c48e574ac360e7723121
+github.com/klauspost/compress,v1.8.2,h1:Bx0qjetmNjdFXASH02NSAREKpiaDwkO1DRZ3dV2KCcs=,4dc2632696a9cd93cc32c1564e1a6aa4aecfcb5c995a077d45c6f92116e1711d
+github.com/klauspost/cpuid,v1.2.1,h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=,8367d6c97e74f88b149ba9de708ff321273e0114aeb71a45e62e5ac296412420
+github.com/klauspost/crc32,v0.0.0-20161016154125-cb6bfca970f6,h1:KAZ1BW2TCmT6PRihDPpocIy1QTtsAsrx6TneU/4+CMg=,6b632853a19f039138f251f94dbbdfdb72809adc3a02da08e4301d3d48275b06
+github.com/klauspost/pgzip,v1.2.1,h1:oIPZROsWuPHpOdMVWLuJZXwgjhrW8r1yEX8UqMyeNHM=,a482336aa4b0e4e9368b15d75629ae741b44ef290b7d16430ba05ce561846213
+github.com/klauspost/reedsolomon,v1.9.2,h1:E9CMS2Pqbv+C7tsrYad4YC9MfhnMVWhMRsTi7U0UB18=,ea8a4d6d994088dae0308843fd6bddb7541cf36306463a696fd4a29097496705
+github.com/knative/pkg,v0.0.0-20191031171713-d4ce00139499,h1:ha5eqzJaPg1CZroomqWxHqspOqpqpRMO3fDtgF1fvIM=,a8d19fc2196a1aec7869ca45df44ba9c5de5b81b6094f0579d25989eb7967660
+github.com/kniren/gota,v0.9.0,h1:ywFrdNxkBD5Xypk5BxjCaKiH507oQVXIf31pTvRhC4I=,062182a345c456c9c0fd7ce9644900708f7f9c08707d64fe2438b9d295dad6dd
+github.com/knq/sysutil,v0.0.0-20191005231841-15668db23d08,h1:V0an7KRw92wmJysvFvtqtKMAPmvS5O0jtB0nYo6t+gs=,81ec4ac93dba6a6161264a0575f20235d8932abab0cd6b9777b4be936f5c2af5
+github.com/knqyf263/berkeleydb,v0.0.0-20190501065933-fafe01fb9662,h1:UGS0RbPHwXJkq8tcba8OD0nvVUWLf2h7uUJznuHPPB0=,1e575b5fdc170e0318ab06841873ae6d115978fbaffc3779290d7ba3aadbdf0e
+github.com/knqyf263/go-deb-version,v0.0.0-20190517075300-09fca494f03d,h1:X4cedH4Kn3JPupAwwWuo4AzYp16P0OyLO9d7OnMZc/c=,4a09d0533768cf6f9d929858aa2e79b6942685569c2db00b8d4688590a89ba3d
+github.com/knqyf263/go-rpmdb,v0.0.0-20190501070121-10a1c42a10dc,h1:pumO9pqmRAjvic6oove22RGh9wDZQnj96XQjJSbSEPs=,33a3568289d22672dfcb0ba7c5b8aa7f9223d5303003368e7dbe8c9718a803b4
+github.com/knqyf263/nested,v0.0.1,h1:Sv26CegUMhjt19zqbBKntjwESdxe5hxVPSk0+AKjdUc=,c0e123844a174b1e9929d4368d8a8bb2f5ecef578ee9dee692c5971a47a633ff
+github.com/koki/structurederrors,v0.0.0-20180506174113-6b997eb5e2ca,h1:KmXUVzyPjXzd3kY0feNFsWOGVDYFT4MjjgG8QJx0m6k=,1efa717c181722fd1c6807919571dc559b48d17120f5eeb4638a322fb882411a
+github.com/kolo/xmlrpc,v0.0.0-20190717152603-07c4ee3fd181,h1:TrxPzApUukas24OMMVDUMlCs1XCExJtnGaDEiIAR4oQ=,9d37c94f50784536aa8ef9a7623ec7bcac9e5bc67b18f7a801efc7cbbe6b1ab0
+github.com/konsorten/go-windows-terminal-sequences,v1.0.2,h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=,4d00d71b8de60bcaf454f8f867210ebcd05e75c0a7c2725904f71aa2f20fb08e
+github.com/koron/go-ssdp,v0.0.0-20180514024734-4a0ed625a78b,h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ=,3a99f050b7a668291942cada4e38213965fa0ae3794469bb29ad0d6d9677db23
+github.com/kr/fs,v0.1.0,h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=,d376bd98e81aea34585fc3b04bab76363e9e87cde69383964e57e9779f2af81e
+github.com/kr/logfmt,v0.0.0-20140226030751-b84e30acd515,h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=,ebd95653aaca6182184a1b9b309a65d55eb4c7c833c5e790aee11efd73d4722c
+github.com/kr/pretty,v0.1.0,h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=,06063d21457e06dc2aba4a5bd09771147ec3d8ab40b224f26e55c5a76089ca43
+github.com/kr/pty,v1.1.8,h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=,d66e6fbc65e772289a7ff8c58ab2cdfb886253053b0cea11ba3ca1738b2d6bc6
+github.com/kr/text,v0.1.0,h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=,9363a4c8f1f3387a36014de51b477b831a13981fc59a5665f9d21609bea9e77c
+github.com/kshvakov/clickhouse,v1.3.4,h1:p/yqvOmeDRH+KyCH6NtwExelr4rimLBBfKW2a/wBN94=,01a0d1a90e0545da94350319a52c051257fee64c838e2632ec40ef8d89a2f153
+github.com/kylelemons/go-gypsy,v0.0.0-20160905020020-08cad365cd28,h1:mkl3tvPHIuPaWsLtmHTybJeoVEW7cbePK73Ir8VtruA=,321087246482a680bd3f06de64075fb843430da544596ad216a4a63d5b8dafa3
+github.com/kylelemons/godebug,v1.1.0,h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=,dbbd0ce8c2f4932bb03704d73026b21af12bd68d5b8f4798dbf10a487a2b6d13
+github.com/kyokomi/emoji,v2.1.0+incompatible,h1:+DYU2RgpI6OHG4oQkM5KlqD3Wd3UPEsX8jamTo1Mp6o=,0721a2fc643e49e002bd8a3e604b5d2f0f3e242cc279d14d76f90a55f8aeebf7
+github.com/labbsr0x/bindman-dns-webhook,v1.0.2,h1:I7ITbmQPAVwrDdhd6dHKi+MYJTJqPCK0jE6YNBAevnk=,d1a327ab22f62486250f50f98990c0d9e1a5fdece6a496fbbb85d4e123df3244
+github.com/labbsr0x/goh,v1.0.1,h1:97aBJkDjpyBZGPbQuOK5/gHcSFbcr5aRsq3RSRJFpPk=,84c91135623961c7c400bf8b646da76c0ce2941fe8706d5aef5650be9a5e37dd
+github.com/labstack/echo,v3.3.10+incompatible,h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=,29634743cf44c47079b74812ecf5aa7074630507886c4ff40b60c397c45af524
+github.com/labstack/gommon,v0.3.0,h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=,2783ed1c24d09a5539bc35954f71f41d270d78dc656be256c98a8ede2cbbe451
+github.com/lafriks/xormstore,v1.0.0,h1:P/IJzNSIpjXl/Up3o2Td5ZU/x4v6DEKLMaPQJGtmJCk=,0e347e24ab91f62e1b69bab5d78cbba77569f087b483569ef37761e1f93a3f46
+github.com/lann/builder,v0.0.0-20180802200727-47ae307949d0,h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=,1fe7a88079ff2bbe90fb4724fb5c353ecb6af4cd7e011440354c804f678895ee
+github.com/lann/ps,v0.0.0-20150810152359-62de8c46ede0,h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk=,76756d46634f44edd3facdb01e7271ddf23a1b51a8423de55d3a2bf685ff032a
+github.com/leanovate/gopter,v0.2.4,h1:U4YLBggDFhJdqQsG4Na2zX7joVTky9vHaj/AGEwSuXU=,99b27788411d478764bf7c51e4f6e84e5ccd60f3959a88a03e96b2a1d519a45d
+github.com/leodido/go-urn,v1.2.0,h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=,8a854d784171000a69b79babb2cd3da9b8fccb1e1b6bb102c7a6d2b52380d08a
+github.com/lestrrat-go/jspointer,v0.0.0-20181205001929-82fadba7561c,h1:pGh5EFIfczeDHwgMHgfwjhZzL+8/E3uZF6T7vER/W8c=,a64de11dd2840c3251906c5fe5f61719713af52a41287411007434684745af39
+github.com/lestrrat-go/jsref,v0.0.0-20181205001954-1b590508f37d,h1:1eeFdKL5ySmmYevvKv7iECIc4dTATeKTtBqP4/nXxDk=,1acee9b59501460f5063a82bc2c05f1a11cd24077198fc08ba100ee642d3db72
+github.com/lestrrat-go/jsschema,v0.0.0-20181205002244-5c81c58ffcc3,h1:TSKrrGm89gmmVlrG34ZzCIOMNVk5kkSV1P88Dt38DiE=,1b7552a5ecd193bdd07995226f58fe48de0aadedbcb42f3a5b135fd7b3538ea4
+github.com/lestrrat-go/jsval,v0.0.0-20181205002323-20277e9befc0,h1:w4rIjeCV/gQpxtn3i1voyF6Hd7v1mRGIB63F7RZOk1U=,f060af1b36e0f156546436dcc9b1569600871185d69e9daf214f24e0e2934784
+github.com/lestrrat-go/pdebug,v0.0.0-20180220043849-39f9a71bcabe,h1:S7XSBlgc/eI2v47LkPPVa+infH3FuTS4tPJbqCtJovo=,17690c72219264e0a195dac69ae6ed12bbadf309242dbaa21609339dfa74b3a5
+github.com/lestrrat-go/structinfo,v0.0.0-20190212233437-acd51874663b,h1:YUFRoeHK/mvRjBR0bBRDC7ZGygYchoQ8j1xMENlObro=,8dd77f51595dea974553558e0d249059b9047a39354548b5bbd88b32cf3df75a
+github.com/lestrrat/go-jsschema,v0.0.0-20181205002244-5c81c58ffcc3,h1:UaOmzcaCH2ziMcSbQFBq/3Iuz/E/Jr/GOGtV80jpFII=,ce0f1e04d70eadcc75f96d70703b53231e1c5be7d9fd832c144e0135bfd5afb4
+github.com/lib/pq,v1.2.0,h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=,cb1028c395747cacafb6c3c6ad5fa244563ce641aae45cf7742f98b6764b1fde
+github.com/libp2p/go-addr-util,v0.0.1,h1:TpTQm9cXVRVSKsYbgQ7GKc3KbbHVTnbostgGaDEP+88=,d49a37e15540c8b95f845dde6cdf802e7af490bc13fd88fec3da318d08464f7b
+github.com/libp2p/go-buffer-pool,v0.0.2,h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs=,fef932705b72198df3d50befd9d2aa157aea1b5f3d23712b09d627d02cfe841e
+github.com/libp2p/go-conn-security,v0.0.1,h1:4kMMrqrt9EUNCNjX1xagSJC+bq16uqjMe9lk1KBMVNs=,e7b58f887c8a8a2ed0178d2f0d6b4ad36bdd7b8cf52ca4d66bafc108b80d095c
+github.com/libp2p/go-conn-security-multistream,v0.1.0,h1:aqGmto+ttL/uJgX0JtQI0tD21CIEy5eYd1Hlp0juHY0=,597b249bd51de097142815318b13c339752532f15131887492d9d3e3407ab92e
+github.com/libp2p/go-eventbus,v0.1.0,h1:mlawomSAjjkk97QnYiEmHsLu7E136+2oCWSHRUvMfzQ=,1b02c8340d2740f99d67078a8c8823c6b9212b92dd9ca7eaf2a38adf2bfd6b56
+github.com/libp2p/go-flow-metrics,v0.0.1,h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s=,f783542a7fce8382de9cea6940049b106cc35f9714126a1e3d61925c29db8617
+github.com/libp2p/go-libp2p-autonat,v0.1.0,h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU=,11e86ef0b36125a7cd6aa447ffe488f7f3ab00e441bdf8cf30a832a41da4342c
+github.com/libp2p/go-libp2p-blankhost,v0.1.4,h1:I96SWjR4rK9irDHcHq3XHN6hawCRTPUADzkJacgZLvk=,9cd5abe8ad2f137c13309a9dbdd213376bbec03f9685cf8cde7fbfe2e5783e7d
+github.com/libp2p/go-libp2p-circuit,v0.1.0,h1:eniLL3Y9aq/sryfyV1IAHj5rlvuyj3b7iz8tSiZpdhY=,24ee6c7851f4f0072922ae497c230718a0f44beab890d0403261b38a2946a866
+github.com/libp2p/go-libp2p-core,v0.2.4,h1:Et6ykkTwI6PU44tr8qUF9k43vP0aduMNniShAbUJJw8=,d521cc1bffba8afc8b8057901cf22c2f6ffd88faec0274426e13c4e7c12c756c
+github.com/libp2p/go-libp2p-crypto,v0.1.0,h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ=,14ef1867bd8b0ef8fc528f5069ef267270dd0de8cf89a235beb9fbd79e4bed8d
+github.com/libp2p/go-libp2p-discovery,v0.2.0,h1:1p3YSOq7VsgaL+xVHPi8XAmtGyas6D2J6rWBEfz/aiY=,d1c0800b601cbe6833522727b249567379422e9f324b7d0a0866bd86c74fb930
+github.com/libp2p/go-libp2p-host,v0.1.0,h1:OZwENiFm6JOK3YR5PZJxkXlJE8a5u8g4YvAUrEV2MjM=,d26bf1db299917f080a13ace37ef4363c08c2407c126cee59e642b1372d2b211
+github.com/libp2p/go-libp2p-interface-connmgr,v0.0.5,h1:KG/KNYL2tYzXAfMvQN5K1aAGTYSYUMJ1prgYa2/JI1E=,fe1e74365cc5c155161e5500671a8e9a85a90efdad9f5630bdfdc15bdfc52fe5
+github.com/libp2p/go-libp2p-interface-pnet,v0.0.1,h1:7GnzRrBTJHEsofi1ahFdPN9Si6skwXQE9UqR2S+Pkh8=,9767f78f87f54bdf3fb1f0f9b5f67e907463b445a00a566402bacca85749c8fe
+github.com/libp2p/go-libp2p-loggables,v0.1.0,h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8=,351c87c02c2b147193fac5c441d8767d2b247cd3f3c420fa205da2ccd1c3f00f
+github.com/libp2p/go-libp2p-metrics,v0.1.0,h1:v7YMUTHNobFaQeqaMfJJMbnK3EPlZeb6/KFm4gE9dks=,a86fe0ae6cda820fd6a0e576bcd94a22360439819f344a9121086b31c651caaf
+github.com/libp2p/go-libp2p-mplex,v0.2.1,h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8iGvirYI=,f11961ef5114e57eb176740a066e1535132c8c238bd444ed53d94fad36ba7708
+github.com/libp2p/go-libp2p-nat,v0.0.4,h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw=,4c3db4e0f7f714439364ca0853f63d426bba67924da6fd050fd0184abdfec2df
+github.com/libp2p/go-libp2p-net,v0.1.0,h1:3t23V5cR4GXcNoFriNoZKFdUZEUDZgUkvfwkD2INvQE=,4140afd418393c2a4ecccca97d80b4752d20da6f34fac15fbdc4f0566f7b8cea
+github.com/libp2p/go-libp2p-netutil,v0.1.0,h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ=,c98ad0a3ffab37b6a0bc80aefba4e4cb442b09c01277a7dcc0086c4a004e649a
+github.com/libp2p/go-libp2p-peer,v0.2.0,h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY=,5b400d6b6337cc759846d7ddf50ec2d761148e1447a86982696687ef1e792c1a
+github.com/libp2p/go-libp2p-peerstore,v0.1.4,h1:d23fvq5oYMJ/lkkbO4oTwBp/JP+I/1m5gZJobNXCE/k=,1606c0bb56c31d0249980b8a0c0e5dda9212687b1994ef47cfd42039d4cf1847
+github.com/libp2p/go-libp2p-protocol,v0.1.0,h1:HdqhEyhg0ToCaxgMhnOmUO8snQtt/kQlcjVk3UoJU3c=,4560018136a73817e03eed49af46d97dd561b3eeffb1ff00559152acf9a74627
+github.com/libp2p/go-libp2p-pubsub,v0.2.0,h1:4UXcjpQdpam/RsGhfWyT/4u5f6F42ods/WgDAaocYxA=,bde7bb50d950b8ea7902c523a696eff4ad7b5d0daac808356358ff6d53aecb14
+github.com/libp2p/go-libp2p-record,v0.1.1,h1:ZJK2bHXYUBqObHX+rHLSNrM3M8fmJUlUHrodDPPATmY=,27a3e94e144b893cbb5ceaddfa7a4e456052e173f807db52945e06920f62d0b3
+github.com/libp2p/go-libp2p-routing,v0.1.0,h1:hFnj3WR3E2tOcKaGpyzfP4gvFZ3t8JkQmbapN0Ct+oU=,4241980dadf216e937a42a572a9c5b5eb28ff62458380ad37892c5b5095de270
+github.com/libp2p/go-libp2p-secio,v0.2.0,h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXYwAWqHng=,979a82829f3188d4ca8d20d194923c5620ff12a161d13c945c1630b7b9d050ff
+github.com/libp2p/go-libp2p-swarm,v0.2.2,h1:T4hUpgEs2r371PweU3DuH7EOmBIdTBCwWs+FLcgx3bQ=,b920f69fbfaa8805047b958c6d45d944a195181dd6dddab36bead5fe68f2f1e4
+github.com/libp2p/go-libp2p-testing,v0.1.0,h1:WaFRj/t3HdMZGNZqnU2pS7pDRBmMeoDx7/HDNpeyT9U=,e1c7fa467d88b33f2fc519542cc19aa48bcade304f579f10ab402a19c38d0aa6
+github.com/libp2p/go-libp2p-transport,v0.0.5,h1:pV6+UlRxyDpASSGD+60vMvdifSCby6JkJDfi+yUMHac=,df7bc96a5d76c351fd3a6ee29995f4974013d9709904edd9608b86f4fa089ad2
+github.com/libp2p/go-libp2p-transport-upgrader,v0.1.1,h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw=,60ea73fa42536178798c3d4a36c5f9cffb185b6c1629c23c3faff5919f9e9cad
+github.com/libp2p/go-libp2p-yamux,v0.2.1,h1:Q3XYNiKCC2vIxrvUJL+Jg1kiyeEaIDNKLjgEjo3VQdI=,849f0097fd7203b5c6d590463b7fb17573af8d12136413768706188a39b34b21
+github.com/libp2p/go-maddr-filter,v0.0.5,h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg=,19c76e021879aab85a8858b53d706220e9e3277a96dead161db152f5a1d17219
+github.com/libp2p/go-mplex,v0.1.0,h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0=,3340a423ea89310360810973a77a97c217fe7b35e1c18189a3628e35fe1275e0
+github.com/libp2p/go-msgio,v0.0.4,h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA=,ec22f703203a2a443c57896b2082c02fe9c54d372aad091cdca144709d244721
+github.com/libp2p/go-nat,v0.0.3,h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI=,d642c9dd697176ec69c4a5faeff1fc3b5472ef9f32c2c40e21c42f81ceef86b9
+github.com/libp2p/go-openssl,v0.0.3,h1:wjlG7HvQkt4Fq4cfH33Ivpwp0omaElYEi9z26qaIkIk=,f2eb05d710fe960ba12d5f640cefe7d31d24f1fab0d9a52faf5f2923a19c6f13
+github.com/libp2p/go-reuseport,v0.0.1,h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw=,274ade934c7f26ffae86d3f4d34352371c3eca7ead080392f6f35698ec5f0a3f
+github.com/libp2p/go-reuseport-transport,v0.0.2,h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4=,866f45bfa6c2e65d563955a28050bcfbc6ed11df6ded7c551e92ff98ba98a2d8
+github.com/libp2p/go-stream-muxer,v0.1.0,h1:3ToDXUzx8pDC6RfuOzGsUYP5roMDthbUKRdMRRhqAqY=,d42dab9fb102b3e56cc555eb9aacb742e4230120dd356078cc723f8817200d43
+github.com/libp2p/go-stream-muxer-multistream,v0.2.0,h1:714bRJ4Zy9mdhyTLJ+ZKiROmAFwUHpeRidG+q7LTQOg=,a4ca5d0422d55ee7b4e74b040ca85799365b05684b7b6687adfa79a345049a9d
+github.com/libp2p/go-tcp-transport,v0.1.1,h1:yGlqURmqgNA2fvzjSgZNlHcsd/IulAnKM8Ncu+vlqnw=,147dc8d50aab944666c1a7a371ba3e351480506313be298ebf8dcdb9dc51b1b4
+github.com/libp2p/go-testutil,v0.1.0,h1:4QhjaWGO89udplblLVpgGDOQjzFlRavZOjuEnz2rLMc=,9fa6fa5741f541a6309e8a5fa6031c51f97fcd3086fe3a3b371b74f9d8e9a4b8
+github.com/libp2p/go-ws-transport,v0.1.0,h1:F+0OvvdmPTDsVc4AjPHjV7L7Pk1B7D5QwtDcKE2oag4=,30cfd8011bb8de03c23680d2249120ea9ba29879e855ca5c35311f8fa874d094
+github.com/libp2p/go-yamux,v1.2.3,h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI=,97947a07c9430184c3be45e87580abcdea18c9b7435adb8048b08aebce0fea50
+github.com/liggitt/tabwriter,v0.0.0-20181228230101-89fcab3d43de,h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=,41b6869255915ffdfd32575ba14d52732d62d34b47d904df4890e165489ec77d
+github.com/linkedin/goavro,v2.1.0+incompatible,h1:DV2aUlj2xZiuxQyvag8Dy7zjY69ENjS66bWkSfdpddY=,25d4ccde4ece770196fbf6f09ca4184df581944224be5d64a263eb2c7f9a24fc
+github.com/linode/linodego,v0.10.0,h1:AMdb82HVgY8o3mjBXJcUv9B+fnJjfDMn2rNRGbX+jvM=,4c4e8829c0290c473e36bacdce8b490833d1f6247b1a4290062db30ba2b21568
+github.com/liquidweb/liquidweb-go,v1.6.0,h1:vIj1I/Wf97fUnyirD+bi6Y63c0GiXk9nKI1+sFFl3G0=,19e08fe2aa62655eb3cb209b37d532a267dd3078e5d262c4c45e7e09134b079c
+github.com/lithammer/dedent,v1.1.0,h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=,4ec56a3fef0d7dd1536046e540827e60419a935dde49d87d21f5856174cadba2
+github.com/logrusorgru/aurora,v0.0.0-20180419164547-d694e6f975a9,h1:KQdwUNlTDGyS6e+2rjAxfHSpBFIOHXqgDceNDqb55+4=,3b9d5caeede8553ead48405de57cd25bf6276b12531dae582c3ee089474aaf95
+github.com/loov/hrtime,v0.0.0-20181214195526-37a208e8344e,h1:UC+nLCm+w3WL+ibAW/wsWbQC3KAz7LLawR2hgX0eR9s=,f077796a9f39c579d356ac8f99831c56b3b2c52b70526f97730eccdc5ce558b2
+github.com/loov/plot,v0.0.0-20180510142208-e59891ae1271,h1:51ToN6N0TDtCruf681gufYuEhO9qFHQzM3RFTS/n6XE=,eb57dc24113d92cda1d0eecd6280603a2f1a98eececde895db4b060a7208659a
+github.com/lovoo/gcloud-opentracing,v0.3.0,h1:nAeKG70rIsog0TelcEtt6KU0Y1s5qXtsDLnHp0urPLU=,7bead4937d23976e07caf4bf7a7f302724cda9155aa8ac4de7baa2e10976eacc
+github.com/lsegal/gucumber,v0.0.0-20180127021336-7d5c79e832a2,h1:Gg0dt1q5bB+3R3qu+BucR+1f5ZhKm3OzPPo53dZ3Hxs=,2e5cd235f8c80ae078b3115b41fb765682c796d62fa54ecbb2096b159b0294bd
+github.com/lucas-clemente/aes12,v0.0.0-20171027163421-cd47fb39b79f,h1:sSeNEkJrs+0F9TUau0CgWTTNEwF23HST3Eq0A+QIx+A=,074a3c40044c8f07dbe93129fe30bfd4a12f6283f393e7300664d59924a8af2b
+github.com/lucas-clemente/quic-clients,v0.1.0,h1:/P9n0nICT/GnQJkZovtBqridjxU0ao34m7DpMts79qY=,b916edbd87d45fd375b0f81f905453102eb4e7e724ca0fc8ac5be323fe5958b8
+github.com/lucas-clemente/quic-go,v0.12.1,h1:BPITli+6KnKogtTxBk2aS4okr5dUHz2LtIDAP1b8UL4=,144443ffb6231cabbe6da1496c5851eb73f03fff33d7bd94aa394f8d1e3c73b3
+github.com/lucas-clemente/quic-go-certificates,v0.0.0-20160823095156-d2f86524cced,h1:zqEC1GJZFbGZA0tRyNZqRjep92K5fujFtFsu5ZW7Aug=,d9eff929a62711fc36f9655008e144863cd816ad2b59d25eb00a248c96178ce5
+github.com/lucasb-eyer/go-colorful,v1.0.2,h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=,c0e388db91f217be87f8d508ac9f495adc5a33ffda78849e2d0a89a8e8dae28c
+github.com/lunixbochs/struc,v0.0.0-20190916212049-a5c72983bc42,h1:PzBD7QuxXSgSu61TKXxRwVGzWO5d9QZ0HxFFpndZMCg=,8a7db31161ec3a3bcc7b52e25975d0299b9c0bb465f076014d303f112b5cb9e1
+github.com/lunixbochs/vtclean,v1.0.0,h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8=,4d73f9678abde21c67dd8cb4ed8d7f63bcdd9413b6093b53cec4d26ce1be5b88
+github.com/lunny/dingtalk_webhook,v0.0.0-20171025031554-e3534c89ef96,h1:uNwtsDp7ci48vBTTxDuwcoTXz4lwtDTe7TjCQ0noaWY=,b94d4c7cacca0c289b3fbbeae6cc9e66f2eec4a3210fbbfd208316337ff2f1e3
+github.com/lunny/levelqueue,v0.0.0-20190217115915-02b525a4418e,h1:GSprKUrG9wNgwQgROvjPGXmcZrg4OLslOuZGB0uJjx8=,8f62ece23811c3c2be0d1c8d10057ab564641b2f73dc5a9910dd5f8462954f19
+github.com/lunny/log,v0.0.0-20160921050905-7887c61bf0de,h1:nyxwRdWHAVxpFcDThedEgQ07DbcRc5xgNObtbTp76fk=,0d551b83dcb0c4a3e0f97febf74e8f69b58a419791e217a7d2fd3d79a1e5877b
+github.com/lunny/nodb,v0.0.0-20160621015157-fc1ef06ad4af,h1:UaWHNBdukWrSG3DRvHFR/hyfg681fceqQDYVTBncKfQ=,a0f6632294f1eec60e2651fa2d4b3590f3a1a8e2f7692dcc77251b945906a701
+github.com/lusis/go-artifactory,v0.0.0-20160115162124-7e4ce345df82,h1:wnfcqULT+N2seWf6y4yHzmi7GD2kNx4Ute0qArktD48=,487d2ef1720bd49c5a36efc8893fdb0a76bd5f8b064c2a98974a78b3e35f5763
+github.com/lusis/go-slackbot,v0.0.0-20180109053408-401027ccfef5,h1:AsEBgzv3DhuYHI/GiQh2HxvTP71HCCE9E/tzGUzGdtU=,0bb7feaeb5a4e83486234c1c8fbe2f73b94213f511aaf6b8ef1f0fc96dd7b4fa
+github.com/lusis/outputter,v0.0.0-20171130132426-5a3b464a163f,h1:JY0YSH+YvMGmq83g5qILMAkJDFv7qIiHalhlQXal9V0=,e3b54ad36707730681b10a3838d89c346bf2d2c52cb61a241b178bcb0fc96e0f
+github.com/lusis/slack-test,v0.0.0-20190426140909-c40012f20018,h1:MNApn+Z+fIT4NPZopPfCc1obT6aY3SVM6DOctz1A9ZU=,019aa5a65d7fc369730c089a8af985f8d4760297a0058dd0c352fb662e8a0cfc
+github.com/lyft/protoc-gen-star,v0.4.11,h1:zW6fJQBtCtVeSiO/Kbpzv32GO0J/Z8egSLeohES202w=,673c0c53ce301a5589d4aab2b389c6ab52c8312193bae9b491e75e4938475277
+github.com/lyft/protoc-gen-validate,v0.1.0,h1:NytKd9K7UW7Szxn+9PYNsaJ/98TL/WsDq4ro4ZVuh5o=,2e452d4298aa5f2be8d4eda3e55522a4c020d0f23dac6b33ecf9942be09bf082
+github.com/magefile/mage,v1.4.0,h1:RI7B1CgnPAuu2O9lWszwya61RLmfL0KCdo+QyyI/Bhk=,55862155e89367536d665080ac028decc98ce68c5651ccc4238d7e34ddf1cbc2
+github.com/magiconair/properties,v1.8.1,h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=,c0f0378f5949db2e7976d6822a0dfac1786acd34190e83ab253d6505542d0128
+github.com/mailgun/mailgun-go,v0.0.0-20171127222028-17e8bd11e87c,h1:5huPh/MfWW65cx8KWNVD4mCCnwIrNiX4bFJR5OeONg0=,33250edd00795e387f2de671003b8ef8f2d940d24b12a9ce90c6b49dd6094231
+github.com/mailgun/minheap,v0.0.0-20170619185613-3dbe6c6bf55f,h1:aOqSQstfwSx9+tcM/xiKTio3IVjs7ZL2vU8kI9bI6bM=,26930b2a6dc2f2b442e28ecc5dcbb22c2e7da3d151b3388d0bc604370bd9df77
+github.com/mailgun/multibuf,v0.0.0-20150714184110-565402cd71fb,h1:m2FGM8K2LC9Zyt/7zbQNn5Uvf/YV7vFWKtoMcC7hHU8=,7dbb280e8bc981732510ee72e124e931991d06c317531de709fd7922e38a5339
+github.com/mailgun/timetools,v0.0.0-20170619190023-f3a7b8ffff47,h1:jlyJPTyctWqANbaxi/nXRrxX4WeeAGMPaHPj9XlO0Rw=,a4d961cefbfbe858f4ba5a5824d91ad8713a736707f5c259cf0d7307a07ac83e
+github.com/mailgun/ttlmap,v0.0.0-20170619185759-c1c17f74874f,h1:ZZYhg16XocqSKPGNQAe0aeweNtFxuedbwwb4fSlg7h4=,35308e95ed02635049d1804b85f16407f3109fc60c38df541f0401dbba66dc8d
+github.com/mailru/easyjson,v0.7.0,h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=,c36c8ab36aab9ba2ca776d1c71cbd9c30fce7c4e8e62be6611f4c2d1e98e86ae
+github.com/manucorporat/sse,v0.0.0-20160126180136-ee05b128a739,h1:ykXz+pRRTibcSjG1yRhpdSHInF8yZY/mfn+Rz2Nd1rE=,cd90f350cca3a6536432afb4cd2355ff25124ef89fc23a52392e5189733b0359
+github.com/manveru/faker,v0.0.0-20171103152722-9fbc68a78c4d,h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ=,80bc3e8ca50e89d3a6139d1709fbf4680c26231079d297d237902d3c23f4c1e8
+github.com/manveru/gobdd,v0.0.0-20131210092515-f1a17fdd710b,h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4=,39811c3d6c7de66195a29a78b235dead57fb866e61082301fe68d51cf04a5200
+github.com/markbates/deplist,v1.3.0,h1:uPgoloPraPBPYtNSxj2UwZBh2EHW9TmMvQCP2FBiRlU=,e0b1903fb33c324721565076e2061d7f54e29ba098afb80af4fe2ccdd02ed178
+github.com/markbates/going,v1.0.3,h1:mY45T5TvW+Xz5A6jY7lf4+NLg9D8+iuStIHyR7M8qsE=,61efe687a56d3141284be7bdb83bb5ae86e1df694ababa5937c4d3e30f3b60f1
+github.com/markbates/goth,v1.49.0,h1:qQ4Ti4WaqAxNAggOC+4s5M85sMVfMJwQn/Xkp73wfgI=,39a0244d07f47d7b91215590900a7754c4700e875c0866b1e65568133471478a
+github.com/markbates/grift,v1.1.0,h1:DsljFKUSK1ELpU22ZE+Gi93jiQI3cYD/RQ+vHM/PpY8=,29aa2fa782f9d8730bde2df024c40ba749f1812dd3bbab489b4197a1faa78627
+github.com/markbates/hmax,v1.1.0,h1:MswE0ks4Iv1UAQNlvAyFpsyFQSBHolckas95gRUkka4=,8c7557798a88c74594f27137be859e99195427e2e04f0835f48781b0bde5c73a
+github.com/markbates/inflect,v1.0.4,h1:5fh1gzTFhfae06u3hzHYO9xe3l3v3nW5Pwt3naLTP5g=,0da6e75f6cd27672255a41f5dfab418d2746897239ad601e5d8d78d6354b5665
+github.com/markbates/oncer,v1.0.0,h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY=,9a774885bfa4c9a96c438fdb51768833e1c7003f35cd27961137ff4096b1a764
+github.com/markbates/refresh,v1.8.0,h1:ELMS9kKyO/H6cJrqFo6qCyE0cRx2JeHWC9yusDkVeM8=,7ac81390a898cfd1cdc097ffb1e05321c415183165b7341749de41160c47e504
+github.com/markbates/safe,v1.0.1,h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=,d5a98e8242318d4e88844ddbbfebe91f67f41e5aa1f6a96a58fa2fa94e0ae9ef
+github.com/markbates/sigtx,v1.0.0,h1:y/xtkBvNPRjD4KeEplf4w9rJVSc23/xl+jXYGowTwy0=,e3b591a1a2b4dcec7b86d59e504b0bbf87ec3663efad818cd9b00471a33a0345
+github.com/markbates/willie,v1.0.9,h1:394PpHImWjScL9X2VRCDXJAcc77sHsSr3w3sOnL/DVc=,a6c3eda44d765eeb1370b0ddeb739df86e900b78eb365688da143f1c0c0e9bc0
+github.com/marstr/guid,v1.1.0,h1:/M4H/1G4avsieL6BbUwCOBzulmoeKVP5ux/3mQNnbyI=,7db3cd8020c72ba260d1a20183bf5a030c696d6442eccaff2b31f72b194fc571
+github.com/marten-seemann/qpack,v0.1.0,h1:/0M7lkda/6mus9B8u34Asqm8ZhHAAt9Ho0vniNuVSVg=,46c42087e554edae4e19f79b785722d27316e23278889bf78a0c8f43fc387f2e
+github.com/marten-seemann/qtls,v0.3.2,h1:O7awy4bHEzSX/K3h+fZig3/Vo03s/RxlxgsAk9sYamI=,ff5245b3d5a1e65754d4a740e09ff02c738e9043c6e2bc02c59d5851c1fc1e2d
+github.com/martini-contrib/render,v0.0.0-20150707142108-ec18f8345a11,h1:YFh+sjyJTMQSYjKwM4dFKhJPJC/wfo98tPUc17HdoYw=,2edd7f64b2f1f053f86a51856cd0f02b1f762af61a458a2e282dab76ad093d70
+github.com/martinlindhe/unit,v0.0.0-20190604142932-3b6be53d49af,h1:4bEyeobv/dO+lT1Qp1hr+/DcNjy6Ob8BDaSrxX6nQsQ=,ee5001e908fb9997e5918c909dcb0cc078f1a91719f4df3d62243d5e88dc07c6
+github.com/martinusso/go-docs,v0.0.0-20161215163720-81905d575a58,h1:VmcrkkMjTdCGOsuuMnn7P2X9dGh3meUNASx6kHIpe7A=,70ad43a3172287882f904657184af77133a578c6d1ec968c5ce3e27259100a06
+github.com/maruel/panicparse,v0.0.0-20171209025017-c0182c169410,h1:1ROIrlLvFoHKX+i48KdRauq21irSOXPyfQw4T/PrINY=,5fd98b2b0a8346ffcba1858775e93db0582ead6b3329b974595d5ab448c95f28
+github.com/maruel/ut,v1.0.0,h1:Tg5f5waOijrohsOwnMlr1bZmv+wHEbuMEacNBE8kQ7k=,a7c90a5020071c66efe2ccae7f3859c60f17840d4ae2972ee9c9a38ae071fb3e
+github.com/masterzen/azure-sdk-for-go,v0.0.0-20161014135628-ee4f0065d00c,h1:FMUOnVGy8nWk1cvlMCAoftRItQGMxI0vzJ3dQjeZTCE=,de40198aee773ecaf502d59b8f29fe5d1564fb9a68900b6bfed2369e169e193a
+github.com/masterzen/simplexml,v0.0.0-20190410153822-31eea3082786,h1:2ZKn+w/BJeL43sCxI2jhPLRv73oVVOjEKZjKkflyqxg=,a9e4548a5c7e098c89273c470e4e9d18cb0beb530629f2e512f6f105fd9cbc88
+github.com/masterzen/winrm,v0.0.0-20190223112901-5e5c9a7fe54b,h1:/1RFh2SLCJ+tEnT73+Fh5R2AO89sQqs8ba7o+hx1G0Y=,28f8e69baadf7f220842a5cd4269ccebdb175a835c0b43819a6b15670ae5403c
+github.com/matryer/moq,v0.0.0-20190312154309-6cfb0558e1bd,h1:HvFwW+cm9bCbZ/+vuGNq7CRWXql8c0y8nGeYpqmpvmk=,b9fb2bc3d0894dfaa3cc4298f49c97346ccb66f2f0e6911f4f224ffc9acc3972
+github.com/matryer/try,v0.0.0-20161228173917-9ac251b645a2,h1:JAEbJn3j/FrhdWA9jW8B5ajsLIjeuEHLi8xE4fk997o=,f1afa36a4bd0bf09a1290f3afef954058e334d6b275aae6a591d8dad276f5e2f
+github.com/mattbaird/elastigo,v0.0.0-20170123220020-2fe47fd29e4b,h1:v29yPGHhOqw7VHEnTeQFAth3SsBrmwc8JfuhNY0G34k=,f6a94deccbe4d008d265bb4b5cbaee7893e5994a82bc49b44438675a0ca8d8f3
+github.com/mattbaird/jsonpatch,v0.0.0-20171005235357-81af80346b1a,h1:+J2gw7Bw77w/fbK7wnNJJDKmw1IbWft2Ul5BzrG1Qm8=,55abaf4d26d8ad7f81c230f38a6e482b6b416d9b5777a6c3b1a5c140465a5235
+github.com/mattermost/mattermost-server,v5.11.1+incompatible,h1:LPzKY0+2Tic/ik67qIg6VrydRCgxNXZQXOeaiJ2rMBY=,1f601d79e647a248f9e711891e015b1709f3af37e6a45d5e97827f074c40398e
+github.com/mattn/go-colorable,v0.1.4,h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=,02ad42bc54adf7c52030b6ab903277af8fb7163aad4f7f8d8703ecfdc62597de
+github.com/mattn/go-ieproxy,v0.0.0-20190805055040-f9202b1cfdeb,h1:hXqqXzQtJbENrsb+rsIqkVqcg4FUJL0SQFGw08Dgivw=,5914c18852b0be63008f7ccaf1bd3a8214a82fae78f8afe2e7d774ff96a410ff
+github.com/mattn/go-isatty,v0.0.10,h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=,dca893515dccb58e21f9b08837470c5512e0ecd1275767ed996912bb46933c91
+github.com/mattn/go-mastodon,v0.0.5-0.20190517015615-8f6192e26b66,h1:TbnaLJhq+sFuqZ1wxdfF5Uk7A2J41iOobCCFnLI+RPE=,b290b77b6e5556bba70cf18ac815c13ed9a80ffa4cb03627d73187e99cd15d42
+github.com/mattn/go-oci8,v0.0.0-20190320171441-14ba190cf52d,h1:m+dSK37rFf2fqppZhg15yI2IwC9BtucBiRwSDm9VL8g=,eb3bd1fa93c8a341ad43176cb6e4d8540d7a91d3edd7eb98c1388cf2f4c3515c
+github.com/mattn/go-runewidth,v0.0.5,h1:jrGtp51JOKTWgvLFzfG6OtZOJcK2sEnzc/U+zw7TtbA=,3b34033634b059bfa31ac552d2150d8c0d6e530dd1c0ead2ce0806e1d7cc754a
+github.com/mattn/go-shellwords,v1.0.6,h1:9Jok5pILi5S1MnDirGVTufYGtksUs/V2BWUP3ZkeUUI=,374285b205f0659ab4be3f8ce346cfd3291cd42f47b12bda15174c42c462b1a6
+github.com/mattn/go-sqlite3,v1.11.0,h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=,7fec79c50206f5faa759d1b64500fb0d082e22ef23f10e2d4cbce24e4fc2d5c1
+github.com/mattn/go-tty,v0.0.0-20190424173100-523744f04859,h1:smQbSzmT3EHl4EUwtFwFGmGIpiYgIiiPeVv1uguIQEE=,76f28f59927667d2d750fa6ffdefeb3f0c41034cb593e4545a206995c76c619f
+github.com/mattn/go-xmpp,v0.0.0-20190124093244-6093f50721ed,h1:A1hEQg5M0b3Wg06pm3q/B0wdZsPjVQ/a2IgauQ8wCZo=,2c39b78184ea27890be56f593353c8fe6b3d6efa53db20e800ff8793bc665199
+github.com/mattn/go-zglob,v0.0.1,h1:xsEx/XUoVlI6yXjqBK062zYhRTZltCNmYPx6v+8DNaY=,8decd6c1916188ab4fa1001e3da3f22d7c9fb6218215fd25053c901979930feb
+github.com/mattn/goveralls,v0.0.2,h1:7eJB6EqsPhRVxvwEXGnqdO2sJI0PTsrWoTMXEk9/OQc=,3df5b7ebfb61edd9a098895aae7009a927a2fe91f73f38f48467a7b9e6c006f7
+github.com/matttproud/golang_protobuf_extensions,v1.0.1,h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=,e64dc58023f4b8c4472d05a44f2719b84d6c2cc364cc682820c9f72b233c9cdc
+github.com/maxbrunsfeld/counterfeiter/v6,v6.2.2,h1:g+4J5sZg6osfvEfkRZxJ1em0VT95/UOZgi/l7zi1/oE=,c185793a7e749ff2557f4557628f5b5d8d9edbf72ca6bd2cb94503f4817c01d2
+github.com/mcuadros/go-version,v0.0.0-20190830083331-035f6764e8d2,h1:YocNLcTBdEdvY3iDK6jfWXvEaM5OCKkjxPKoJRdB3Gg=,ff2364bda8605ad94051c576ffa601e1a9aedabc8a1fda588eb04c3371a845ea
+github.com/mdlayher/dhcp6,v0.0.0-20190311162359-2a67805d7d0b,h1:r12blE3QRYlW1WBiBEe007O6NrTb/P54OjR5d4WLEGk=,fba7b2f01311e2d41bb4ebe15409d4e0a605a79d2f05156bb0f4adbc20f557bc
+github.com/mdlayher/netlink,v0.0.0-20191009155606-de872b0d824b,h1:W3er9pI7mt2gOqOWzwvx20iJ8Akiqz1mUMTxU6wdvl8=,9be201b393fe866f855e5ebb20ef33e86a0e6a99b6b76209531b93615fcbac7c
+github.com/mesos/mesos-go,v0.0.10,h1:+M/7Zlkvw4MolkLvXHfj6hkDsLLHOOU54CmOkOUaNBc=,f18d5601dc6a5234b9c2d65cb96b8d30ab877e3117dd52dd47e31a353ed887d1
+github.com/mgutz/ansi,v0.0.0-20170206155736-9520e82c474b,h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=,d7c0ff88c53dfca384bb82108a6e5fdc9e11b358d68b67144ff6a285be20a16a
+github.com/mgutz/logxi,v0.0.0-20161027140823-aebf8a7d67ab,h1:n8cgpHzJ5+EDyDri2s/GC7a9+qK3/YEGnBsd0uS/8PY=,0a7837d5246591fe1fd341e48a72786c0b61fff8d3ebfea0e9c789176c3e75d5
+github.com/mgutz/str,v1.2.0,h1:4IzWSdIz9qPQWLfKZ0rJcV0jcUDpxvP4JVZ4GXQyvSw=,bf640c2048957f183e72664ff08745ae3d016f64072a5967f5269ccb5fc4b318
+github.com/mholt/archiver,v3.1.1+incompatible,h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=,6cbad83ecd8a2bcb013fb1ac163a6551e6f948b103df9b258788612c72551184
+github.com/mholt/certmagic,v0.7.5,h1:1ZGHwUI4+zg1S17tPUj5Xxb9Q1ghTjLcUZE5G4yV5SM=,a85c14ecbb135636c8e4701a25b8d2884f091d948269c0a3187918af83e11db3
+github.com/michaelklishin/rabbit-hole,v1.5.0,h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM=,1fdb62e985c4b1be24632875668720ed687455ece54cb2c77079488784e06e69
+github.com/micro-plat/gmq,v1.0.1,h1:ai1PiCEfgBmiqzmZ4iWE3l2Vuz7rOTWOakqRWqi/Hgo=,63c4a02b87b31c0f5cfcdfee5df2fa05e77eeaa2aab93b0ef217c57f6b37b38a
+github.com/micro-plat/lib4go,v0.2.1,h1:NBTIq0DvpRzTChnYShBagPmsYM4k1NgvkE8OYhgMDt8=,ae1056cc76eee3fccb14b0d8723b6444d8f31d2575a0caa1d3723bc54b91496b
+github.com/micro/cli,v0.2.0,h1:ut3rV5JWqZjsXIa2MvGF+qMUP8DAUTvHX9Br5gO4afA=,09e532e4616aa7827d1a1f249bc80ebb01fe8c63978f4b14605246c6be596b82
+github.com/micro/go-log,v0.1.0,h1:szYSR+yyTsomZM2jyinJC5562DlqffSjHmTZFaeZ2vY=,5ec9ba1cfb781edd3695dc9c28afb520cced5e1cf7eabb5faafd4bd8db6953ea
+github.com/micro/go-micro,v1.14.0,h1:lptn9DBbsNCB3RC3PMwxTJGqCUgU8Rf23nAMaRuOcOA=,2278cfa86f7bf97df81ea79535127cf87bf03aba29e7603f2feeb48b2d1a3334
+github.com/micro/go-rcache,v0.2.0,h1:g51QJW+lj+dAOXwRlYNZPQQ8ueHLptgoUzZE3iRwJMg=,fa96add40dac8fb14cf08f7a8c96d05c902da40b27b2c4e586cf3304e4ef6533
+github.com/micro/h2c,v1.0.0,h1:ejw6MS5+WaUoMHRtqkVCCrrVzLMzOFEH52rEyd8Fl2I=,6fea0303cbaa2bc6c45098ce5ad0ae2aa7f9c54ce2ff90160549756f8c7a2b07
+github.com/micro/mdns,v0.3.0,h1:bYycYe+98AXR3s8Nq5qvt6C573uFTDPIYzJemWON0QE=,a40ecbd32a2170698f0f49f8961b39e88e7c3e958546a401a59653231b51f1b2
+github.com/micro/micro,v1.14.0,h1:Uol1+Yg5frzneACpzoHEDsyNTN+/+yLrlGMuxR3RVRQ=,0fd330788ad610cc2cb3eb2224f1ca403d9888ad40e78628f250c885373d739c
+github.com/micro/util,v0.2.0,h1:6u0cPj1TeixEk5cAR9jbcVRUWDQsmCaZvDBiM3zFZuA=,3e61d5232a3a91d521ade483ab64b53a7b8760d0635978d72b4920eba52f8f79
+github.com/microcosm-cc/bluemonday,v1.0.2,h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s=,9cfac37098da75ab1c278740e8f0f7741891d8843e14afb256574596ad786f83
+github.com/miekg/dns,v1.1.22,h1:Jm64b3bO9kP43ddLjL2EY3Io6bmy1qGb9Xxz6TqS6rc=,54f1f62de314150df163bbe1de91acc922cdce70c5c8a43dfeb7f4af24711d38
+github.com/miekg/mmark,v1.3.6,h1:t47x5vThdwgLJzofNsbsAl7gmIiJ7kbDQN5BxwBmwvY=,8d1b05ee1c0a28093c678af2ed9d0aac9dfc30dce728ccd21fe1506762b54cee
+github.com/mindprince/gonvml,v0.0.0-20190828220739-9ebdce4bb989,h1:PS1dLCGtD8bb9RPKJrc8bS7qHL6JnW1CZvwzH9dPoUs=,6702f94187c4e2994ffbdc318c94a04d4bc67081a402e968a2c362a74c81263f
+github.com/minio/blake2b-simd,v0.0.0-20160723061019-3f5f724cb5b1,h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=,ab10edfe994b513e2d03cdd8122b352f31a1eb246fe884617b3f2f6195a3ca0c
+github.com/minio/cli,v1.22.0,h1:VTQm7lmXm3quxO917X3p+el1l0Ca5X3S4PM2ruUYO68=,33533a4e0a2b1a698d0f899cb5b84d9fc199e7723b971d1408e4b5ee797c9a50
+github.com/minio/dsync,v0.0.0-20180124070302-439a0961af70,h1:pRHQdPOlUhelWqNUF3icFrBSC6VYH1hvF6HigVfgMoI=,850e5b400afc4301a1860debf934c5e8e67565d4937ac45f9a37132b31a09941
+github.com/minio/highwayhash,v0.0.0-20180501080913-85fc8a2dacad,h1:L+8skVz2lusCbtlalLXmJp+TK8XaGAsZ3utSC3k5Jc0=,7393dfe736668f9ab98fcf2d264f9bd20bbf4f98538f02ff15df9604f747cdb1
+github.com/minio/lsync,v0.0.0-20180328070428-f332c3883f63,h1:utJHim4C0K4CmD+Qgod/tgHvo7QNOlH6HN5O8QUvPEI=,417c4bdd4fc5d50da2d81e8890b03af4b80ce9fbd5e4c196731a3d76a09913c1
+github.com/minio/mc,v0.0.0-20180926130011-a215fbb71884,h1:co3kRW9cEI65yolYtcLcNxp2a9yk5T/eEt7gw14tJVs=,37300de5179e1085559c6f317b331d261cc4508ba0e4febbd93cbbfef42d7fc9
+github.com/minio/minio,v0.0.0-20180508161510-54cd29b51c38,h1:F7p0ZU9AQuxlA6SWwhXr0H/rYrA9fOiBk2OzOj7GtfM=,6421e5cf72b35a2948e5edd2b189f37ad1896b8637d5b9bcf7cd40b7ab63dfd4
+github.com/minio/minio-go,v6.0.14+incompatible,h1:fnV+GD28LeqdN6vT2XdGKW8Qe/IfjJDswNVuni6km9o=,3bc396d5e1c0c6f3497743140eaf16ebb97c5f1ca815ba12c4f431e804fb737d
+github.com/minio/minio-go/v6,v6.0.27-0.20190529152532-de69c0e465ed,h1:g3DRJpu22jEjs14fSeJ7Crn9vdreiRsn4RtrEsXH/6A=,34d85b6b915ef5876f9c262f260583fabec147c37dcb82e1f42374dd088b9096
+github.com/minio/sha256-simd,v0.1.1,h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=,0ecfa6532265e139d5d9406c0a803c7ef45b1d8d0f0c1b1d55f7b81969294bfc
+github.com/minio/sio,v0.0.0-20180327104954-6a41828a60f0,h1:ys4bbOlPvaUBlA0byjm6TqydsXZu614ZIUTfF+4MRY0=,6c46bc4a68353d7b41f6e91eb276c9b21560cad4f75419baaee01764927fb7e8
+github.com/mistifyio/go-zfs,v2.1.1+incompatible,h1:gAMO1HM9xBRONLHHYnu5iFsOJUiJdNZo6oqSENd4eW8=,545764e34ed40473380ea1b08af9f0aea1715d15a0a56fc937e6c3b1bda0d9a3
+github.com/mitchellh/cli,v1.0.0,h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y=,74199f2c2e1735a45e9f5c2ca049d352b0cc73d945823540e54ca9975ce35752
+github.com/mitchellh/colorstring,v0.0.0-20190213212951-d06e56a500db,h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=,d0733284b20567055e374b420373f5508fa47e95204e59e4b8a66834e7e3964d
+github.com/mitchellh/copystructure,v1.0.0,h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=,4a2c9eb367a7781864e8edbd3b11781897766bcf6120f77a717d54a575392eee
+github.com/mitchellh/go-fs,v0.0.0-20180402234041-7b48fa161ea7,h1:PXPMDtfqV+rZJshQHOiwUFqlqErXaAcuWy+/ZmyRfNc=,21c34fee3df3dc1ddad5e774ddf9e05998061177420709fb68a958c6c113a90b
+github.com/mitchellh/go-homedir,v1.1.0,h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=,fffec361fc7e776bb71433560c285ee2982d2c140b8f5bfba0db6033c0ade184
+github.com/mitchellh/go-linereader,v0.0.0-20190213213312-1b945b3263eb,h1:GRiLv4rgyqjqzxbhJke65IYUf4NCOOvrPOJbV/sPxkM=,7b83ef857c71fe8d4937b57923923176dd43c7b1b7632a9779bac411924e87e1
+github.com/mitchellh/go-ps,v0.0.0-20190716172923-621e5597135b,h1:9+ke9YJ9KGWw5ANXK6ozjoK47uI3uNbXv4YVINBnGm8=,06090b6c22dedf800259eb5d9b5f35bfb7b38e22888c0345631dc54366b21f89
+github.com/mitchellh/go-testing-interface,v1.0.0,h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=,255871a399420cd3513b12f50738d290e251637deb23e21a4332192584ecf9c7
+github.com/mitchellh/go-vnc,v0.0.0-20150629162542-723ed9867aed,h1:FI2NIv6fpef6BQl2u3IZX/Cj20tfypRF4yd+uaHOMtI=,2d65ac584e1a17421265fe97f83bd1cbff447ca6a911fa8d91414fa2115e3e74
+github.com/mitchellh/go-wordwrap,v1.0.0,h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=,9ea185f97dfe616da351b63b229a5a212b14ac0e23bd3f943e39590eadb38031
+github.com/mitchellh/gox,v1.0.1,h1:x0jD3dcHk9a9xPSDN6YEL4xL6Qz0dvNYm8yZqui5chI=,30a69e17ba5cafe6f1ac436bcc99368a5a34f0a0763926d2c6780a781f8e9e95
+github.com/mitchellh/hashstructure,v1.0.0,h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y=,3b79b07860631d05645ea3f54830b7e1997dbcf477e84a8adfe4979be3abdfde
+github.com/mitchellh/iochan,v1.0.0,h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY=,f3eede01adb24c22945bf71b4f84ae25e3744a12b9d8bd7c016705adc0d778b8
+github.com/mitchellh/mapstructure,v1.1.2,h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=,cd86d8586cbc333de28f6a46989069487877fae437df4c2cc417668d203c7305
+github.com/mitchellh/panicwrap,v0.0.0-20190213213626-17011010aaa4,h1:jw9tsdJ1FQmUkyTXdIF/nByTX+mMnnp16glnvGZMsC4=,b9ab07bbacf733cc24f9f7f53eec19f9bf999cbb35180ad0b615fe437640de6e
+github.com/mitchellh/pointerstructure,v0.0.0-20190430161007-f252a8fd71c8,h1:1CO5wil3HuiVLrUQ2ovSTO+6AfNOA5EMkHHVyHE9IwA=,658a3e14e4983f3c8a04c8da4a56d4d8a86e2b4fcaa6b1eefab150efcd742848
+github.com/mitchellh/prefixedio,v0.0.0-20190213213902-5733675afd51,h1:eD92Am0Qf3rqhsOeA1zwBHSfRkoHrt4o6uORamdmJP8=,d3209d88b3b5b05ecd48f469bc16811666f786685c49273664a5496d5dd69018
+github.com/mitchellh/reflectwalk,v1.0.1,h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=,bf1d4540bf05ea244e65fca3e9f859d8129c381adaeebe7f22703959aadc4210
+github.com/mjibson/esc,v0.2.0,h1:k96hdaR9Z+nMcnDwNrOvhdBqtjyMrbVyxLpsRCdP2mA=,9f090786bd43dddb5c0d798b449d5e8aede4cb7d106f56dcac0aebd8fd1929cc
+github.com/mndrix/ps,v0.0.0-20131111202200-33ddf69629c1,h1:kCroTjOY+wyp+iHA2lZOV5aJ6WfBVjGnW8bCYmXmLPo=,30b12b7a2467d4a1aa64aa31c715cb45d570d36e31ae70719101d686363d2685
+github.com/mndrix/tap-go,v0.0.0-20171203230836-629fa407e90b,h1:Ga1nclDSe8gOw37MVLMhfu2QKWtD6gvtQ298zsKVh8g=,c6f65bd8d977e53fa083d9d0309cffb0dbfaaae69a5a64a352fb2f7d079ce73d
+github.com/modern-go/concurrent,v0.0.0-20180306012644-bacd9c7ef1dd,h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=,91ef49599bec459869d94ff3dec128871ab66bd2dfa61041f1e1169f9b4a8073
+github.com/modern-go/reflect2,v1.0.1,h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=,6af8268206d037428a4197bd421bbe5399c19450ef53ae8309a083f34fb7ac05
+github.com/mohae/deepcopy,v0.0.0-20170929034955-c48cc78d4826,h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=,41ba726508a213f4af89e7d58937263ff778e352d591edd422d3a3dc3272585c
+github.com/mongodb/grip,v0.0.0-20191008181606-ee248dc03622,h1:pPoJByX3B56ydhWGUMard1QQ2skLNTw/s1W5VuLLAtA=,08fcfea928382f428dc1fceeada1c264e7f6dc7256dbe05c5c0ba41dca16a42c
+github.com/monoculum/formam,v0.0.0-20190830100315-7ff9597b1407,h1:ZU5O9BawmEx9Mu1lxn9NLIwO9DrqRfjE+HWKU+e9GKQ=,5a04e3907fb1008c1e6640e8a0e9394c752aab4ebf7e3be01cd3ee55c2659121
+github.com/montanaflynn/stats,v0.5.0,h1:2EkzeTSqBB4V4bJwWrt5gIIrZmpJBcoIRGS2kWLgzmk=,05527945351f54f4e8c48666bce277fbace34026eed22ac7d88a50a6730767f1
+github.com/morikuni/aec,v1.0.0,h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=,c14eeff6945b854edd8b91a83ac760fbd95068f33dc17d102c18f2e8e86bcced
+github.com/moul/anonuuid,v0.0.0-20160222162117-609b752a95ef,h1:E/seV1Rtsnr2juBw1Dfz4iDPT3/5s1H/BATx+ePmSyo=,ec103e75b93231b5b858a2fc9985da39d6b7c35644a689a20e60f3a6ad6b1396
+github.com/moul/gotty-client,v0.0.0-20180327180212-b26a57ebc215,h1:y6FZWUBBt1iPmJyGbGza3ncvVBMKzgd32oFChRZR7Do=,265c4cbad4789e267f283b9012ad174c89e378e59ad9c64ac28729402eb60afe
+github.com/moul/http2curl,v0.0.0-20161031194548-4e24498b31db,h1:eZgFHVkk9uOTaOQLC6tgjkzdp7Ays8eEVecBcfHZlJQ=,2ff4e19b14d84f6d181afc79f28668c6171d6dea79c43a1918c0428a265137c1
+github.com/mozilla-services/heka,v0.10.0,h1:w+y6RPJkU6ZKeNbG1VvK9aSqJm0sru5TYcwOj6ejv8U=,f325891304f9acc654944d9a2297b8816a0a86440b2f035c4996ec38fcfa0eed
+github.com/mozillazg/go-cos,v0.12.0,h1:b9hUd5HjrDe10BUfkyiLYI1+z4M2kAgKasktszx9pO4=,5376eaf13e10fed6d73b713fbabc4a159d204239579120c410ea74de33dd6d71
+github.com/mozillazg/go-httpheader,v0.2.1,h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ=,50b7a36360fc1ec1a85fd40fe45f8db02fc734fc2af0514a60a068f0a2708122
+github.com/mozillazg/go-unidecode,v0.1.1,h1:uiRy1s4TUqLbcROUrnCN/V85Jlli2AmDF6EeAXOeMHE=,812d3bc9f03cb6a8552bfadd9e0d1b44a57807a3af2e8667a42861510bb2b20c
+github.com/mpvl/unique,v0.0.0-20150818121801-cbe035fff7de,h1:D5x39vF5KCwKQaw+OC9ZPiLVHXz3UFw2+psEX+gYcto=,af2bcc8a61a6881e0703afee2217dd1e75c8b34f4e49947c0d7f6e87af574e0e
+github.com/mr-tron/base58,v1.1.2,h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78=,c2b362db55d8266ce02a161b7f73cad646432d2dae98511385b88481380c4e86
+github.com/mreiferson/go-httpclient,v0.0.0-20160630210159-31f0106b4474,h1:oKIteTqeSpenyTrOVj5zkiyCaflLa8B+CD0324otT+o=,e94cbe43c052831323c59ff186c830ea2e271065f7f8b2794ade7aaf88a37a85
+github.com/mrjones/oauth,v0.0.0-20180629183705-f4e24b6d100c,h1:3wkDRdxK92dF+c1ke2dtj7ZzemFWBHB9plnJOtlwdFA=,4c1fef02b34241008ba6bc33fb5d01b4cfb3b7e7544fb7f70823fe74b9b21362
+github.com/mrunalp/fileutils,v0.0.0-20171103030105-7d4729fb3618,h1:7InQ7/zrOh6SlFjaXFubv0xX0HsuC9qJsdqm7bNQpYM=,c32d691ce15012ba21fbe69db3558df0c97326426c14ef747b8a1e02652ca7b3
+github.com/mschoch/smat,v0.0.0-20160514031455-90eadee771ae,h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY=,488e193897c7d8e3b3758cbeb8a5bc1b58b9619f3f14288a2ea9e0baa5ed9b3e
+github.com/msteinert/pam,v0.0.0-20151204160544-02ccfbfaf0cc,h1:z1PgdCCmYYVL0BoJTUgmAq1p7ca8fzYIPsNyfsN3xAU=,315d911c41d88a22bf8831b174bbd15310bc403626507095f98b9780ddcf9174
+github.com/muesli/smartcrop,v0.0.0-20180228075044-f6ebaa786a12,h1:l0X/8IDy2UoK+oXcQFMRSIOcyuYb5iEPytPGplnM41Y=,5857e4d0ed238d8c6f8f41294b98771f1c21874a80ea5f2e75b4a49cbcf1d3e0
+github.com/multiformats/go-base32,v0.0.3,h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI=,658875e4980370db6180f99835b3a48158a697eef69e7c3eb86b0b4f5c1c19ed
+github.com/multiformats/go-multiaddr,v0.1.1,h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE=,ba4849fc68453c3e812e850f40e6d5acef671060ed79f203c2d179d395d20fc5
+github.com/multiformats/go-multiaddr-dns,v0.0.2,h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8=,219f855f485aa198d36305f2f43012a73bd40f15caa3e606324cee9f117e5b89
+github.com/multiformats/go-multiaddr-fmt,v0.1.0,h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=,d83537dc1f83185dfb60b190ea4b3c7b05c552a75ad7cfaddd0b987c00ff0cff
+github.com/multiformats/go-multiaddr-net,v0.1.1,h1:jFFKUuXTXv+3ARyHZi3XUqQO+YWMKgBdhEvuGRfnL6s=,241c47d621bcb9a40d33284f407a7fdf458cb3f87ef02db68735cc6b9002afed
+github.com/multiformats/go-multibase,v0.0.1,h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA=,ed39145efcf5e8c99deaa183071aed246239730f5781b291bad7de5d1fc12d81
+github.com/multiformats/go-multihash,v0.0.8,h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg=,44fae6e8771331f54f267d9440a9d520e7daeb91817ff61e26b8494099ae046a
+github.com/multiformats/go-multistream,v0.1.0,h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ=,f720be6e29845f0a41c1241a24f19c08adf762f9e7e972b4096416776c603b15
+github.com/munnerz/goautoneg,v0.0.0-20191010083416-a7dc8b61c822,h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=,3d7ce17916779890be02ea6b3dd6345c3c30c1df502ad9d8b5b9b310e636afd9
+github.com/mwitkow/go-conntrack,v0.0.0-20190716064945-2f068394615f,h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=,d6fc513490d5c73e3f64ede3cf18ba973a4f8ef4c39c9816cc6080e39c8c480a
+github.com/mwitkow/go-grpc-middleware,v1.0.0,h1:XraEe8LhUuB33YeV4NWfLh2KUZicskSZ2lMhVRnDvTQ=,074f46f92d7a0043c5b283f1af224123cc48e21f96b259e62f77b6da72240812
+github.com/mxk/go-flowrate,v0.0.0-20140419014527-cca7078d478f,h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=,bd0701ef9115469a661c07a3e9c2e572114126eb2d098b01eda34ebf62548492
+github.com/myesui/uuid,v1.0.0,h1:xCBmH4l5KuvLYc5L7AS7SZg9/jKdIFubM7OVoLqaQUI=,3055c4b167daeb9984ccd7c8eeba154e3d84afa6fdf06a3151280ef120d1633d
+github.com/myitcv/gobin,v0.0.8,h1:hQORun03Mlnm8yp/OgKX8UYSIVZQ8ebTWf3aahY1u+s=,015311e9db646cb9e5f63a0586c466c9eb5bc5f45661282644f8a5b549607e72
+github.com/myitcv/vbash,v0.0.2,h1:8R+91eSlfcgoRjEbnUgvbXYOmfh+p0+7i5klFOM5VMA=,08dcf62b94843e7fd115cd0605158d948fb361ca8c958db1958c5d2feef9c2d1
+github.com/namedotcom/go,v0.0.0-20180403034216-08470befbe04,h1:o6uBwrhM5C8Ll3MAAxrQxRHEu7FkapwTuI2WmL1rw4g=,0c6ea2c994e982c25e44ccba2ead1a9655cd2f253986eedb73253c30ad21b42f
+github.com/naoina/go-stringutil,v0.1.0,h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=,4cfea6f0ebfecb5e6297f8a6eee0e9ef9fe254883eb75dd6179133995a219c58
+github.com/naoina/toml,v0.1.1,h1:PT/lllxVVN0gzzSqSlHEmP8MJB4MY2U7STGxiouV4X8=,8e34d510563d9e8b3f2dbdf0927bf5108b669144bdbe2fda4fcb44e7e2e55268
+github.com/natefinch/lumberjack,v2.0.0+incompatible,h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=,1f6e7c9e0b915c45151d8780a8711426b19d16d04c9cf0e7995b29035d6b500f
+github.com/nats-io/gnatsd,v1.3.0,h1:+5d80klu3QaJgNbdavVBjWJP7cHd11U2CLnRTFM9ICI=,85fa90b3eaef17698734d398a9939b8bb94df1b9f35bc92c8d31cb7a349c1e97
+github.com/nats-io/go-nats,v1.6.0,h1:FznPwMfrVwGnSCh7JTXyJDRW0TIkD4Tr+M1LPJt9T70=,8c63be6f10479802a40c66c0999f724e492bcb9863d5517038c6472e585a76aa
+github.com/nats-io/go-nats-streaming,v0.4.2,h1:e7Fs4yxvFTs8N5xKFoJyw0sVW2heJwYvrUWfdf9VQlE=,62dd1d6ba18f3b7686766116e3beaaf9f62b89b58a6efb0b8f1ad04d3ddfb026
+github.com/nats-io/jwt,v0.3.0,h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo=,e131314c7cf6a714ec10ca3b6f95f8af6a41f5cdaf72a364f7c71b33e97314db
+github.com/nats-io/nats,v1.6.0,h1:U5b2apHOTZlUou+NGfCRWG4ZEeivbt2hpsZO4kHKIVU=,12cc70ed3477472d110d4b4bc109fbe20218e8199629669ad5f617c199fbf9d2
+github.com/nats-io/nats-server/v2,v2.1.0,h1:Yi0+ZhRPtPAGeIxFn5erIeJIV9wXA+JznfSxK621Fbk=,a5897b8f5302ae38894de2c240f31d33ab7b2f3d4e88a2c212fc9b31f2d4f444
+github.com/nats-io/nats-streaming-server,v0.12.2,h1:EpyLfUBZgwu5c0mdSSytQsapm615AyitPssq7jgafdw=,48605f61f74903ba1322f11aa17806b57f71cebf2557b7dd8620d4193abc868d
+github.com/nats-io/nats.go,v1.9.1,h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ=,34a735d158d70685faad1fc3153f08da0ddc21c0ae42f6a0cb09430d638364b2
+github.com/nats-io/nkeys,v0.1.0,h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4=,dbc82abacf752e532ffd67db230a97f52a5f92070b04b4028cb79534d2ab0ef6
+github.com/nats-io/nuid,v1.0.1,h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=,809d144fbd16f91651a433e28d2008d339e19dafc450c5995e2ed92f1c17c1f3
+github.com/nats-io/stan.go,v0.5.0,h1:ZaSPMb6jnDXsSlOACynJrUiB3Evleg3ZyyX+rnf3TlQ=,1dcb14e2ef8ad30dd1ee61a63b0a3bfbaa48e9c3d13f69458a149956a14bbab7
+github.com/nbio/st,v0.0.0-20140626010706-e9e8d9816f32,h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=,e6cd27bd360be27d0f7efd3c4c41c4e14e659e60086b0bc4f09fb09cfd02a50d
+github.com/ncw/swift,v1.0.49,h1:eQaKIjSt/PXLKfYgzg01nevmO+CMXfXGRhB1gOhDs7E=,b2be24cad8923c9171835547df2d621d2aa2029ceb9fa770d6ecf3bf70c2c029
+github.com/neelance/astrewrite,v0.0.0-20160511093645-99348263ae86,h1:D6paGObi5Wud7xg83MaEFyjxQB1W5bz5d0IFppr+ymk=,815811c2140669e55e99d59d4bdd2fcf4c810610a9d278fd25cc2c3480c002d4
+github.com/neelance/sourcemap,v0.0.0-20151028013722-8c68805598ab,h1:eFXv9Nu1lGbrNbj619aWwZfVF5HBrm9Plte8aNptuTI=,ce5499f29779a604233bb76f36925c3326a8a8f270533df8d3dff1107b7aa066
+github.com/neurosnap/sentences,v1.0.6,h1:iBVUivNtlwGkYsJblWV8GGVFmXzZzak907Ci8aA0VTE=,9dbe86e291937eba92847454650d1c65338527ff89dec5daccb99aaf7e03865b
+github.com/newrelic/go-agent,v2.15.0+incompatible,h1:IB0Fy+dClpBq9aEoIrLyQXzU34JyI1xVTanPLB/+jvU=,4c541c5f7b10055c37cf22843edbb9b0fcb06ad3504e8d6eae3d9c37ff3c64c6
+github.com/nf/cr2,v0.0.0-20140528043846-05d46fef4f2f,h1:nyKdx+jcykIdxGNrbgo/TGjdGi99EY9FKBCjYAUS4bU=,665afbe7830424dd9815cae42aa7762b657484686d671f88704257ea7c9736be
+github.com/nfnt/resize,v0.0.0-20180221191011-83c6a9932646,h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=,b8e97cb14e5e5ef29d762d2dff890f6279a125990ddf9cb7ae5c4d2a015b109c
+github.com/ngaut/pools,v0.0.0-20180318154953-b7bc8c42aac7,h1:7KAv7KMGTTqSmYZtNdcNTgsos+vFzULLwyElndwn+5c=,26342833d7a5b91a52f8451e8e34bc9ffc5069d342666ab0b478628c41a86d44
+github.com/ngaut/sync2,v0.0.0-20141008032647-7a24ed77b2ef,h1:K0Fn+DoFqNqktdZtdV3bPQ/0cuYh2H4rkg0tytX/07k=,2635d6120b6172c190f84b57b5fc878f9158b768b4bd6bd4468bfa98a73061a4
+github.com/nicksnyder/go-i18n,v2.0.2+incompatible,h1:Xt6dluut3s2zBUha8/3sj6atWMQbFioi9OMqUGH9khg=,687be9dc953545d390761e5464e07c38f313d19c1f695f7d7702d954afcf6b66
+github.com/nicolai86/scaleway-sdk,v1.10.2-0.20180628010248-798f60e20bb2,h1:BQ1HW7hr4IVovMwWg0E0PYcyW8CzqDcVmaew9cujU4s=,a2e992324edd4396f24e0b6a165c4d1057eeefdecdc9f7472b0de8a30f3be729
+github.com/niklasfasching/go-org,v0.1.6,h1:F521WcqRNl8OJumlgAnekZgERaTA2HpfOYYfVEKOeI8=,c938afb1ad7f567524686395c9de66da75220eaa60fe8917c02b97aa1e2cbbb1
+github.com/nkovacs/streamquote,v0.0.0-20170412213628-49af9bddb229,h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg=,679a789b4b1409ea81054cb12e5f8441199f5fb17d4a2d3510c51f3aa5f3f0cc
+github.com/nlopes/slack,v0.6.0,h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA=,048ddfddd4a66407f26b069a65d4d8f3d6d0368adcd52fd5a0dc6d86fe012f47
+github.com/nrdcg/auroradns,v1.0.0,h1:b+NpSqNG6HzMqX2ohGQe4Q/G0WQq8pduWCiZ19vdLY8=,81e3564b38ca27024b6e981a03ae70afcf435d5f8d35a2113321dfd3a220f00b
+github.com/nrdcg/goinwx,v0.6.1,h1:AJnjoWPELyCtofhGcmzzcEMFd9YdF2JB/LgutWsWt/s=,8e1e3ea7d38f5b9b21603350d97a583c9108d380f5cc08bf93a4c69d6968dc8a
+github.com/nrdcg/namesilo,v0.2.1,h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg=,e20a47d9257fcf7ce95254b14bb84ba290b5f4867e4d63027b669f5a55aaab6c
+github.com/nsf/jsondiff,v0.0.0-20160203110537-7de28ed2b6e3,h1:OqFSgO6CJ8heZRAbXLpT+ojX+jnnGij4qZwUz/SJJ9I=,9652618358184592fb7a4657e2c51748cbe0bf5bbf97150a2c6e95ecf65b126b
+github.com/nsf/termbox-go,v0.0.0-20190817171036-93860e161317,h1:hhGN4SFXgXo61Q4Sjj/X9sBjyeSa2kdpaOzCO+8EVQw=,a64e374836a25ab74ece4eb5314d79617d8b828bd6d13c654d95bed920c82784
+github.com/nsqio/go-nsq,v1.0.7,h1:O0pIZJYTf+x7cZBA0UMY8WxFG79lYTURmWzAAh48ljY=,5acb7902bf31355fa7d77f507ed42847368834eb378fbf407d82ae3e4211e248
+github.com/nu7hatch/gouuid,v0.0.0-20131221200532-179d4d0c4d8d,h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=,0889a0ac13cfa9f32f986a88a82bb24380070932299131ae7d7180a389d08ca7
+github.com/nullstyle/go-xdr,v0.0.0-20180726165426-f4c839f75077,h1:A804awGqaW7i61y8KnbtHmh3scqbNuTJqcycq3u5ZAU=,0ab4f958f0420027d40b53c98bcb8f3cbe1e106dfb49d3e91415cb1c512a552c
+github.com/nutmegdevelopment/sumologic,v0.0.0-20160817160817-42ed9b372fa3,h1:xOEJG5C3e8CvgAYsnkgoSBzCr0No+m++aB6v7A2WScY=,a33916e02e1159304145b621ffdf284120e50f618c684f38776a8bab7ae7b3fe
+github.com/nwaples/rardecode,v0.0.0-20171029023500-e06696f847ae,h1:UF9xsJn7AeQ72TCus3eRO1lh08Id3AoF37vl+qigL/w=,5598a02308af3b04418b15854ff940be49cf31ce7238ce23c10409110364d40f
+github.com/ogier/pflag,v0.0.1,h1:RW6JSWSu/RkSatfcLtogGfFgpim5p7ARQ10ECk5O750=,c4db0ecff32deb3205c705d72a616bce01e1f6a1948c851d30b52deeec3fbf91
+github.com/oklog/run,v1.0.0,h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=,108d409b7d235d61b82cfb6e1df139501123fcd8fa68fe94ddb024b53335cb48
+github.com/oklog/ulid,v1.3.1,h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=,40e502c064a922d5eb7f2bc2cda9c6a2a929ec0fc76c9aae4db54fb7b6b611ae
+github.com/olekukonko/tablewriter,v0.0.1,h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88=,7e5cc8a9b5a51126a0cb46ac96b274d92a8b1cc24b2321832c38d60c0ea4cc9c
+github.com/oliamb/cutter,v0.2.2,h1:Lfwkya0HHNU1YLnGv2hTkzHfasrSMkgv4Dn+5rmlk3k=,9174c2374109a7d3aeb2c59b5f4b744ec5f65752aab797f0d50beb26cfc7d857
+github.com/olivere/elastic,v6.2.25+incompatible,h1:X34sPAlSpZVlnuSjOYwbMbiCMU+WKK7YUxrunuNSdG8=,bf3b4cc7ea89a716e91002a31b33f55ec3168ce5ab36ffe5c02ff68d94b9aad5
+github.com/olivere/env,v1.1.0,h1:owp/uwMwhru5668JjMDp8UTG3JGT27GTCk4ufYQfaTw=,f486deab73b3d7866e762e1ad34fe63c88e9ac38f41d811414361fb6490bbb2c
+github.com/onsi/ginkgo,v1.10.3,h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=,088314495acb90d1e520519b243f4dbdd17b43469e6fb83bd45d600796856e63
+github.com/onsi/gomega,v1.7.1,h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=,0a245e719f17cc2bc399aa7c2005cca84f1cfba5373b0c96f5c64673f758a712
+github.com/op/go-logging,v0.0.0-20160315200505-970db520ece7,h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=,c506eace74028656eb28677a4c162f9c023ce2f9c0207354ba80cca89f11b461
+github.com/openconfig/gnmi,v0.0.0-20190823184014-89b2bf29312c,h1:a380JP+B7xlMbEQOlha1buKhzBPXFqgFXplyWCEIGEY=,f52967c7b194daa57252042f6ccf9d26f8c599a7e13aca26043f948d5139b91a
+github.com/openconfig/reference,v0.0.0-20190727015836-8dfd928c9696,h1:yHCGAHg2zMaW8olLrqEt3SAHGcEx2aJPEQWMRCyravY=,040cf32cee7256a08716313dd7ea4f8c44f1d644ae872ecf2dd381c35b12125c
+github.com/opencontainers/go-digest,v1.0.0-rc1,h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=,25fd455029e8a1bbe15ed2eeafc67222372c6f305a47b4ec157d8a1a2849c15c
+github.com/opencontainers/image-spec,v1.0.1,h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=,ebb2dca711a137fbfb717158b0368792f834000f4308d9ea259d06c6804c677c
+github.com/opencontainers/runc,v0.1.1,h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=,aa212163f009190d0f4f3dbe64f71fcda06d7896b67863d7f7b185fee6a68ea6
+github.com/opencontainers/runtime-spec,v1.0.1,h1:wY4pOY8fBdSIvs9+IDHC55thBuEulhzfSgKeC1yFvzQ=,1958458b00ce912425f5c7d2ee836431b296a3f9320d565512d8c96b107fffbf
+github.com/opencontainers/runtime-tools,v0.9.0,h1:FYgwVsKRI/H9hU32MJ/4MLOzXWodKK5zsQavY8NPMkU=,53c720dbb7452cfb2fd3945e37c26b5a0140cb1012d35a2b72a5e035f28a32c4
+github.com/opencontainers/selinux,v1.3.0,h1:xsI95WzPZu5exzA6JzkLSfdr/DilzOhCJOqGe5TgR0g=,88286825b32cd46a0469e578f378a185032da2d5b03893623861ef3af59359d8
+github.com/openshift/client-go,v3.9.0+incompatible,h1:13k3Ok0B7TA2hA3bQW2aFqn6y04JaJWdk7ITTyg+Ek0=,661b7f28b4905f1936dd58e373374513d54663ec85aecafede1c7d9c260e9369
+github.com/openshift/library-go,v0.0.0-20191101161407-e7c97b468b83,h1:wwR+laNaFKVGiizoIDL/cAKIZVoKXJ9jbjUoUlq2p5I=,c74f8134013f978ef154d6accf9b4b0c5126941f2d45e6eb223db7098f7ab2a4
+github.com/opentracing-contrib/go-observer,v0.0.0-20170622124052-a52f23424492,h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU=,50023eee1ef04412410f43d8b5dcf3ef481c0fc39067add27799654705fa84b2
+github.com/opentracing-contrib/go-stdlib,v0.0.0-20190519235532-cf7a6c988dc9,h1:QsgXACQhd9QJhEmRumbsMQQvBtmdS0mafoVEBplWXEg=,966cdf6d869ff62c35edf1ea00113465cc9b90f34838c6a6990a1f776e7d1152
+github.com/opentracing/basictracer-go,v1.0.0,h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo=,a908957c8e55b7b036b4761fb64c643806fcb9b59d4e7c6fcd03fca1105a9156
+github.com/opentracing/opentracing-go,v1.1.0,h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=,3e0f42d035019fa037991d340da9677a802f8182792770c38e87906d33e06629
+github.com/openzipkin-contrib/zipkin-go-opentracing,v0.4.4,h1:bzTJRoOZEN7uI1gq594S5HhMYNSud4FKUEwd4aFbsEI=,8a4688f80cd67140aa4edb91506d440ecea4d8ec01634caab5c95991af011c5d
+github.com/openzipkin/zipkin-go,v0.2.2,h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI=,dfc610dc52d9299df49172a9e61fcc772d85450b6b6f82e8f43cf23562232a4c
+github.com/oracle/oci-go-sdk,v7.0.0+incompatible,h1:oj5ESjXwwkFRdhZSnPlShvLWYdt/IZ65RQxveYM3maA=,941cd26813b22873477f1c6bb86fed929bdc85379d435bd9707d923f57d070dc
+github.com/orcaman/concurrent-map,v0.0.0-20190826125027-8c72a8bb44f6,h1:lNCW6THrCKBiJBpz8kbVGjC7MgdCGKwuvBgc7LoD6sw=,ec80830c751199283290a8d398ebf28ca5169e866a70347b39856d2c1178f2cb
+github.com/ory/dockertest,v3.3.4+incompatible,h1:VrpM6Gqg7CrPm3bL4Wm1skO+zFWLbh7/Xb5kGEbJRh8=,cbcc7ba21c846d38229aa06a2d7cf35b99ac219eb2694bd9a1ceeac89667e475
+github.com/ory/herodot,v0.6.2,h1:zOb5MsuMn7AH9/Ewc/EK83yqcNViK1m1l3C2UuP3RcA=,caf465ffb73c7537212ba4fd58a4c2c41fe7ca69737404a28e84ceff90c340ea
+github.com/otiai10/copy,v0.0.0-20180813032824-7e9a647135a1,h1:A7kMXwDPBTfIVRv2l6XV3U6Su3SzLUzZjxnDDQVZDIY=,67d0e4f6ba369653e30257882fbbb20c28b560bc837e1847a42c48e868f1c81c
+github.com/otiai10/curr,v0.0.0-20150429015615-9b4961190c95,h1:+OLn68pqasWca0z5ryit9KGfp3sUsW4Lqg32iRMJyzs=,7cf2143067d9bb3e7d54d2906766bb24c11d76f1bb0b0c5069574e9a0d8ae93d
+github.com/otiai10/mint,v1.2.3,h1:PsrRBmrxR68kyNu6YlqYHbNlItc5vOkuS6LBEsNttVA=,0b82a05ca43810c9aa8299ddae1663feeb178d699aeb5242c3bdeb61cb5a54fb
+github.com/outscale/osc-go,v0.0.1,h1:hvBtORyu7sWSKW1norGlfIP8C7c2aegI2Vkq75SRPCE=,2a988384c564fdba8b8c496024aafc212140e4b996654be7a92a3b0c7a962632
+github.com/ovh/go-ovh,v0.0.0-20181109152953-ba5adb4cf014,h1:37VE5TYj2m/FLA9SNr4z0+A0JefvTmR60Zwf8XSEV7c=,0fa35e8026a9b3aebd804739f31ffe07e553b84e2b8ea145b2f2ebaa0dd7c08f
+github.com/oxtoacart/bpool,v0.0.0-20190530202638-03653db5a59c,h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=,6816ec3a6f197cbee0ba6ddb9ec70958bc28870e59864b24e43da0c858079a1b
+github.com/packer-community/winrmcp,v0.0.0-20180921204643-0fd363d6159a,h1:A3QMuteviunoaY/8ex+RKFqwhcZJ/Cf3fCW3IwL2wx4=,4a48fa503853d129e7e32ca81f069b9e09a9e3249739781f61fae70bb02d098b
+github.com/packethost/packngo,v0.1.1-0.20180711074735-b9cb5096f54c,h1:vwpFWvAO8DeIZfFeqASzZfsxuWPno9ncAebBEP0N3uE=,6dac4e55c104df58ace636ef31d5dd6173a36747c4fd79299252ba8826127491
+github.com/parnurzeal/gorequest,v0.2.16,h1:T/5x+/4BT+nj+3eSknXmCTnEVGSzFzPGdpqmUVVZXHQ=,cc7b7d56e2e4c3fa0709e0e547875807746ac067b2a5c4b740b3088c1fdf941d
+github.com/pascaldekloe/goe,v0.1.0,h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=,37b73886f1eec9b093143e7b03f547b90ab55d8d5c9aa3966e90f9df2d07353c
+github.com/patrickmn/go-cache,v2.1.0+incompatible,h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=,d5d1c13e3c9cfeb04a943f656333ec68627dd6ce136af67e2aa5881ad7353c55
+github.com/pborman/uuid,v1.2.0,h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=,b888ff5d33651a1f5f6b8094acc434dd6dc284e2fe5052754a7993cebd539437
+github.com/pelletier/go-buffruneio,v0.2.0,h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA=,70593688607f4d48192776fe257ab9298689267ebcdd7b155bfe40d893735f38
+github.com/pelletier/go-toml,v1.6.0,h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4=,cc6dce19df6c6c30abd67594d17ea6015d1210aa6dd8c6096c6429eec06fdab4
+github.com/peterbourgon/diskv,v2.0.1+incompatible,h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=,1eeff260bd1ad71cd1611078995db99e1c7eba28628e7d6f24c79039536ea1cb
+github.com/peterbourgon/g2s,v0.0.0-20170223122336-d4e7ad98afea,h1:sKwxy1H95npauwu8vtF95vG/syrL0p8fSZo/XlDg5gk=,41526f42b4fe3019581ab3745afea18271d7f037eb55a6e9fb3e32fd09ff9b8d
+github.com/petergtz/pegomock,v2.7.0+incompatible,h1:42rJ5wIOBAg9OGdkLaPW9PlF/RtqDc5aGl6PcTCXl3o=,dc93e4483e8de4eb429e007aad17348822197ea7a3adde283b7752bc4544dfbb
+github.com/peterh/liner,v1.1.0,h1:f+aAedNJA6uk7+6rXsYBnhdo4Xux7ESLe+kcuVUF5os=,5cdc45c19901db8d8295c139bb382d7eea150e8fd96bd26de10384685728a461
+github.com/peterhellberg/link,v1.0.0,h1:mUWkiegowUXEcmlb+ybF75Q/8D2Y0BjZtR8cxoKhaQo=,d320f4204fbe886e1cefc0b677af2bfaba855e9e6556a6e92e43bcd80c3bb7a5
+github.com/petermattis/goid,v0.0.0-20180202154549-b0b1615b78e5,h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=,5134a176e306f9b973ff670a33c7536b59bf4114d83fd94f74c736ff0cc10ef0
+github.com/phayes/freeport,v0.0.0-20180830031419-95f893ade6f2,h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=,4ac97358de55a9b1ac60f13fdb223c5309a129fb3fb7bf731062f9c095a0796c
+github.com/philhofer/fwd,v1.0.0,h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=,b4e79b1f5fdfe8c44bf6dae3dd593c62862930114411a30968f304084de1d0b3
+github.com/pierrec/lz4,v2.3.0+incompatible,h1:CZzRn4Ut9GbUkHlQ7jqBXeZQV41ZSKWFc302ZU6lUTk=,775487f2be5ddf23034b59bc862cb0d5767155c5e08d1186665d117092ceb50f
+github.com/pingcap/check,v0.0.0-20190102082844-67f458068fc8,h1:USx2/E1bX46VG32FIw034Au6seQ2fY9NEILmNh/UlQg=,b8eeddacc35915d8c40b42e9af4db468ed309a506412a767ba6bb03bb7ce4627
+github.com/pingcap/errors,v0.11.4,h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=,df62e548162429501a88d936a3e8330f2379ddfcd4d23c22b78bc1b157e05b97
+github.com/pingcap/gofail,v0.0.0-20181217135706-6a951c1e42c3,h1:04yuCf5NMvLU8rB2m4Qs3rynH7EYpMno3lHkewIOdMo=,444866a53b7429e80a8a16791e39555de8103c7514cd322fe191c902b8071360
+github.com/pingcap/goleveldb,v0.0.0-20171020122428-b9ff6c35079e,h1:P73/4dPCL96rGrobssy1nVy2VaVpNCuLpCbr+FEaTA8=,08ec0ffe5d0d74bdc543695f975316af6a63c17e36644ae56d42e30b0d1f8777
+github.com/pingcap/kvproto,v0.0.0-20191101062931-76b56d6eb466,h1:C5nV9osqA+R/R2fxYxVfqAUlCi3Oo5yJ/JSKDeHSAOk=,0d834c10c217c5de2c9ef79049891a69e73e102c4dbcd130173c3650e96da570
+github.com/pingcap/log,v0.0.0-20191012051959-b742a5d432e9,h1:AJD9pZYm72vMgPcQDww9rkZ1DnWfl0pXV3BOWlkYIjA=,eaece6f27792a39ccff08152050d4eb7905c250bf36877cacdd7e74c79d80472
+github.com/pingcap/parser,v0.0.0-20191101070347-94a5ef60f10b,h1:TLljHrSTC9MCTiUA6nMhV68my/D/FI3VNkUs94Wo3DE=,94e6857f4d2bf653edf4c2881cb8fb6b3abdf9efaec7d1f49159deec77580df2
+github.com/pingcap/pd,v2.1.17+incompatible,h1:mpfJYffRC14jeAfiq0jbHkqXVc8ZGNV0Lr2xG1sJslw=,b75266cd20abe6b1ccbb777a2f71d74dfcf231a06276b602df08bf27a9ea36f1
+github.com/pingcap/tidb-tools,v2.1.4+incompatible,h1:dkB4FMJcSk9GYRB2ICupU/lsTLf4mHLfkBE6fAsLdJ4=,c5c8e2b5c69c21bba2050c75d3a4582eda26308a355557036f058365d4583e5f
+github.com/pingcap/tipb,v0.0.0-20191030045153-07a0962bbc64,h1:wUSHIp4dura5/YAepdgDBEdf2zz20MHXyNtMi1TcaDE=,8ac8e775e3d5fd255b7a8f07460f3b19bebb04cb50a3c0f5d6f64cc2fd585177
+github.com/pkg/browser,v0.0.0-20180916011732-0a3d74bf9ce4,h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98=,b845f84fbf08bba75401a4eff94c01c9e2c668fa1b43016e835bd60c6a8b4e87
+github.com/pkg/errors,v0.8.1,h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=,4e47d021340b7396a7dee454f527552faf7360a9fc34038b1dc32ba3b5a951d8
+github.com/pkg/profile,v1.3.0,h1:OQIvuDgm00gWVWGTf4m4mCt6W1/0YqU7Ntg0mySWgaI=,5f20c007ac81019900f06cf1e4d451ce8e1d981460e39e04794fbcc60639f851
+github.com/pkg/sftp,v1.10.1,h1:VasscCm72135zRysgrJDKsntdmPN+OuU3+nnHYA9wyc=,4e30f0455865434be7b83d4010ab97667217dafd0017caa651faafa2cc6aed64
+github.com/pkg/term,v0.0.0-20180730021639-bffc007b7fd5,h1:tFwafIEMf0B7NlcxV/zJ6leBIa81D3hgGSgsE5hCkOQ=,165bb00eeab26fe65c64e0e13bc29abc7ea18ac28d288e2218c137cd0bd91d9b
+github.com/plaid/plaid-go,v0.0.0-20161222051224-02b6af68061b,h1:Don6I/E8nLCT6gdBi1sKB9hYxkx/24YD7XWwSly8IEo=,bd900ff0acd2968150f60770ab4e870d9f6b92c129a49eac0c9620a8043f901e
+github.com/pmezard/go-difflib,v1.0.0,h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=,de04cecc1a4b8d53e4357051026794bcbc54f2e6a260cfac508ce69d5d6457a0
+github.com/polydawn/refmt,v0.0.0-20190408063855-01bf1e26dd14,h1:2m16U/rLwVaRdz7ANkHtHTodP3zTP3N451MADg64x5k=,a92440a944006fd3e0b6f1717fce4c2ea490cf2c4af93b56675216204f138c3a
+github.com/portworx/kvdb,v0.0.0-20190911174000-a0108bddd091,h1:DqGiNhvCpvhWW/HJ1naJa0DudtlckvzQ9hEXSsOyv8Y=,d6fa957e1469a1b47ccbebc805034bafc5ed24798a1bef8675f751f9c4ed961e
+github.com/portworx/sched-ops,v0.0.0-20191101005636-ded833c86f1e,h1:emQnaLwLEYN3Hner2ekVuZfrcChdN3H3J4Lxu5mPe64=,43ff366e97ff640a34a566c81dd7d63537c2864da85d33b49d5261417cd8d4b0
+github.com/posener/complete,v1.2.1,h1:LrvDIY//XNo65Lq84G/akBuMGlawHvGBABv8f/ZN6DI=,a97f73829e0b71ae7a8f17a4884d5dcbb2c3499d8d3a077c2a8d7c2596f68d37
+github.com/pquerna/cachecontrol,v0.0.0-20180517163645-1555304b9b35,h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=,0e5185ab4dab1bb2241e9e23e36ebde5713f3fb1e47767c3eb44001b7e17644f
+github.com/pquerna/ffjson,v0.0.0-20190930134022-aa0246cd15f7,h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20=,377b4667540f620eae19722b5346f6f1efdea5688f9eedda97f2c659dad131f9
+github.com/pquerna/otp,v1.1.0,h1:q2gMsMuMl3JzneUaAX1MRGxLvOG6bzXV51hivBaStf0=,d46d289853f801387dfc514fd50133de30b684a6af34031b27caa877cbb7f687
+github.com/profitbricks/profitbricks-sdk-go,v4.0.2+incompatible,h1:ZoVHH6voxW9Onzo6z2yLtocVoN6mBocyDoqoyAMHokE=,b0baf185752eb96f8890f3e9adf856b13f5c43b5346387b659e2b1deb1d087c7
+github.com/project-flogo/core,v0.9.3,h1:uZXHR9j1Byqt+x3faNnOqB8NlEfwE2gpCh40iQ+44oA=,d1c43e3bc517bb438a9d313d976e327ba219232418064d439fb20671341832a2
+github.com/projectcalico/libcalico-go,v1.7.3,h1:qcbxAhsq/5zqZqpHE24VqMHfmoBVdXZV0Kf82+5rbqU=,4f638d56eb47ff8e1763f65131050294f7d2c828139276fe86127a803245ae8c
+github.com/prometheus/alertmanager,v0.18.0,h1:sPppYFge7kdf9O96KIh3fd093D1xN8JxIp03wW6yAEE=,45e122e7c2ac69577d63844313798060673a28b2e86ec8a0197f330c584b379b
+github.com/prometheus/client_golang,v1.2.1,h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=,174c921fe3e154adddd8e0dc572323dd04901bcad0965de614174241981da57c
+github.com/prometheus/client_model,v0.0.0-20190812154241-14fe0d1b01d4,h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=,5d4719be47f4f69ab5bf36a04c75eb078a0f69b43a335f400c2d688ac9e61795
+github.com/prometheus/common,v0.7.0,h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=,f2640a94b18b115552df41ee33effa013e10536aca51e09a971d1503a20e186a
+github.com/prometheus/procfs,v0.0.5,h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=,f45b90c72f8c2e4c84e5314092ee1ccf7d6ace1cc14b2f483c82f7c1e6d0d0d4
+github.com/prometheus/prom2json,v1.1.0,h1:/fEL2DK7EEyHVeGMG4TV+gSS9Sw53yYKt//QRL0IIYE=,166f5f98c62d0b90139947d1464ee747f8143772b9e926c7b51c53a4420380ff
+github.com/prometheus/prometheus,v2.5.0+incompatible,h1:7QPitgO2kOFG8ecuRn9O/4L9+10He72rVRJvMXrE9Hg=,ede73f6ccabd60365549986a6c7ae152c1952129006c8ae521c86ff45c4aadcc
+github.com/prometheus/tsdb,v0.10.0,h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic=,34e98f0e9ba55e7290774ee40569737745b395e32811e5940d2ed124a20f927c
+github.com/pyinx/gorocket,v0.0.0-20170810024322-78ae1353729f,h1:N1r6pSlez3lLsqaNHbtrHW9ZuzrilETIabr9jPNj3Zs=,dcd920b789a98157bbe1ed7fff249255c1dd4d2fd80f7edc39b3a49fc08db13a
+github.com/qor/admin,v0.0.0-20191021122103-f3db8244d2d2,h1:IWw22+hlihdss/qI93QH48jTBUEOD/fsBqj+0z61z/Y=,722e243550878791adcdb3bcea66ab8e7a185637c8a7ad0a752713951aef2a91
+github.com/qor/assetfs,v0.0.0-20170713023933-ff57fdc13a14,h1:JRpyNNSRAkwNHd4WgyPcalTAhxOCh3eFNMoQkxWhjSw=,7fe36875e7e59afd9154f827babbffaa7f67ac54b7790df5a4a4a376c78b2282
+github.com/qor/middlewares,v0.0.0-20170822143614-781378b69454,h1:+WCc1IigwWpWBxMFsmLUsIF230TakGHstDajd8aKDAc=,4c2ed9a2f7b24dfa64464091b2c01ce9fc947524bb834d77aeb9ceaf8610e5fc
+github.com/qor/qor,v0.0.0-20191022064424-b3deff729f68,h1:MSbP9P4HnmEyH+uGQAW+V0HoTzlZ9SRq7kdCaRiZEmU=,9053796b8a7afe21483262affaf5b35bac8bf3387e24531448a4833d7b758978
+github.com/qor/render,v1.1.1,h1:DaGaKlf0OzpOB+hJUEiOTbZ40mg+n+LlSJx20/KUfes=,8f957a13173ef1a22d0caeea1cc6d198b064d242676444e00e2f597c405928c9
+github.com/qor/responder,v0.0.0-20171031032654-b6def473574f,h1:sKELSAyL+z5BRHFe97Bx71z197cBEobVJ6rASKTMSqU=,b69784649ec65ec2580d7640af25ec66973d59d82ec5391498cfe4c3076e5f6f
+github.com/qor/roles,v0.0.0-20171127035124-d6375609fe3e,h1:F0BNcPJKfubM/+IIILu/GbrH9v2vPZWQ5/StSRKUfK4=,1a35a5480c7169e86025eb19dbcddc13fd00472e6b4ade7574e62c290cf09100
+github.com/qor/session,v0.0.0-20170907035918-8206b0adab70,h1:8l21EEdlZ9R0AA3FbeUAANc5NAx8Y3tn1VKbyAgjYlI=,7c759bc736c4936a602ca1f0ebad9a324d8332ffd342e1e3acd80355180fc858
+github.com/qor/validations,v0.0.0-20171228122639-f364bca61b46,h1:dRlsVUhwD1pwrasuVbNooGQITYjKzmXK5eYoEEvBGQI=,b29360c4a4e9cc8d0ff682d8bf1f446a5d61d5a4f8d3cf2fc6d8cc077e5d810f
+github.com/racker/perigee,v0.1.0,h1:8RjBm1YGJKVVjUfO02Uok+npegz8lSSEVqjimDqlFYc=,d43613102ed67445c9fc81b621959b58f827c187189b09cec236c3bac5ce1ccb
+github.com/raff/goble,v0.0.0-20190909174656-72afc67d6a99,h1:JtoVdxWJ3tgyqtnPq3r4hJ9aULcIDDnPXBWxZsdmqWU=,ef5dde1af55d451c37ddf13e17ae339d299903cb7e67567fc6d1e69688a789e1
+github.com/rai-project/config,v0.0.0-20190926180509-3bd01e698aad,h1:o0056EwcQBeyaVb2my+T0TvMR5FpEY0CGNgWkbj/xEo=,27c2311ad1fdc185e08f2e1703893482b7d26caf64854ed371bf38f3a9303f92
+github.com/rai-project/godotenv,v0.0.0-20180619160704-a501614c3b8d,h1:reVy+ViZcrx1ILo+L8wa3dGf6hSd4qlY62VqxZxEgWs=,f4d9ecb56f20667fbb09bd5256d0c6b81b9e8cbca8f6476240c5d1800ffb07ed
+github.com/rai-project/logger,v0.0.0-20190701163301-49978a80bf96,h1:GeXSVSRfXOBN5XHNA+wq5G+sfq99mhpwn6U5kcGwSeg=,53d7677e7d7dab6b1f83591ec10491301289752e337641403f8413c0749b84d8
+github.com/rai-project/utils,v0.0.0-20180619204045-c582bb171808,h1:cHOS6oMEt8wi93zm5V7cHVnWgOhaAUCpjRDEZHBsckg=,6d43ccc901ad2f19744696f6c3d04ee28b4496cef7fe72ce7eccb89af0d8bfac
+github.com/rai-project/vipertags,v0.0.0-20190404224953-d63b0a674aa9,h1:3o86f/tK0DBZdPcUBjzFu1mEZsRCzjSgi5PNHope4AQ=,9aa8cdd1a3369382d28bad0f4581250fbecae51602aa8566cbe68dfadc8f7785
+github.com/raintank/schema,v1.0.0,h1:tK0zKHceZd5nkCUI5Soip1pA2BAvoc4qzloVEsK0y+Q=,9ffc30e882b1cfed3152bab9c8c95e00c984dc0d8895426c95d96a184e09ffe3
+github.com/rainycape/memcache,v0.0.0-20150622160815-1031fa0ce2f2,h1:dq90+d51/hQRaHEqRAsQ1rE/pC1GUS4sc2rCbbFsAIY=,2d42bb018c6b0531f93e2dc862c87374966c64c9a88863612ab5e676a32661fa
+github.com/rainycape/unidecode,v0.0.0-20150907023854-cb7f23ec59be,h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ=,0ab56010a3ef93c20bb6d8c486e3b447b4004052053e280ea6eabf2a5138bdce
+github.com/rakyll/statik,v0.1.6,h1:uICcfUXpgqtw2VopbIncslhAmE5hwc4g20TEyEENBNs=,58cc0c07f8e9dd17ad5c4e0f89c03d8a3ed420aac0e76b79adf7ebd1d48c5893
+github.com/rcrowley/go-metrics,v0.0.0-20190826022208-cac0b30c2563,h1:dY6ETXrvDG7Sa4vE8ZQG4yqWg6UnOcbqTAahkV813vQ=,22e944d960aec1a1e62e8cc2daaa70abefbbe989dd9c233060ab533de5f6e724
+github.com/remyoudompheng/bigfft,v0.0.0-20190512091148-babf20351dd7,h1:FUL3b97ZY2EPqg2NbXKuMHs5pXJB9hjj1fDHnF2vl28=,73f78c7e36c32822221f9f676b65ebe7ccb92ab6ff221035ace35c184e165c0d
+github.com/renier/xmlrpc,v0.0.0-20170708154548-ce4a1a486c03,h1:Wdi9nwnhFNAlseAOekn6B5G/+GMtks9UKbvRU/CMM/o=,f9c07652c6de1aecf5baaa3b93c1e6c23379458e30553400d5f96ac8b3ea85c4
+github.com/renstrom/fuzzysearch,v0.0.0-20160331204855-2d205ac6ec17,h1:4qPms2txLWMLXKzqlnYSulKRS4cS9aYgPtAEpUelQok=,01782a5d1682a72614126da402171253030c0de60485bc18a3e63b07d977c094
+github.com/retr0h/go-gilt,v0.0.0-20190206215556-f73826b37af2,h1:vZ42M1tDiMLtirFA1K5k2QVFhWRqR4BjdSw0IMclzH4=,e7956b01b3ccea41395f1f641a0f9045f214c1075d7ecc25553b72383009274e
+github.com/revel/config,v0.21.0,h1:Bw4iXLGAuD/Di2HEhPSOyDywrTlFIXUMbds91lXTtTU=,22842698f6c646b9b89649b432d0f24deae1c5a3779c49819ec99c5db6e4b5a0
+github.com/revel/log15,v2.11.20+incompatible,h1:JkA4tbwIo/UGEMumY50zndKq816RQW3LQ0wIpRc+32U=,28e4263b0320a07dd2ae71ba09aef1f9b4af44258a8c0f1dfb1d63300f93c401
+github.com/revel/pathtree,v0.0.0-20140121041023-41257a1839e9,h1:/d6kfjzjyx19ieWqMOXHSTLFuRxLOH15ZubtcAXExKw=,de658b8de908c9c090343447e66e6bbdfe99656fcfa5889997486b0594c2a719
+github.com/revel/revel,v0.21.0,h1:E6kDJmpJSDb0F8XwbyG5h4ayzpZ+8Wcw2IiPZW/2qSc=,c66570c338f37e95626646909af1086f0bf31d8432fe982d24c415d14bc1dc9c
+github.com/rivo/tview,v0.0.0-20191018125527-685bf6da76c2,h1:GVXSfgXOMAeLvFH7IrpY3yYM8H3YekZEFcZ14q9gQXM=,000538d9517bd5f28cfe377e63183f7093043acf8bb913eb493adb29518eb6b8
+github.com/rivo/uniseg,v0.1.0,h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=,cb701df81f36acfbb2627a78662fdcaa150ee1ac00d0796a7f3eafbdb6218128
+github.com/rjeczalik/notify,v0.9.2,h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8=,e8b9b93870f7ed17f30c617acb55f5fa78e7931518c88999c3d1b5b048f51482
+github.com/rkt/rkt,v1.30.0,h1:ZI5RQtSibfjicSttV/HLiHuWreYClEJA2Or5XKAdJb0=,ca2e00335dbeae7e0fbe2c45535d2bb8fce72c2bb6045b0bdf25bc6b8b59179e
+github.com/robertkrimen/otto,v0.0.0-20180617131154-15f95af6e78d,h1:1VUlQbCfkoSGv7qP7Y+ro3ap1P1pPZxgdGVqiTVy5C4=,7adbe73b0db5319bae0421a0ed7fc5619002d6e9a2be87dc8c673c8541dfd949
+github.com/robfig/cron,v1.2.0,h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=,0811a1a5a4e1f45824ac520deb2002326a659dbb4918cdfea47d80560a23211d
+github.com/robfig/cron/v3,v3.0.0,h1:kQ6Cb7aHOHTSzNVNEhmp8EcWKLb4CbiMW9h9VyIhO4E=,5e29b4f7f4ba62293420b918fb2309823523a583c2adaf6eddb059f525f05496
+github.com/rogpeppe/fastuuid,v1.2.0,h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=,f9b8293f5e20270e26fb4214ca7afec864de92c73d03ff62b5ee29d1db4e72a1
+github.com/rogpeppe/go-charset,v0.0.0-20180617210344-2471d30d28b4,h1:BN/Nyn2nWMoqGRA7G7paDNDqTXE30mXGqzzybrfo05w=,a28b06534aa71873d08578d69b08512dab54caa0ffd9e2943b3479166049eddd
+github.com/rogpeppe/go-internal,v1.4.0,h1:LUa41nrWTQNGhzdsZ5lTnkwbNjj6rXTdazA1cSdjkOY=,fb7d843253301d3ea9793f90e6bea16a8f2970a01b361f490ee66b36f81e03a5
+github.com/rpcx-ecosystem/quic-conn,v0.0.0-20190920095804-3967ef162525,h1:Awv5A28rrxuHf1+9+N08cnBa6JuKbhHswmNdfj65Bzo=,b40886ad7129eff9e517187b527467330db3705207349cdaa8f35c0dc8445c08
+github.com/rs/cors,v1.7.0,h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=,67815316761fddc4acfaad852965cf04ec88674abe3a05c6c332519556c55855
+github.com/rs/xhandler,v0.0.0-20160618193221-ed27b6fd6521,h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20=,665ae95533e1a046cf470c7341c59e64b3e2a795cdaaf307368f69a0ba547f2c
+github.com/rs/xid,v1.2.1,h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc=,4abdedc4de69adcb9a4575f99c59d8ab542191e1800b6a91e12a4e9ea8da0026
+github.com/rs/zerolog,v1.16.0,h1:AaELmZdcJHT8m6oZ5py4213cdFK8XGXkB3dFdAQ+P7Q=,64e248c1fa3c62e2d904868b49acf906d0cb04a00a323d2562ea9ce7c6f154e1
+github.com/rubenv/sql-migrate,v0.0.0-20191025130928-9355dd04f4b3,h1:lwDYefgiwhjuAuVnMVUYknoF+Yg9CBUykYGvYoPCNnQ=,4d4e9e2c7387542b26a1cd9fbfcbdab7b75dce807877d5a0a501180b584c60f2
+github.com/rubyist/circuitbreaker,v2.2.1+incompatible,h1:KUKd/pV8Geg77+8LNDwdow6rVCAYOp8+kHUyFvL6Mhk=,fc1125d9260a471d349c94a251340c437f98743b42324706482596f303c28b11
+github.com/russross/blackfriday,v2.0.0+incompatible,h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk=,836047aa9cbd223efba85b892e6897cf7a3b5ee3f2e6ad36b189d40842f703df
+github.com/russross/blackfriday/v2,v2.0.1,h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=,496079bbc8c4831cd0507213e059a925d2c22bd1ea9ada4dd85815d51b485228
+github.com/rwcarlsen/goexif,v0.0.0-20190401172101-9e8deecbddbd,h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc=,98e8ce7bf484716bdf272f31ee01354599f4ec4b4ece7c04156c15b264d8f6ec
+github.com/ryanuber/columnize,v2.1.0+incompatible,h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s=,ff687e133db2e470640e511c90cf474154941537a94cd97bb0cf7a28a7d00dc7
+github.com/ryanuber/go-glob,v1.0.0,h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=,2084f36ead38a505489fdb46329502fb627f568224dcc22ef11ec173b61fc2cf
+github.com/ryszard/goskiplist,v0.0.0-20150312221310-2dfbae5fcf46,h1:GHRpF1pTW19a8tTFrMLUcfWwyC0pnifVo2ClaLq+hP8=,12c65729fc31d5a9bf246eb387bd4c268d0d68bf33b913cccd81bebd47d6f80d
+github.com/sacloud/libsacloud,v1.26.1,h1:td3Kd7lvpSAxxHEVpnaZ9goHmmhi0D/RfP0Rqqf/kek=,4f0e24194ce3566707df5862177cb0f697debe3d5b799decb2685ee8d07dbe11
+github.com/saintfish/chardet,v0.0.0-20120816061221-3af4cd4741ca,h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=,d9cb0e35c88fbf91a409db0626f2e8ae9db305cf95dc3469dc7d089a8432c9c3
+github.com/samuel/go-zookeeper,v0.0.0-20190923202752-2cc03de413da,h1:p3Vo3i64TCLY7gIfzeQaUJ+kppEO5WQG3cL8iE8tGHU=,499f8144de8a6839b2d70c8869d88f294604188ec501e928ca17446043147d40
+github.com/sanity-io/litter,v1.1.0,h1:BllcKWa3VbZmOZbDCoszYLk7zCsKHz5Beossi8SUcTc=,c4bbddbf1bd7bb4ef74a3c2cac98f4a78a2a3a5a6b8dd140bd31a5d38c459217
+github.com/santhosh-tekuri/jsonschema,v1.2.4,h1:hNhW8e7t+H1vgY+1QeEQpveR6D4+OwKPXCfD2aieJis=,1c946415ee3395181090664a37779c296b540ca7eec58844ad0283fef11fec00
+github.com/sasha-s/go-deadlock,v0.2.0,h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y=,6c3f90c7947da1090f545438f4b3fd461cfeec79ee1c6e5e83a0eed7258622b1
+github.com/sassoftware/go-rpmutils,v0.0.0-20190420191620-a8f1baeba37b,h1:+gCnWOZV8Z/8jehJ2CdqB47Z3S+SREmQcuXkRFLNsiI=,88264dbd268c88bc8a57e4b4a261f22058fa6e03eb2883b0a82375f854e15188
+github.com/satori/go.uuid,v1.2.0,h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=,4f741306a0cbe97581e34a638531bcafe3c2848150539a2ec2ba12c5e3e6cbdd
+github.com/satori/uuid,v1.2.0,h1:6TFY4nxn5XwBx0gDfzbEMCNT6k4N/4FNIuN8RACZ0KI=,bfd4d3d619e3ad4dd915e05fec5bf10949d8af9bc5c19b840db35ec0f21172ad
+github.com/scaleway/scaleway-cli,v0.0.0-20180921094345-7b12c9699d70,h1:DaqC32ZwOuO4ctgg9qAdKnlQxwFPkKmCOEqwSNwYy7c=,05566d6711de08738803132b8522f7051fccd3b3bf2c739dde421fffdfa75eaf
+github.com/sclevine/agouti,v3.0.0+incompatible,h1:8IBJS6PWz3uTlMP3YBIR5f+KAldcGuOeFkFbUWfBgK4=,b20c8a6a2c1fda0ae6a9cd6d319e78a7a5afea4bc90810cd46b99246d8219d23
+github.com/sclevine/spec,v1.2.0,h1:1Jwdf9jSfDl9NVmt8ndHqbTZ7XCCPbh1jI3hkDBHVYA=,582017cd824cf3cdf6803ec7db2250304f66efea705feb69cbabab416928b8f4
+github.com/sean-/conswriter,v0.0.0-20180208195008-f5ae3917a627,h1:Tn2Iev07a4oOcAuFna8AJxDOF/M+6OkNbpEZLX30D6M=,0637d2fc0eb4627827e4b73dbe3a72479708641df8fc71a06e7bc481f6a7f39b
+github.com/sean-/pager,v0.0.0-20180208200047-666be9bf53b5,h1:D07EBYJLI26GmLRKNtrs47p8vs/5QqpUX3VcwsAPkEo=,a4288f9116ea01c34efd65b7dce4357ba6f9c02ad984ca758fea0d0aebb605c9
+github.com/sean-/seed,v0.0.0-20170313163322-e2103e2c3529,h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=,0bc8e6e0a07e554674b0bb92ef4eb7de1650056b50878eed8d5d631aec9b6362
+github.com/sebest/xff,v0.0.0-20150611211316-7a36e3a787b5,h1:MqIPVG2sHTgcQxFwZ+iHZSQ869PVP42SgEEeI1+X4Y8=,8cbe518a78ab7998550c509bd9fadc95a1aef8e86b1022cb3d265348ad370cde
+github.com/seccomp/libseccomp-golang,v0.9.1,h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46rlXTMfXGWBo=,5989692d87ef4c377fbc60d441795a90d9453b9e357d019e44d9033ab39ca888
+github.com/segmentio/go-loggly,v0.5.1-0.20171222203950-eb91657e62b2,h1:S4OC0+OBKz6mJnzuHioeEat74PuQ4Sgvbf8eus695sc=,5e071d0b6923a0fa78895bf7e673f5a4e482d39d4603b7dabd4056a506923ca7
+github.com/segmentio/go-prompt,v1.2.1-0.20161017233205-f0d19b6901ad,h1:EqOdoSJGI7CsBQczPcIgmpm3hJE7X8Hj3jrgI002whs=,b86fcda4b8afd5a3893ea333431368e60ea5ebee302a3014aee6d2020233bf31
+github.com/segmentio/kafka-go,v0.1.0,h1:IXCHG+sXPNiIR5pC/vTEItZduPKu4cnpr85YgxpxlW0=,e0b749b974d3277438d09dd6178928c3ad6c3760313f7ad45ec5cd88d8eb14b9
+github.com/serenize/snaker,v0.0.0-20171204205717-a683aaf2d516,h1:ofR1ZdrNSkiWcMsRrubK9tb2/SlZVWttAfqUjJi6QYc=,67272dde9cf92af80704869dea59346be1c37098373200dd8eea6e0e034079b4
+github.com/sergi/go-diff,v1.0.0,h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=,287218ffcd136dbb28ce99a2f162048d8dfa6f97b524c17797964aacde2f8f52
+github.com/serialx/hashring,v0.0.0-20180504054112-49a4782e9908,h1:RRpyb4kheanCQVyYfOhkZoD/cwClvn12RzHex2ZmHxw=,4184e14faf8e39222109eb2b7fa3aee2e0a544b66785ad0b7058318483ff76bb
+github.com/sethgrid/pester,v0.0.0-20190127155807-68a33a018ad0,h1:X9XMOYjxEfAYSy3xK1DzO5dMkkWhs9E9UCcS1IERx2k=,ddcaf31e63aaf1ac003af97e667bedaa0fc89956e19aeb032c5658629da29800
+github.com/shiena/ansicolor,v0.0.0-20151119151921-a422bbe96644,h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=,60da6dc53662eb72063784f3bf609edb7aa317c552f81651164bc657754902a6
+github.com/shirou/gopsutil,v2.19.10+incompatible,h1:lA4Pi29JEVIQIgATSeftHSY0rMGI9CLrl2ZvDLiahto=,e5afa6f0b690ecc3ff12458663c6337920a759f27c3d9692a0836644337e4e85
+github.com/shirou/w32,v0.0.0-20160930032740-bb4de0191aa4,h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U=,3ed6741a7e1470feffb50031ecf9919f30b5f573f993683b6574488756ef65c1
+github.com/shopspring/decimal,v0.0.0-20191009025716-f1972eb1d1f5,h1:Gojs/hac/DoYEM7WEICT45+hNWczIeuL5D21e5/HPAw=,91a0ee539fb6f3de1550cdf93c73434fc8a16bab37be693997b20317510331a9
+github.com/shurcooL/component,v0.0.0-20170202220835-f88ec8f54cc4,h1:Fth6mevc5rX7glNLpbAMJnqKlfIkcTjZCSHEeqvKbcI=,2dd1cfac518def9fc8c6ac69022a85b0413269caf93d9532f77dca7375e1d645
+github.com/shurcooL/events,v0.0.0-20181021180414-410e4ca65f48,h1:vabduItPAIz9px5iryD5peyx7O3Ya8TBThapgXim98o=,1dcade8d00ba3945f5d1bc56c09a84e2d51fa20d20ef4fa6f867e5e4cd918e9d
+github.com/shurcooL/github_flavored_markdown,v0.0.0-20181002035957-2122de532470,h1:qb9IthCFBmROJ6YBS31BEMeSYjOscSiG+EO+JVNTz64=,d984dc45e823f4c99e89841d675e34d2d35d3b334f1b3690fde05de30a66929f
+github.com/shurcooL/githubv4,v0.0.0-20191006152017-6d1ea27df521,h1:ARaYJO1zp2afVv0s28fq7uxgee4WLop35FWrOoSZyak=,7f5c88b38760c5090bffe582a40abe7dc17a789f9041549e5c17e3d71df2d75d
+github.com/shurcooL/go,v0.0.0-20180423040247-9e1955d9fb6e,h1:MZM7FHLqUHYI0Y/mQAt3d2aYa0SiNms/hFqC9qJYolM=,350e4c547dbeb657bb3b2eab428f1c29a80808e8096ff87324fd84744f914766
+github.com/shurcooL/go-goon,v0.0.0-20170922171312-37c2f522c041,h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc=,31cb3f736521597c56f962b9d7d21073620fbb1da845305aba743960f09e4115
+github.com/shurcooL/gofontwoff,v0.0.0-20180329035133-29b52fc0a18d,h1:Yoy/IzG4lULT6qZg62sVC+qyBL8DQkmD2zv6i7OImrc=,685dedb79602bb41403a7b5198f5c9d0ffbc99a68d7f99160ecf08a71475e5f4
+github.com/shurcooL/gopherjslib,v0.0.0-20160914041154-feb6d3990c2c,h1:UOk+nlt1BJtTcH15CT7iNO7YVWTfTv/DNwEAQHLIaDQ=,ea6c396c92724a8028793bde957dbe9a1c594b8af085035e652d4335e6aa30e1
+github.com/shurcooL/graphql,v0.0.0-20181231061246-d48a9a75455f,h1:tygelZueB1EtXkPI6mQ4o9DQ0+FKW41hTbunoXZCTqk=,eb1b45dc90aed0edcfc4cacffdc2645121dda8155702440eada1bcafefddcbba
+github.com/shurcooL/highlight_diff,v0.0.0-20170515013008-09bb4053de1b,h1:vYEG87HxbU6dXj5npkeulCS96Dtz5xg3jcfCgpcvbIw=,b4bcb7f3e50a99623d5f39c4e054964fc60d5e4b34543408582a0a984a67b630
+github.com/shurcooL/highlight_go,v0.0.0-20181028180052-98c3abbbae20,h1:7pDq9pAMCQgRohFmd25X8hIH8VxmT3TaDm+r9LHxgBk=,9f879b051c8eadb6dc063ca3ff6856d0e64cd30b5ad545e580b77b4f8ef9ddd7
+github.com/shurcooL/home,v0.0.0-20181020052607-80b7ffcb30f9,h1:MPblCbqA5+z6XARjScMfz1TqtJC7TuTRj0U9VqIBs6k=,0042d859afa3221fd4b4049b350a2d6ffcc674e4c4177bb0c232dc120b410ee6
+github.com/shurcooL/htmlg,v0.0.0-20190503024804-b6326af49ef6,h1:kXXs9Xnfv5gU7KLKiOE3AQgaRUUXchcXnO2rP3fZ5Ao=,52485f17bba8920b37a70124b90eea9d43037a9764a785c97a7e531ca09ed5a5
+github.com/shurcooL/httperror,v0.0.0-20190506043526-2e76094aa70e,h1:QTph/PpT1aDtFHk0sVJoVG/Vfox0YZkq70sW/tvXJM0=,7807129d1577611bdf803b7a4dd3253f45e4b63a77c1a73bed48a0c838c463c6
+github.com/shurcooL/httpfs,v0.0.0-20190707220628-8d4bc4ba7749,h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk=,a2079dbd8c236262ecbb22312467265fbbddd9b5ee789531c5f7f24fbdda174b
+github.com/shurcooL/httpgzip,v0.0.0-20190720172056-320755c1c1b0,h1:mj/nMDAwTBiaCqMEs4cYCqF7pO6Np7vhy1D1wcQGz+E=,70ef73fce2f89d622f828cb439fd6c7b48a7fe63600410a8c0a936042c0e4631
+github.com/shurcooL/issues,v0.0.0-20190705005435-6a96395fbb66,h1:kls/E9JqtKEj8tWx2PwKCWqEWmwzsX7cnj9QkaEhUpM=,dd1ace2ad69b6c130a9294c3eb4032090e73c3b7dace098a5a7e1ad154f8e911
+github.com/shurcooL/issuesapp,v0.0.0-20180602232740-048589ce2241,h1:Y+TeIabU8sJD10Qwd/zMty2/LEaT9GNDaA6nyZf+jgo=,ac947684d3f13beef9433724deddc2c7ddb6d19921d6902f4789dd4ce1af5f3c
+github.com/shurcooL/notifications,v0.0.0-20181111060504-bcc2b3082a7a,h1:bQX0+HfDylIQCtf1tzyrxQ+BqIV08ZjkjgspFWiIYhc=,c1c77700f490d0211cec00fd5fd0ee80debf66e0e41de1dc68b24dc726db5409
+github.com/shurcooL/octicon,v0.0.0-20190930024621-43309dfb482e,h1:C2+alklsN4yRHXaOX3v9TuCGlTSwZQjSnN88nLGVhg8=,88953a9951a14e24afd2d1040e9de0b4fbe194805fdc7ec9d9d9bbcd8c2f3448
+github.com/shurcooL/reactions,v0.0.0-20181222204718-145cd5e7f3d1,h1:hHIhW4KrmPQ/hJ7AuKNNvVPVE2k/LVE5NTFsQ68taBw=,fd5f9a0c6e7e292bdfa81fcad767f61c95dc84f18bf4f9f02a4fe02f75327d37
+github.com/shurcooL/sanitized_anchor_name,v1.0.0,h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=,0af034323e0627a9e94367f87aa50ce29e5b165d54c8da2926cbaffd5834f757
+github.com/shurcooL/users,v0.0.0-20180125191416-49c67e49c537,h1:YGaxtkYjb8mnTvtufv2LKLwCQu2/C7qFB7UtrOlTWOY=,3f17089e996438a88a478d38807ce4f3c045a91114830946a1bdc760eb2b7c58
+github.com/shurcooL/vfsgen,v0.0.0-20181202132449-6a9ea43bcacd,h1:ug7PpSOB5RBPK1Kg6qskGBoP3Vnj/aNYFTznWvlkGo0=,8a093681b21159514a1742b1a49e88fa2cf562673a5a0055e9abeb7ff590ee19
+github.com/shurcooL/webdavfs,v0.0.0-20170829043945-18c3829fa133,h1:JtcyT0rk/9PKOdnKQzuDR+FSjh7SGtJwpgVpfZBRKlQ=,bb70104152800cbb490c480bead0d2ef24176be9e1304e6701ab161115484863
+github.com/siddontang/go,v0.0.0-20180604090527-bdc77568d726,h1:xT+JlYxNGqyT+XcU8iUrN18JYed2TvG9yN5ULG2jATM=,ef97fabc8a96a758fac273b01dff6be7957ed44c4b6c6a8316f43741329a0049
+github.com/siddontang/go-snappy,v0.0.0-20140704025258-d8f7bb82a96d,h1:qQWKKOvHN7Q9c6GdmUteCef2F9ubxMpxY1IKwpIKz68=,faf83d6459d06f5f4a9acd09e23e284e11792d14de331bd7b87852b18f9cf5c3
+github.com/siddontang/ledisdb,v0.0.0-20190202134119-8ceb77e66a92,h1:qvsJwGToa8rxb42cDRhkbKeX2H5N8BH+s2aUikGt8mI=,dab81c0bdfc62063a340f61dfab19c065d2d10b1245cd56cc04832130a6bbea5
+github.com/siddontang/rdb,v0.0.0-20150307021120-fc89ed2e418d,h1:NVwnfyR3rENtlz62bcrkXME3INVUa4lcdGt+opvxExs=,93bf89960d84b8732e648cb413dced692c1d3d9000997e99826538a5f20b1d82
+github.com/sigurn/crc8,v0.0.0-20160107002456-e55481d6f45c,h1:hk0Jigjfq59yDMgd6bzi22Das5tyxU0CtOkh7a9io84=,12916a0da94e747b99653138a25112e24b082db53bc0d5cffe62214ce3fb884d
+github.com/sigurn/utils,v0.0.0-20190728110027-e1fefb11a144,h1:ccb8W1+mYuZvlpn/mJUMAbsFHTMCpcJBS78AsBQxNcY=,694bb4cbe9dd17447c1e0054ef327eebd9bed8682aa39f5f4d282fb9b1717299
+github.com/sirupsen/logrus,v1.4.2,h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=,9a8e55830261a4b1c9350d7c45db029c8586c0b2d934d1224cde469425031edd
+github.com/skratchdot/open-golang,v0.0.0-20190402232053-79abb63cd66e,h1:VAzdS5Nw68fbf5RZ8RDVlUvPXNU6Z3jtPCK/qvm4FoQ=,242db3338b172ecb58bdf3406b4cafecfa738cfb7b8cd71698d23831aedd94b0
+github.com/skyrings/skyring-common,v0.0.0-20160929130248-d1c0bb1cbd5e,h1:jrZSSgPUDtBeJbGXqgGUeupQH8I+ZvGXfhpIahye2Bc=,d5010d4900d7417c05d4863399e5509e82dfaca9c09c31ac9e5ebdcaf109e833
+github.com/smallnest/libkv-etcdv3-store,v0.0.0-20191101045330-f92940446965,h1:YQtdLz+7JQdKn7f5cG+xSrSbI7X4jObx0Jy6ZzffGew=,b9fb22d7d67e16cd3a1d7c7a5b2faf6c35c690ae1c3bcf70dbf77813db7dc563
+github.com/smallnest/rpcx,v0.0.0-20191101045608-2a801682117a,h1:Fzp1HLqyYg8koEELgwfSEUgkE6QPvrN9qCkHZ8tikFY=,0d2255c9ffc429e32936dbb9e51c79bbf2b76a7dec95c5d9dc1668053d5642bc
+github.com/smallnest/valkeyrie,v0.0.0-20191030064635-54a884e4b303,h1:NDOAHb1sE8pYWd0Dge8W6bGQ63FHfa0/QjClXG2hrgw=,b846d492aaf7053115b2e143b7c7696299b852ec670d261bd78b5cd996eacde3
+github.com/smartystreets/assertions,v1.0.1,h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w=,2e3d9f61f68cdf7b48653582640ef88744c1a3bdd4257ac68f621579a2f807dd
+github.com/smartystreets/go-aws-auth,v0.0.0-20180515143844-0c1422d1fdb9,h1:hp2CYQUINdZMHdvTdXtPOY2ainKl4IoMcpAXEf2xj3Q=,d9441cfbef2c680269ced67f8e1d99af9cf649e11a7f133a5b0685be0277ca7d
+github.com/smartystreets/goconvey,v0.0.0-20190731233626-505e41936337,h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=,fd90be078397b45806e4dfaca367235aef6d6133871c8a6cc6d3d579280d8d03
+github.com/smartystreets/gunit,v1.0.0,h1:RyPDUFcJbvtXlhJPk7v+wnxZRY2EUokhEYl2EJOPToI=,36cf43529cfadeb297ce1537c7d0fca8373a95936806121ce7ce0bf653e959ee
+github.com/smola/gocompat,v0.2.0,h1:6b1oIMlUXIpz//VKEDzPVBK8KG7beVwmHIUEBIs/Pns=,7812934f407beeab20aa289b0056234ae6637b30b301ebf97a5d7a9fd8e665fc
+github.com/snikch/goodman,v0.0.0-20171125024755-10e37e294daa,h1:YJfZp12Z3AFhSBeXOlv4BO55RMwPn2NoQeDsrdWnBtY=,ab939c56cb7afcff213aef4568f40c9ddeae30166e34a2fa7f5718a47227c2e1
+github.com/softlayer/softlayer-go,v0.0.0-20180806151055-260589d94c7d,h1:bVQRCxQvfjNUeRqaY/uT0tFuvuFY0ulgnczuR684Xic=,63ad57bc2d4c27db3dcab7cf545a075bb4d7ea66aba57c284c07a2c938220f8c
+github.com/soheilhy/cmux,v0.1.4,h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=,6d6cadade0e186f84b5f8e7ddf8f4256601b21e49b0ca49fd003a7e570ae1885
+github.com/songtianyi/rrframework,v0.0.0-20180901111106-4caefe307b3f,h1:o3QHyJEW1U+8oyEZeaXFcYqdhhiZjrs25/8AZmsWjiU=,b1cf04474a48de1ed7ae535ae4a2d5b17a0df4ce0d3b953c5268f42ee34cb17d
+github.com/soniakeys/unit,v1.0.0,h1:UMIgu6dxDQaK6tYaQV6dJn5oovB6035KRxCS0O7Jiec=,565c64fe777e1140d82422e9b8d29ce8de82d7916e50dac2f7591d2c6f2d79e7
+github.com/sony/gobreaker,v0.4.1,h1:oMnRNZXX5j85zso6xCPRNPtmAycat+WcoKbklScLDgQ=,eab9bf8f98b16b051d7d13c4f5c70d6d1039347e380e0a12cb9ff6e33200d784
+github.com/sourcegraph/annotate,v0.0.0-20160123013949-f4cad6c6324d,h1:yKm7XZV6j9Ev6lojP2XaIshpT4ymkqhMeSghO5Ps00E=,2a58cbf2485b2e97e49d7c3e83e81385d1418bfbab2b846dabec041a3d402b3e
+github.com/sourcegraph/syntaxhighlight,v0.0.0-20170531221838-bd320f5d308e,h1:qpG93cPwA5f7s/ZPBJnGOYQNK/vKsaDaseuKT5Asee8=,c0e6323ed7a5dcddcdd7686f2d7c68dff44a8ecbfd6818db3bdb33a7af422792
+github.com/spacemonkeygo/errors,v0.0.0-20171212215202-9064522e9fd1,h1:xHQewZjohU9/wUsyC99navCjQDNHtTgUOM/J1jAbzfw=,b360a46f9534dd46d2b2c27c84ba8bbe3942832e74aa4ceb16acaa6ba30620be
+github.com/spacemonkeygo/monotime,v0.0.0-20180824235756-e3f48a95f98a,h1:8+cCjxhToanKmxLIbuyBNe2EnpgwhiivsIaRJstDRFA=,4a55e556811ab93b23b46907b354e53fc553eb93314cf0b524933f37ac1437f8
+github.com/spacemonkeygo/openssl,v0.0.0-20181017203307-c2dcc5cca94a,h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek=,23031c8d37bbaa5aace338eed65af68c7d72bf134d7d0e09c963ed4974c56e58
+github.com/spacemonkeygo/spacelog,v0.0.0-20180420211403-2296661a0572,h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=,91eb98e80c44d42e6f3ff7ddf84f825d20eb55669452d752fb8ed3adeb723be7
+github.com/spaolacci/murmur3,v1.1.0,h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=,60bd43ada88cc70823b31fd678a8b906d48631b47145300544d45219ee6a17bc
+github.com/spf13/afero,v1.2.2,h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=,81d51799397212c9adb2cea6cf3a96a2b50f1baff8aff7bd410128a84f2a9e73
+github.com/spf13/cast,v1.3.0,h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=,001ed519a3ec007e76e639f72bd9560be70497d499acbf1a32ccf32dc4647d91
+github.com/spf13/cobra,v0.0.5,h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=,6c6739f11d69fa1e5b60ba1e04529f355f8a30e1aa2b137ba26260de8fa7a647
+github.com/spf13/fsync,v0.9.0,h1:f9CEt3DOB2mnHxZaftmEOFWjABEvKM/xpf3cUwJrGOY=,d470c73c6e821d6c8f47ce05be3360f4d686d9079dd5af1585420c73e4725c56
+github.com/spf13/jwalterweatherman,v1.1.0,h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=,43cc5f056caf66dc8225dca36637bfc18509521b103a69ca76fbc2b6519194a3
+github.com/spf13/pflag,v1.0.5,h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=,fc6e704f2f6a84ddcdce6de0404e5340fa20c8676181bf5d381b17888107ba84
+github.com/spf13/viper,v1.5.0,h1:GpsTwfsQ27oS/Aha/6d1oD7tpKIqWnOA6tgOX9HHkt4=,7f3513d0a1186b765937c788f0ac751076067b7a0abc82420171b6f262787ac5
+github.com/src-d/envconfig,v1.0.0,h1:/AJi6DtjFhZKNx3OB2qMsq7y4yT5//AeSZIe7rk+PX8=,c694b1440b6969dfd4ebcba669faea8a05bdc7791ac78dcfbe29f153b0a8f0cd
+github.com/src-d/gcfg,v1.4.0,h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=,2aa52404cbeec89c0a976d333448d1a4a6e113f03e000a715ce9006c84eb2e32
+github.com/srwiley/oksvg,v0.0.0-20190829233741-58e08c8fe40e,h1:LJUrNHytcMXWKxnULIHPe5SCb1jDpO9o672VB1x2EuQ=,e29e85accb2169d2f0f4dc90c22c446c24d244d68e0bbe038ba9df63381916c5
+github.com/srwiley/rasterx,v0.0.0-20181219215540-696f7edb7a7e,h1:FFotfUvew9Eg02LYRl8YybAnm0HCwjjfY5JlOI1oB00=,8a4b0686258a3e1b4f8b3e5f25efbaaefe7919d4e47e89eb36a6779504f8b116
+github.com/ssdb/gossdb,v0.0.0-20180723034631-88f6b59b84ec,h1:q6XVwXmKvCRHRqesF3cSv6lNqqHi0QWOvgDlSohg8UA=,2c20531d93416fa34ee9039308166c869c72c16fff715c73c05a3977157fdc2d
+github.com/ssor/bom,v0.0.0-20170718123548-6386211fdfcf,h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo=,7622ce25bbc5d5376ccb113f267f3d68bf2363963b02d04c053dfbc252f62c4a
+github.com/steakknife/bloomfilter,v0.0.0-20180922174646-6819c0d2a570,h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=,fb001f6df1197d462e7dfdbeded863aebd85bb904da5075117174a027a1b8cb1
+github.com/steakknife/hamming,v0.0.0-20180906055917-c99c65617cd3,h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM=,e42bd1bc7073772613c2b4879110dd5330fded46a8cdf9269ff03cb6a82d1108
+github.com/stellar/go,v0.0.0-20191031165136-ed88b67b723d,h1:0pucQZ9fngYUl/tIGO/H96N3F5NL5ySjM3fuz+XEFSY=,d9d23bd5fc8cae6e65d4bb0d87e3cb582bc684eac1a519ca787b187a175999a5
+github.com/stellar/go-xdr,v0.0.0-20180917104419-0bc96f33a18e,h1:n/hfey8pO+RYMoGXyvyzuw5pdO8IFDoyAL/g5OiCesY=,5122e57a861bd0c38a3a3607f13576a150face8cacf9cafaf24e21e38a104b87
+github.com/stellar/throttled,v2.2.3-0.20190823235211-89d75816f59d+incompatible,h1:jMXXAcz6xTarGDQ4VtVbtERogcmDQw4RaE85Cr9CgoQ=,a89e929d8d8ba24e621c479708378263714861d8fce137085108da9f0cc8805a
+github.com/steveyen/gtreap,v0.0.0-20150807155958-0abe01ef9be2,h1:JNEGSiWg6D3lcBCMCBqN3ELniXujt+0QNHLhNnO0w3s=,64b6a1f094784f1a843a6787bd159a103b9bebd2e85cc09a7e8445cc9e3ffc03
+github.com/streadway/amqp,v0.0.0-20190827072141-edfb9018d271,h1:WhxRHzgeVGETMlmVfqhRn8RIeeNoPr2Czh33I4Zdccw=,66bd109504bf565a4a777c20a8cf6a1c5d05cd87b59baa50da8b6f2b0da4c494
+github.com/stretchr/objx,v0.2.0,h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=,5517d43cfb7e628b9c2c64010b934e346cd24726e3d6eaf02b7f86e10752e968
+github.com/stretchr/testify,v1.4.0,h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=,0400c42ab95389bb4f4577bc09917a040a97f0f4251db2a54a7f6f5e65065b73
+github.com/stripe/stripe-go,v66.1.1+incompatible,h1:D8qUD1rxv+RdXi2qo+IdDELkDevxYUQDfje20bGQPiw=,471de64dbc99da2b83fc1822ff9b4627b1b0738a8e3ee9ffb038510ce84e4baf
+github.com/struCoder/pidusage,v0.1.2,h1:fFPTThlcWFQyizv3xKs5Lyq1lpG5lZ36arEGNhWz2Vs=,6ae03cd6cab9014ca7c0326fc233b27d942556c9753d2da87a93dd0fecbb9986
+github.com/stumble/gorocksdb,v0.0.3,h1:9UU+QA1pqFYJuf9+5p7z1IqdE5k0mma4UAeu2wmX8kA=,8bf18874189196133dabeb8fb7444633a0961e8983f8b2d8588d522d6aa679de
+github.com/subosito/gotenv,v1.2.0,h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=,21474df92536f36de6f91dfbf466995289445cc4e5a5900d9c40ae8776b8b0cf
+github.com/svanharmelen/jsonapi,v0.0.0-20180618144545-0c0828c3f16d,h1:Z4EH+5EffvBEhh37F0C0DnpklTMh00JOkjW5zK3ofBI=,482b13f426a15f3cb64ae5cb1a5fd2f27ca142465a174e24a2cc356812a3ed28
+github.com/swaggo/files,v0.0.0-20190704085106-630677cd5c14,h1:PyYN9JH5jY9j6av01SpfRMb+1DWg/i3MbGOKPxJ2wjM=,e1fe1ffca3a181bede3787e75797345bc69a583a67d8bb10b934f7a140516162
+github.com/swaggo/gin-swagger,v1.2.0,h1:YskZXEiv51fjOMTsXrOetAjrMDfFaXD79PEoQBOe2W0=,7ba6476ca79affa95429821a187b7cb3458305737ac2d1b86340814c3f276f71
+github.com/swaggo/swag,v1.6.3,h1:N+uVPGP4H2hXoss2pt5dctoSUPKKRInr6qcTMOm0usI=,1adbe98538a3f1b5e64fdf08f86cea4502a2c0d0cf1b047a27af6acf764f8c17
+github.com/syndtr/gocapability,v0.0.0-20180916011248-d98352740cb2,h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=,ece41bcca6ca06202649ccee0d2ab62667217ceb70f3a84794c3751c16b75cee
+github.com/syndtr/goleveldb,v1.0.1-0.20190318030020-c3a204f8e965,h1:1oFLiOyVl+W7bnBzGhf7BbIv9loSFQcieWWYIjLqcAw=,b0dbd1bdec73ea70eb1db85322046d202bcbfe901bc821d6a50ffc182c276306
+github.com/tarm/serial,v0.0.0-20180830185346-98f6abe2eb07,h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU=,cd962b3b9ef46158abad455c95ed92f2632cdb9217df2b7690171cc3db507add
+github.com/tatsushid/go-fastping,v0.0.0-20160109021039-d7bb493dee3e,h1:nt2877sKfojlHCTOBXbpWjBkuWKritFaGIfgQwbQUls=,1c25333d4ca05ca13828835e07876c0efdd90a1c32a715527aa722b3c63c2d48
+github.com/tchap/go-patricia,v2.3.0+incompatible,h1:GkY4dP3cEfEASBPPkWd+AmjYxhmDkqO9/zg7R0lSQRs=,19db63cf16ba944ea853c18397e4336342f1e95e4b2cb12127405bb64c67cf73
+github.com/tdewolff/minify,v2.3.6+incompatible,h1:2hw5/9ZvxhWLvBUnHE06gElGYz+Jv9R4Eys0XUzItYo=,8cabb8163bd65e43b42c5842b700d55e2daeae60c82b019007aceb1ae63638d5
+github.com/tdewolff/minify/v2,v2.5.2,h1:If/q1brvT+91oWiWnIMEGuFcwWtpB6AtLTxba78tvMs=,0af37ec252d094917a1ff4178659fe9f4539fdc3dca108bbeb9c0c2f86499eb9
+github.com/tdewolff/parse,v2.3.4+incompatible,h1:x05/cnGwIMf4ceLuDMBOdQ1qGniMoxpP46ghf0Qzh38=,f290dda8150ebdc2b9586f509770a6c82093ac9027329aeb9f3004a0b26de8e9
+github.com/tdewolff/parse/v2,v2.3.9,h1:d8/K6XOLy5JVpLTG9Kx+SxA72rlm5OowFmVSVgtOlmM=,5f517cbecd071b97ed822e8f88f96ba7d8b5a8accc49fc515298210ac088e7ef
+github.com/tdewolff/test,v1.0.4,h1:ih38SXuQJ32Hng5EtSW32xqEsVeMnPp6nNNRPhBBDE8=,807205136d8f39bb7533d10b72932a183f15b45c385cd5464ae9d06e4af43337
+github.com/tealeg/xlsx,v1.0.5,h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=,ff32f4336aed03df7c9cb7a4df9f1f42a1c64fe5d17c34566159511943d24bde
+github.com/tecbot/gorocksdb,v0.0.0-20181010114359-8752a9433481,h1:HOxvxvnntLiPn123Fk+twfUhCQdMDaqmb0cclArW0T0=,26c0e94162340c7b4d1da3ee4c71ca03f9d6638711cf440d6835e1a8f07e4fb4
+github.com/technoweenie/multipartstreamer,v1.0.1,h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=,5a9aff85522275b125767b746869d24f4e2f776d5031631bf6e29641d99344dc
+github.com/tedsuo/ifrit,v0.0.0-20191009134036-9a97d0632f00,h1:mujcChM89zOHwgZBBNr5WZ77mBXP1yR+gLThGCYZgAg=,1c502a5584dfbce25ff99c1a5689e2d106a138989e4a03249221ca4818674098
+github.com/tedsuo/rata,v1.0.0,h1:Sf9aZrYy6ElSTncjnGkyC2yuVvz5YJetBIUKJ4CmeKE=,f6745fd8ef8ee098410b31b1219def2c4e86c337ba6ff1319f086419b928f134
+github.com/temoto/robotstxt,v1.1.1,h1:Gh8RCs8ouX3hRSxxK7B1mO5RFByQ4CmJZDwgom++JaA=,c37f16f826a27512b7ae683ed32be5124a0252d1c7a8c4a00fd4e27d01c563d4
+github.com/templexxx/cpufeat,v0.0.0-20180724012125-cef66df7f161,h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU=,c29bd644943d69b238da1936593421373d2db675a0fce54090d1c8b7eab7397b
+github.com/templexxx/xor,v0.0.0-20181023030647-4e92f724b73b,h1:mnG1fcsIB1d/3vbkBak2MM0u+vhGhlQwpeimUi7QncM=,578ab42785a74d1a5dd3e65bf0979138b3a98bf877de4767b8eae5701a2342e1
+github.com/tencentcloud/tencentcloud-sdk-go,v3.0.71+incompatible,h1:9sIWfe6ZC7xoSlshYWNGicPqomK7N+CsHMa1YFWBCWU=,33a9526ee0244844270e532358a22616d821cc7f8f0638e33c60f722f84c5e42
+github.com/tendermint/btcd,v0.1.1,h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s=,1967aa3cbabfb9e9780c0371a5359cc21ed77e5673b64e7dd5b234e838c82e62
+github.com/tendermint/crypto,v0.0.0-20180820045704-3764759f34a5,h1:u8i49c+BxloX3XQ55cvzFNXplizZP/q00i+IlttUjAU=,49ad334d452402d59757d3a415602f57bd7b66962d6115262f5c7413112d61bb
+github.com/tendermint/ed25519,v0.0.0-20171027050219-d8387025d2b9,h1:zccWau0P8FELSb4HTDJ88hRo+WVNMbIbg27rFqDrhCE=,7c4a6e57c787df7c6e990c35bb31df3f4a5aa89f45c3b3df4a25dfb70c01f7e3
+github.com/tendermint/go-amino,v0.15.1,h1:D2uk35eT4iTsvJd9jWIetzthE5C0/k2QmMFkCN+4JgQ=,e91cde0d10d5a8ea6ab726fbab02ef737ba52f47e207cf675440f625153d3205
+github.com/tendermint/iavl,v0.12.2,h1:Ls5p5VINCM1HRT9g5Vvs2zmDOCU/CCIvIHzd/pZ8P0E=,a56011434929c4003fd735cbef8147e8aca3d241983c5fa7a006f5753e123020
+github.com/tendermint/tendermint,v0.32.7,h1:Szu5Fm1L3pvn3t4uQxPAcP+7ndZEQKgLie/yokM56rU=,495a31dc762d79a689ce00cdd52f66b6b4071fc2b738ce4b3d1c2a9447389ecc
+github.com/tendermint/tm-db,v0.2.0,h1:rJxgdqn6fIiVJZy4zLpY1qVlyD0TU6vhkT4kEf71TQQ=,99b7c1a00ee483b97e73126a25327b75da9a5bc6e34bf9fb1ecd6b83832fe13e
+github.com/tent/http-link-go,v0.0.0-20130702225549-ac974c61c2f9,h1:/Bsw4C+DEdqPjt8vAqaC9LAqpAQnaCQQqmolqq3S1T4=,a4fe19fdbf8fbc30fe866e2cbb8761ee179f4a83bda63a0a6d30a651f3700ec2
+github.com/terraform-providers/terraform-provider-openstack,v1.15.0,h1:adpjqej+F8BAX9dHmuPF47sUIkgifeqBu6p7iCsyj0Y=,9c7419845747d0c4e3a9432f50788d8adec7ed6fca93ec9ffbf99e8c8b1cf0c3
+github.com/testcontainers/testcontainers-go,v0.0.8,h1:71E+jJpE9dSgydCfn5aWESVM7+l8giw/DBWaTy35TTU=,bceec8989a3beb9f14802c13c496c9158509f6b4cee6f855c0fb06b01e7da150
+github.com/tevino/abool,v0.0.0-20170917061928-9b9efcf221b5,h1:hNna6Fi0eP1f2sMBe/rJicDmaHmoXGe1Ta84FPYHLuE=,924168edd97fe37d4af80990d69c1d11d06b8e9236ebae65b9b68ba0261baaf1
+github.com/tgulacsi/picago,v0.0.0-20171229130838-9e1ac2306c70,h1:elvpffAnrLcWnsunBkvTwxr+Q79bPSNT1+2/pOFkCj0=,68e0cb434718215eae670723ce9327ec16d462a6403007ca22b6af71346445c5
+github.com/thanos-io/thanos,v0.3.2,h1:gNWga6sqv5kZp6ltaA7oUIFj+tTG2ohq4W9SQ4YU6ds=,99491658e5ed421ba1563818dd7c01034803fa1e0c4e5d7c28b06f3d3ed2a570
+github.com/theplant/cldr,v0.0.0-20190423050709-9f76f7ce4ee8,h1:di0cR5qqo2DllBMwmP75kZpUX6dAXhsn1O2dshQfMaA=,214ea2cc1e66f278928d0b5b1b40a3e12358b7a71e0fa6d6ea606c4d687e8eef
+github.com/theupdateframework/notary,v0.6.1,h1:7wshjstgS9x9F5LuB1L5mBI2xNMObWqjz+cjWoom6l0=,f921dfb3d54538118367d9018d9abacc3c0c026951442140d669443977180b66
+github.com/thoj/go-ircevent,v0.0.0-20180816043103-14f3614f28c3,h1:389FrrKIAlxqQMTscCQ7VH3JAVuxb/pe53v2LBiA7z8=,32edd7a9e219bdff36d2aac0c6c5f3ac982c2daf4869e6e0718e917efb23b3de
+github.com/tiancaiamao/appdash,v0.0.0-20181126055449-889f96f722a2,h1:mbAskLJ0oJfDRtkanvQPiooDH8HvJ2FBh+iKT/OmiQQ=,a9961e6079339aec983f97fdb39d5d7258bf8d2031da68482e58e17b27a93a78
+github.com/tidwall/gjson,v1.3.3,h1:wM/XREVc9c0LbRLcNMgVcGpI16r0pbbTJpltR4jJjh0=,17da724ffc86cfb3132bd9c7ac3eb860ca43a2748be519a59aa50b436c147bc6
+github.com/tidwall/match,v1.0.1,h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=,a1b9d52b9a4c7574f46068665279522f2084be26bac71594630786f6ee9a70f2
+github.com/tidwall/pretty,v1.0.0,h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=,3b25a1a0fe7688989326aaa1ca1c74c972b30152ef2a756fbf2d217a827fc07d
+github.com/tidwall/sjson,v1.0.4,h1:UcdIRXff12Lpnu3OLtZvnc03g4vH2suXDXhBwBqmzYg=,cb47595016d45d72e6ee0f5585a86247aaeb93d9efa74e07676d32f60e8a7398
+github.com/tildeleb/cuckoo,v0.0.0-20190627040100-71059d5a2b62,h1:rXSNik45VDd1hfRLUAZwDLCY0FWvn2KlCeXjbd1yAI0=,f81f44544ec771ab630ddd5d65f4735ba2acc7619e41ccbc4bfad2473c21dc2f
+github.com/timewasted/linode,v0.0.0-20160829202747-37e84520dcf7,h1:CpHxIaZzVy26GqJn8ptRyto8fuoYOd1v0fXm9bG3wQ8=,9a3190b3751964a3d47449265d48e2d3a76b23c66a7cb402cc9bdf3d732d82b4
+github.com/tinylib/msgp,v1.1.0,h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=,61bd58489c555b30abffbe1175565b6f8460583349118e9ee12025fd17b67ea4
+github.com/tj/assert,v0.0.0-20171129193455-018094318fb0,h1:Rw8kxzWo1mr6FSaYXjQELRe88y2KdfynXdnK72rdjtA=,59a81d1883aac9635ac15d8a6a6e0630cf0a4122328116f921289dab840374b7
+github.com/tj/cobra,v0.0.0-20160702192511-5e2db986a612,h1:eiUtRvCN5HSnOg9AyX5z5od5VWy/ukyJ2oTboInm9MM=,493ac2ac61730652fcdd0b9b4c1e0c63855666df7fcaa02821b63982a5a7ccdf
+github.com/tj/go-elastic,v0.0.0-20171221160941-36157cbbebc2,h1:eGaGNxrtoZf/mBURsnNQKDR7u50Klgcf2eFDQEnc8Bc=,a0df933432e9c7ec276cbc0edbb941375726cf5a39c663aafe0e945f9ba3079f
+github.com/tj/go-kinesis,v0.0.0-20171128231115-08b17f58cb1b,h1:m74UWYy+HBs+jMFR9mdZU6shPewugMyH5+GV6LNgW8w=,0885f4631d33a20b5447ebbe12a0d23eb5ea3394de4bbc849cfe54ad19cadb2a
+github.com/tj/go-spin,v1.1.0,h1:lhdWZsvImxvZ3q1C5OIB7d72DuOwP4O2NdBg9PyzNds=,060d09c35b1db5992747cde71ccbdaefe596ada06a6fe146e0ef10dc67d817dd
+github.com/tj/pflag,v0.0.0-20160702191705-e367e44eec04,h1:RAPJe7XUQhTjVUKvYegzhXnWkJd/1daXdoiXjvkSURU=,2156357bb17b30ccb893b8f7013168c85c1eb265b7156aca845d06fb35805257
+github.com/tjfoc/gmsm,v1.0.1,h1:R11HlqhXkDospckjZEihx9SW/2VW0RgdwrykyWMFOQU=,f8fe3c4d02f0dc90fd873278957d57c4c45f1c53b1fee3969216b67844efabb1
+github.com/tmc/grpc-websocket-proxy,v0.0.0-20190109142713-0ad062ec5ee5,h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=,dadf62266d259ffb6aa1d707892b97fa36c3f39df5cae99f54d3ef7682995376
+github.com/tomnomnom/linkheader,v0.0.0-20180905144013-02ca5825eb80,h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y=,558504ea96d4312be0fe5faa6de13fb6abd8f1b2ac154123c67b623a5f219cdb
+github.com/toqueteos/webbrowser,v1.2.0,h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=,1227d3ebeab16d8232a304a10b087984a96ad30f7439b6687bab2f5747d308cf
+github.com/transip/gotransip,v0.0.0-20190812104329-6d8d9179b66f,h1:clyOmELPZd2LuFEyuo1mP6RXpbAW75PwD+RfDj4kBm0=,38b593cbdeb59e64d042533c1ce6196d89662de3282373de0d3c0749fe4c4856
+github.com/trivago/tgo,v1.0.5,h1:ihzy8zFF/LPsd8oxsjYOE8CmyOTNViyFCy0EaFreUIk=,06dc60662735374365cd525e2f4f4d1580f348125546e1f3e0d92d2deca4fa9a
+github.com/tstranex/u2f,v1.0.0,h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ=,325e3db32035ce38a5981bfaa35fb6d9b5cb4b960cfa0285b92448d21d29f379
+github.com/tsuru/config,v0.0.0-20180418191556-87403ee7da02,h1:mHuZ6JOixltE9fJmS+W1xLi4t/uDuR6Nl7w/e4uj0+I=,0255268934770d67b9d101a030ed7ed578938e346a279a273ab3983b0eee53fb
+github.com/ttacon/chalk,v0.0.0-20160626202418-22c06c80ed31,h1:OXcKh35JaYsGMRzpvFkLv/MEyPuL49CThT1pZ8aSml4=,325521131515e4840e0083bc62cd9553da0b8d2480820f7e92ca89ae324f4c23
+github.com/tus/tusd,v1.0.1,h1:jb0SDf8zCUvlWv5SuHalOuRn684aW6WIvhfWRHC/XB8=,9a91d59123262b9bb1c43d39588a26d7560513b9e3c18254cd321890e8975083
+github.com/tv42/httpunix,v0.0.0-20150427012821-b75d8614f926,h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8=,8246ebc82e0d9d3142f5aeb50d4fcd67f3f435fb5464120c356a4e5d57ef4aa0
+github.com/twinj/uuid,v1.0.0,h1:fzz7COZnDrXGTAOHGuUGYd6sG+JMq+AoE7+Jlu0przk=,842c314d6d2ef9cb95b0f3f1b4cf998715680e836cfab8c2a7f75e351765a345
+github.com/twitchtv/twirp,v5.8.0+incompatible,h1:DTfGS9u/jHbo34cBB+qhzVHRaAq+tRois71j8pvjQ5M=,a4137792083eedd9ac04e88918d8952a841120b11e71161d2d444065b8e65d79
+github.com/tyler-smith/go-bip39,v1.0.2,h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=,6173ded455fa17cddd889bf3bc123be2343a09aeb60f83e2b63823dd9ce94e09
+github.com/tylerb/graceful,v1.2.15,h1:B0x01Y8fsJpogzZTkDg6BDi6eMf03s01lEKGdrv83oA=,770bd36defb9463ebe8b190f508e47c37bbb6bedf23a32c675066f8edbd7aa8d
+github.com/u-root/dhcp4,v0.0.0-20190206235119-03363dc71ec8,h1:F9cRXeXZ95CzG7352mm+yfgloHFrjpr1L+CQFiCH/iU=,1db09816d65071cfc5dbf25d5dbf11b2b48c3442495d30777cc0714bb4cf4163
+github.com/u-root/u-root,v6.0.0+incompatible,h1:YqPGmRoRyYmeg17KIWFRSyVq6LX5T6GSzawyA6wG6EE=,f3ec29d4b285e50d7b3116e121caca0d722535346a0ddf189d4c7d8e7e0a07d3
+github.com/uber-go/atomic,v1.4.0,h1:yOuPqEq4ovnhEjpHmfFwsqBXDYbQeT6Nb0bwD6XnD5o=,f380292d46ebec89bf53939e4d7d19d617327cbcdf2978e30e6c39bc77df5e73
+github.com/uber/jaeger-client-go,v2.19.0+incompatible,h1:pbwbYfHUoaase0oPQOdZ1GcaUjImYGimUXSQ/+8+Z8Q=,d4928d51ce4440c825df67b4a54f851ead075701e67ece4b07fbc5c5857c091c
+github.com/uber/jaeger-lib,v2.2.0+incompatible,h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw=,496f63f6df32c28ceb6574959c70969da2b609abc8f9f3b3a709466f862054bf
+github.com/uber/tchannel-go,v1.16.0,h1:B7dirDs15/vJJYDeoHpv3xaEUjuRZ38Rvt1qq9g7pSo=,64a37a5e89dd111ab943d94a1670f9addc0d2d41d34d630c95b0a756df916e01
+github.com/ucloud/ucloud-sdk-go,v0.8.7,h1:BmXOb5RivI0Uu4oZRpjI6SQ9/y7n/H9wxTGR1txIE8o=,d94766624c6f676880de354d4ed5c62c9ee7755c3d59cdf106ac0f5a070c0ece
+github.com/ugorji/go,v1.1.7,h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=,d02959e71c59b273d5b099697c058426941a862feef66c191c63e2934db7a2ff
+github.com/ugorji/go/codec,v1.1.7,h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=,8d482061c55b4c4fbf78de9fbf98a8d1b295f5904769679c73a2dc0b06a1a102
+github.com/ulikunitz/xz,v0.5.6,h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8=,19ebb331e7ae7a542ed58597d13ab703fc423acf93a1e3c4db86476b0322049a
+github.com/unixpickle/anyvec,v0.0.0-20170908190750-59aa66ba0472,h1:eVBSKiY98Zth6cEYVzeu0CYagakYqbSWgpWqjZFiUvI=,4159f95762f7a99ee540397e78c7a60da788e6775ad9eca7fc1bd07d332a88f1
+github.com/unixpickle/autofunc,v0.0.0-20170112172612-f27a3f82164a,h1:ZUrHljv3rPkFyTYzUmBH8gBFjDwCIHc4a2DdPCWRjl0=,b39c092ab522c2ca3e8889dfbff281223628c08590b361242e72cc29015da9df
+github.com/unixpickle/essentials,v0.0.0-20180916162721-ae02bc395f1d,h1:mRwAxGRBEFcoKSWDoX5CROMJo6xmXBh4rNqOmyhpRi0=,7aa26b2cbcbac91669e88903f1e05b7696b32a6d8194d66c0fe7d93c613c2f5f
+github.com/unixpickle/num-analysis,v0.0.0-20161229165253-c45203c63047,h1:gipJz9DZGU3fgBjoaiNg+5CG9UdE7MmlBvSwNp1ulnY=,c1dac9bfeb72d39bb0b445f0f0b2af61753e5b11ff66e69bc196886189b7d50a
+github.com/unixpickle/serializer,v0.0.0-20170723202158-c6c092dc55bb,h1:kdurEYFZ2P58xnfWtmxKWkVtFPyK80BMIaJ2zW5uskY=,2cbf6cce1b2a57307c2c675a283ce9b46adcb9d18c3a9317d3ee20772175ae40
+github.com/unknwon/com,v1.0.1,h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=,f6264780f210f130a0edeafe4ffb0753c64b5168771f2d6cd1613999a7b79cd1
+github.com/unrolled/render,v1.0.1,h1:VDDnQQVfBMsOsp3VaCJszSO0nkBIVEYoPWeRThk9spY=,5b0ace5c3798f8989322a32b75c3eeabce7f6568533f808065cacf92425dd867
+github.com/unrolled/secure,v0.0.0-20190103195806-76e6d4e9b90c,h1:ZY4dowVsuIAQtXXwKJ9ezfonDQ2YT7pcXRpPF2iAy3Y=,1aba4f13fe4199198f9b59bbfd337773d049bad06f68360483a5f4c5431bdce4
+github.com/urfave/cli,v1.22.1,h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=,116fc1fba7db091617cd47c2b83c78d22489deeaf8390a6d3509da7fc9217d57
+github.com/urfave/cli/v2,v2.0.0-alpha.2,h1:2OVOKijPPhkA1cJA5SABACE8TT3Cwx9T0N6VtI8LJSI=,57250f97530fcb6fef7abc87cde3fbaf11ea45830adf98e3f1c986e2674e3b5f
+github.com/urfave/negroni,v1.0.0,h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=,7b50615961d34d748866565b8885edd7013e33812acdbaed47502d7cc73a4bbd
+github.com/valyala/bytebufferpool,v1.0.0,h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=,7f59f32c568539afee9a21a665a4156962b019beaac8404e26ba37af056b4f1e
+github.com/valyala/fasthttp,v1.6.0,h1:uWF8lgKmeaIewWVPwi4GRq2P6+R46IgYZdxWtM+GtEY=,b15a953ed5395599871097c94977d21c026205e6ca7ad6e340cd595096d5840e
+github.com/valyala/fastrand,v1.0.0,h1:LUKT9aKer2dVQNUi3waewTbKV+7H17kvWFNKs2ObdkI=,ed2166483141b4f3d59ee07975a5d91990e4c17f36c919565b8063c0cb02f7ed
+github.com/valyala/fasttemplate,v1.0.1,h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=,b4d9f77c6c15a0404952925ad59b759102c0ff48426b6fc88d6bfd347fe243b8
+github.com/valyala/tcplisten,v0.0.0-20161114210144-ceec8f93295a,h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc=,07066d5b879a94d6bc1feed20ad4003c62865975dd1f4c062673178be406206a
+github.com/vbatts/tar-split,v0.11.1,h1:0Odu65rhcZ3JZaPHxl7tCI3V/C/Q9Zf82UFravl02dE=,73136db95ff35c2547c49be43727aa3f67da2d8837e1475954db910b41b1fa18
+github.com/veandco/go-sdl2,v0.3.3,h1:4/TirgB2MQ7oww3pM3Yfgf1YbChMlAQAmiCPe5koK0I=,d19e162daa2a6cc72569eb052adfd3d757fd069ee461a64803e9e8f2e9bb87a7
+github.com/vektah/dataloaden,v0.2.1-0.20190515034641-a19b9a6e7c9e,h1:+w0Zm/9gaWpEAyDlU1eKOuk5twTjAjuevXqcJJw8hrg=,92fe72fa4962bb2f375fae83f7a44a804e398ec08818f7d018724e0a23394ae3
+github.com/vektah/gqlparser,v1.1.2,h1:ZsyLGn7/7jDNI+y4SEhI4yAxRChlv15pUHMjijT+e68=,cdd0119855b98641e7af60dce5b2848b31f8ef03dfcf097c06912309b86fc97c
+github.com/viant/assertly,v0.4.8,h1:5x1GzBaRteIwTr5RAGFVG14uNeRFxVNbXPWrK2qAgpc=,253a5e53bb09bf94be7131d5034a6ba19c6eb1f9b8c7fa66182d577bd7b2d6cd
+github.com/viant/toolbox,v0.24.0,h1:6TteTDQ68CjgcCe8wH3D3ZhUQQOJXMTbj/D9rkk2a1k=,d6773a06b59de043eff2003bb97567056a1910eb0fd514f5503873b8f23309f4
+github.com/vimeo/go-util,v1.2.0,h1:YHzwOnM+V2tc6r67K9fXpYqUiRwXp0TgFKuyj+A5bsg=,85e52371bcf8299d47d8242546bc06e9e0c9c555b719008096889cd081a69173
+github.com/vincent-petithory/dataurl,v0.0.0-20160330182126-9a301d65acbb,h1:lyL3z7vYwTWXf4/bI+A01+cCSnfhKIBhy+SQ46Z/ml8=,5d5fa46ce0f88ba0734f52d0b0bcaa8a427770ef13cd1bfd7995e4d2a8439abb
+github.com/vishvananda/netlink,v1.0.0,h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM=,6fb7184280eb1321e1857171862bdb624eae29876496f1cb56932fbc0064020f
+github.com/vishvananda/netns,v0.0.0-20190625233234-7109fa855b0f,h1:nBX3nTcmxEtHSERBJaIo1Qa26VwRaopnZmfDQUXsF4I=,a99a67e03a35e1d02d1a17900185a1c38c513a79b2b325ad826553dc078a90de
+github.com/vivint/infectious,v0.0.0-20190108171102-2455b059135b,h1:dLkqBELopfQNhe8S9ucnSf+HhiUCgK/hPIjVG0f9GlY=,f5d948bf34ac58786ad20df4fd6e99f990f72458dd2825558bf2e3c871f3f37a
+github.com/vmihailenco/msgpack,v4.0.4+incompatible,h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=,918f7dd7883105b9c55728c704a3bc54c80568b2b09583890b51508c03391356
+github.com/vmware/govmomi,v0.21.0,h1:jc8uMuxpcV2xMAA/cnEDlnsIjvqcMra5Y8onh/U3VuY=,75ca40f34da851e95d7e63685adbaf1ec5c7f659fb0b47096c85da44f098c4a3
+github.com/vmware/vic,v1.5.4,h1:y546pkye0aes2j2h2n6fWz++v8WxMZTLFl1mLOMzqYQ=,2a6f0c20be8acb3b467c78d3de18009ccd0ab2429a997266089d14341e43115c
+github.com/vmware/vmw-guestinfo,v0.0.0-20170707015358-25eff159a728,h1:sH9mEk+flyDxiUa5BuPiuhDETMbzrt9A20I2wktMvRQ=,29c73ba44ac315461640797d6ebfda2d906c28dbe21c20656c6e5fa1f515f220
+github.com/vulcand/oxy,v1.0.0,h1:7vL5/pjDFzHGbtBEhmlHITUi6KLH4xXTDF33/wrdRKw=,148843b55ed01813f8920aab70a799aa10cfdccc0bbd55e270cde78e1ad23b88
+github.com/vulcand/predicate,v1.1.0,h1:Gq/uWopa4rx/tnZu2opOSBqHK63Yqlou/SzrbwdJiNg=,3dd716f2436651429ce7f5fdd59fa1a9944ab4d57fdbae5fef00ef01baf7c4be
+github.com/vultr/govultr,v0.1.4,h1:UnNMixYFVO0p80itc8PcweoVENyo1PasfvwKhoasR9U=,7281fa718c076b84610b155fb0dec34503ea1ae5f2930cc714ed7772e475bb08
+github.com/warpfork/go-wish,v0.0.0-20190328234359-8b3e70f8e830,h1:8kxMKmKzXXL4Ru1nyhvdms/JjWt+3YLpvRb/bAjO/y0=,77a9eefa3edf38cb90eba443f282bd73ffcb6f1b87aebe8f891d8c8b38124d95
+github.com/weaveworks/common,v0.0.0-20190917143411-a2b2a6303c33,h1:UAh7j96ZXQID3shhQsrtfJsrQ2uO3tyRxCuXvh+kipw=,e1ceacd5b24c6414ae664f4b09e295dc25e48d3a1dcd5100d8c98dd405a0d162
+github.com/weaveworks/mesh,v0.0.0-20191031093817-8e3db2fe8f47,h1:RUdrWPah1Xu+efIGqN0YGTv7gQeyR5qwBq9uL4HloKw=,05f5d769f7ff6af1c098f0e42983227d6a86f5d8d1f8453cb0566450cad49358
+github.com/wellington/go-libsass,v0.9.3-0.20181113175235-c63644206701,h1:9vG9vvVNVupO4Y7uwFkRgIMNe9rdaJMCINDe8vhAhLo=,2ae95ed360950fab28eff3bedf1c1a6f5f81b73078000d3a0bd67443d38df87f
+github.com/wendal/errors,v0.0.0-20130201093226-f66c77a7882b,h1:0Ve0/CCjiAiyKddUMUn3RwIGlq2iTW4GuVzyoKBYO/8=,f7722558c5c450fa02e800ce7bf4d0bc1d2a0e1696d3fc50ff1489bcd02ff3b3
+github.com/weppos/publicsuffix-go,v0.5.0,h1:rutRtjBJViU/YjcI5d80t4JAVvDltS6bciJg2K1HrLU=,bd8365c8501b307a1fbd62501bc3332ff97721bef51921a99e67a3f8b96318fc
+github.com/whyrusleeping/cbor-gen,v0.0.0-20190910031516-c1cbffdb01bb,h1:8yBVx6dgk1GfkiWOQ+RbeDDBLCOZxOtmZ949O2uj5H4=,9d5ab8362eaffa07bc2700d9a9e967c1ecf394e3233a6e7141efb48970bfd4e5
+github.com/whyrusleeping/chunker,v0.0.0-20181014151217-fe64bd25879f,h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E=,b28fdb03b69be216c423967e9dee2481aa10c3e39c71d3bfc8911940dadb26a9
+github.com/whyrusleeping/go-keyspace,v0.0.0-20160322163242-5b898ac5add1,h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=,9416f8227e6c516294b9b938fcf2347bebe2cdab4377454150ba60dcd86c2990
+github.com/whyrusleeping/go-logging,v0.0.0-20170515211332-0457bb6b88fc,h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo=,125b1a836936436354791583be42ae19f7c04a636b5c0c96135645d52aaa72ea
+github.com/whyrusleeping/go-notifier,v0.0.0-20170827234753-097c5d47330f,h1:M/lL30eFZTKnomXY6huvM6G0+gVquFNf6mxghaWlFUg=,08dddb594554c3b35791893207e66dd3c04e4da24d0e0df001bb185f97dec6cc
+github.com/whyrusleeping/go-smux-multiplex,v3.0.16+incompatible,h1:iqksILj8STw03EJQe7Laj4ubnw+ojOyik18cd5vPL1o=,e16e3da58e283e71955b21725c384d180a2999bc2a50cb0490b5e2f7a74b5fc6
+github.com/whyrusleeping/go-smux-multistream,v2.0.2+incompatible,h1:BdYHctE9HJZLquG9tpTdwWcbG4FaX6tVKPGjCGgiVxo=,9a783c4a1b69f6002ac4e0af684f4d5c4d360b7107fbbdde48faf38f7e23e998
+github.com/whyrusleeping/go-smux-yamux,v2.0.9+incompatible,h1:nVkExQ7pYlN9e45LcqTCOiDD0904fjtm0flnHZGbXkw=,3f44f41fc7b133085bba08d52e7615e9a8eb92f55fde6a07d3cd7804117e9985
+github.com/whyrusleeping/mafmt,v1.2.8,h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA=,e5d5783d2bc35f7c23f2034fd52c5750ad0590773115c10b4e15360575322c69
+github.com/whyrusleeping/mdns,v0.0.0-20180901202407-ef14215e6b30,h1:nMCC9Pwz1pxfC1Y6mYncdk+kq8d5aLx0Q+/gyZGE44M=,fc2e4d2365ba40d52d03126ea490e712762b4ad398c8d6adb2a1a08699a10eb1
+github.com/whyrusleeping/multiaddr-filter,v0.0.0-20160516205228-e903e4adabd7,h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds=,14e8963464dab0f6277f596985be5ea419bc3bae8bf4f4f139cce456e1815faf
+github.com/whyrusleeping/timecache,v0.0.0-20160911033111-cfcb2f1abfee,h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow=,c33dfc5ac935582261bf5ddbab31bb07febc471a9c26eb3e1a895eddd574d3e8
+github.com/whyrusleeping/yamux,v1.1.5,h1:4CK3aUUJQu0qpKZv5gEWJjNOQtdbdDhVVS6PJ+HimdE=,658f9e704cbe1cac295ed34471bb096a4d2713f69ffbb8140fbf50b8ff6420e0
+github.com/willf/bitset,v1.1.9,h1:GBtFynGY9ZWZmEC9sWuu41/7VBXPFCOAbCbqTflOg9c=,ddd687772ccfd6774e55e7e9d9e71dab86d85a64b98ce1d864d9661f5b0767e4
+github.com/x-cray/logrus-prefixed-formatter,v0.5.2,h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=,00719eeb4f9eadb9431dd9f763fa4013dc52b37a8803a973c6d0c1ce8281e14b
+github.com/xanzy/go-cloudstack,v0.0.0-20190526095453-42f262b63ed0,h1:NJrcIkdzq0C3I8ypAZwFE9RHtGbfp+mJvqIcoFATZuk=,34b46eae351e4916015ce2a43ed501403937e4079cf69dae98a9544bfeec8092
+github.com/xanzy/go-gitlab,v0.21.0,h1:Ru55sR4TBoDNsAKwCOpzeaGtbiWj7xTksVmzBJbLu6c=,12ae6fa35c19fffc31d1fa2891f386875caac8077d19f3f09f49b5e2e51b1755
+github.com/xanzy/ssh-agent,v0.2.1,h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=,7011c1771f8ad9b65795f8a85113e4518c9a2c7493029c4c988bc802b63d9e28
+github.com/xdg/scram,v0.0.0-20180814205039-7eeb5667e42c,h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=,33884d438b686676ceaa2a439634a108f7fe763ce974342d2aa811c22b34112c
+github.com/xdg/stringprep,v1.0.0,h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=,2b262e4e8e9655100c98e2b7e75b517e3e83e2155818174c63ea09d3cce22721
+github.com/xeipuuv/gojsonpointer,v0.0.0-20180127040702-4e3ac2762d5f,h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=,5b1a4bcc8e003f214c92b3fa52959d9eb0e3af1c0c529efa55815db951146e48
+github.com/xeipuuv/gojsonreference,v0.0.0-20180127040603-bd5ef7bd5415,h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=,7ec98f4df894413f4dc58c8df330ca8b24ff425b05a8e1074c3028c99f7e45e7
+github.com/xeipuuv/gojsonschema,v1.2.0,h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=,55c8ce068257aa0d263aad7470113dafcd50f955ee754fc853c2fdcd31ad096f
+github.com/xenolf/lego,v2.7.2+incompatible,h1:aGxxYqhnQLQ71HsvEAjJVw6ao14APwPpRk0mpFroPXk=,25c2495e4fc2f5fea8c70b442add86c049f2f8810235e1ee94f29d8e0267ad2c
+github.com/xeonx/timeago,v1.0.0-rc4,h1:9rRzv48GlJC0vm+iBpLcWAr8YbETyN9Vij+7h2ammz4=,b06f4ede554b35387394827ca0350b628a72228a8002653817826991867e1fdd
+github.com/xi2/xz,v0.0.0-20171230120015-48954b6210f8,h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=,1ffe8f24af5118966084d41eca2c9bee7a831a07deb4356e4d707d208da22e8e
+github.com/xiang90/probing,v0.0.0-20190116061207-43a291ad63a2,h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=,437bdc666239fda4581b592b068001f08269c68c70699a721bff9334412d4181
+github.com/xlab/treeprint,v0.0.0-20181112141820-a009c3971eca,h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=,d14ebea967caa835f25e4c3980c60719e07f0e36375b74dc48928613fca5b2ff
+github.com/xo/dburl,v0.0.0-20191005012637-293c3298d6c0,h1:6DtWz8hNS4qbq0OCRPhdBMG9E2qKTSDKlwnP3dmZvuA=,1fb150cf2144a4b7a571360af52d9b22dfe53e2ba9ab3e56584fdb0eb282d315
+github.com/xordataexchange/crypt,v0.0.3-0.20170626215501-b2862e3d0a77,h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow=,46dc29ef77d77a2bc3e7bd70c94dbaeec0062dd3bd6fcacbaab785c15dcd625b
+github.com/xtaci/kcp-go,v5.4.5+incompatible,h1:CdPonwNu3RKu7HcXSno5r0GXfTViDY2iFV2RDOao/4U=,98e77493d94b33bfec990bd5791d15a09add1a0ba2f3281f26bdc98c1815d9a7
+github.com/xtaci/lossyconn,v0.0.0-20190602105132-8df528c0c9ae,h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=,75cc8c3e14cf812dcc56a1e8cecafd8affd9b2843d39540ab67929f7ce3d1abc
+github.com/xtgo/set,v1.0.0,h1:6BCNBRv3ORNDQ7fyoJXRv+tstJz3m1JVFQErfeZz2pY=,6b70026a5ea66bc0be7efb2247afa53ae970b9535c7a8541795750ef9b640217
+github.com/yalp/jsonpath,v0.0.0-20150812003900-31a79c7593bb,h1:06WAhQa+mYv7BiOk13B/ywyTlkoE/S7uu6TBKU6FHnE=,d2041be5f19a3dbcd4b384dbbf5782cdb96d80ad9c60c8c9b887f2c5170cb25f
+github.com/yandex-cloud/go-genproto,v0.0.0-20190928220815-a36c849d0fc1,h1:GDyRNvsi/tOZj1ssPkk+kocO1djpbmLSpDKg4XeRPy4=,5502c680146902518514935af5ab5b554a80f5ebe2e79d491db3120911f5498d
+github.com/yandex-cloud/go-sdk,v0.0.0-20190916101744-c781afa45829,h1:2FGwbx03GpP1Ulzg/L46tSoKh9t4yg8BhMKQl/Ff1x8=,4b375b871ce7501943a26ba02c348ad4fdf2cb112520513628566a15a98a4796
+github.com/yohcop/openid-go,v0.0.0-20160914080427-2c050d2dae53,h1:HsIQ6yAjfjQ3IxPGrTusxp6Qxn92gNVq2x5CbvQvx3w=,8c4f676193e3aa5ec012e0661d0e552a3e5d5d96086a73901dcfbf0bd4a6d2e9
+github.com/yookoala/realpath,v1.0.0,h1:7OA9pj4FZd+oZDsyvXWQvjn5oBdcHRTV44PpdMSuImQ=,9fe8b06f8efabb7df08608f18edc77d284e04ad06d490af9f55196e4184c339f
+github.com/yosssi/ace,v0.0.5,h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA=,96157dbef72f2f69a900e09b3e58093ee24f7df341ac287bddfb15f8c3f530db
+github.com/yosssi/gmq,v0.0.1,h1:GhlDVaAQoi3Mvjul/qJXXGfL4JBeE0GQwbWp3eIsja8=,d06bbe96ba0e8c3c79bfb0b9191a02a19d8d3d3c181eba62df6d94c0602c784e
+github.com/youtube/vitess,v2.1.1+incompatible,h1:SE+P7DNX/jw5RHFs5CHRhZQjq402EJFCD33JhzQMdDw=,2eb3c516c8b24a72b8cb14f76f39562638acf0cd7fc3858002163d28047607f2
+github.com/yudai/gojsondiff,v0.0.0-20170107030110-7b1b7adf999d,h1:yJIizrfO599ot2kQ6Af1enICnwBD3XoxgX3MrMwot2M=,3f61230fe62a6fe2e93a75264d176bda3f62323063c1e9bfb87c0be31ac5d269
+github.com/yudai/golcs,v0.0.0-20150405163532-d1c525dea8ce,h1:888GrqRxabUce7lj4OaoShPxodm3kXOMpSa85wdYzfY=,ff1f3899e710574a08aaa51051a36c523ecf850180ad0564d55eec611c3cff72
+github.com/yudai/pp,v2.0.1+incompatible,h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI=,ecfda4152182e295f2b21a7b2726e2865a9415fc135a955ce42e039db29e7a20
+github.com/yuin/gopher-lua,v0.0.0-20190514113301-1cd887cd7036,h1:1b6PAtenNyhsmo/NKXVe34h7JEZKva1YB/ne7K7mqKM=,fd157d5d26c336c44837eceef5c6fc4b442a56b25931d4afae3c4080932a7aa7
+github.com/zach-klippenstein/goregen,v0.0.0-20160303162051-795b5e3961ea,h1:CyhwejzVGvZ3Q2PSbQ4NRRYn+ZWv5eS1vlaEusT+bAI=,6f523a11fcb80dca31c3bae99c8c4a59b7e5a4176e36cad0e3f1e64e1b9a7b11
+github.com/zclconf/go-cty,v1.1.0,h1:uJwc9HiBOCpoKIObTQaLR+tsEXx1HBHnOsOOpcdhZgw=,024660decfe11e74a9fab80f1447b79c61e328baf6418629a15c74e183b95e95
+github.com/zclconf/go-cty-yaml,v1.0.1,h1:up11wlgAaDvlAGENcFDnZgkn0qUJurso7k6EpURKNF8=,2502da37ac6d9105b07748c4252f970aa6a7ffc8929b92a0b85abb81b804e9b7
+github.com/zeebo/admission,v0.0.0-20180821192747-f24f2a94a40c,h1:WoYvMZp+keiJz+ZogLAhwsUZvWe81W+mCnpfdgEUOl4=,b62a80509cfa84e697b23dd6b1b314a264e6f68586661ecd84026625f7753cb1
+github.com/zeebo/assert,v1.0.0,h1:qw3LXzO7lbptWIQ6DsemJIUOoaqyKbgY3M8b8yvlaaY=,bb31d428cc59a322975ab6b5757832e62507655f3e2c467a88345b21d7431d98
+github.com/zeebo/errs,v1.2.2,h1:5NFypMTuSdoySVTqlNs1dEoU21QVamMQJxW/Fii5O7g=,d2fa293e275c21bfb413e2968d79036931a55f503d8b62381563ed189b523cd2
+github.com/zeebo/float16,v0.1.0,h1:kRqxv5og6z1emEyz5FpW0/BVHe5VfxEAw6b1ljCZlUc=,ffc6b2a7bce5e37798bc3ac53448b6190039a77f2e7d589779680fbd3cb53a48
+github.com/zeebo/incenc,v0.0.0-20180505221441-0d92902eec54,h1:+cwNE5KJ3pika4HuzmDHkDlK5myo0G9Sv+eO7WWxnUQ=,141b997c5ece8f136f43644f5a2526305563128c4ecce280d9a54ce1ae506ba2
+github.com/zeebo/structs,v1.0.2,h1:kvcd7s2LqXuO9cdV5LqrGHCOAfCBXaZpKCA3jD9SJIc=,0495c69abfeb2ffa0911f4c44ba145d81b04ec76d2311e2eedfc2b3e2efd66c9
+github.com/zenazn/goji,v0.9.0,h1:RSQQAbXGArQ0dIDEq+PI6WqN6if+5KHu6x2Cx/GXLTQ=,0807a255d9d715d18427a6eedd8e4f5a22670b09e5f45fddd229c1ae38da25a9
+github.com/ziutek/mymysql,v1.5.4,h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=,1ea104186e0990a3d97a1e67fcd31177849c975de4abd9399270ab0a04c025de
+github.com/zkfy/cron,v0.0.0-20170309132418-df38d32658d8,h1:jxPemXnLeekMXItoaw4jZtDfe8HmvFmviUm2L5tEBhE=,81a903448f6bc140e07bc4ff70762f0a46e750388f4b92f700d358331b1ca8d5
+github.com/zkfy/go-metrics,v0.0.0-20161128210544-1f30fe9094a5,h1:Rb2qQMbEon+BI3IXGh4eW3u/iTLPA3+Y6kNK+gHO32w=,07f9078cbc233559128dc4ae80d69505dd1a07d47d33135fc8f4969829fd6ee8
+github.com/zkfy/jwt-go,v3.0.0+incompatible,h1:5hZNIkrRRa0mrkRiXoPFdLJWpMDByIZ6VIbX9aWhwmk=,8306a4a65059e17be035dd47f45d83aac503c50c954716c83e481d0b6530aed6
+github.com/zkfy/log,v0.0.0-20180312054228-b2704c3ef896,h1:nktyhX5ycnu+WA489Ei7SUi00bF+LW8TF2N7se5gQ/o=,dd0acb5ccceb2225c89f0f50dc8eea9f1cae0971b731750ea7a1b186c194d9bc
+github.com/zkfy/stompngo,v0.0.0-20170803022748-9378e70ca481,h1:dqbWcJVZJv06ZR7zK8yN9w8oNOHL23eylL4o9Xj9Zn0=,9e643fbfd166421cb186275742bafc663fc350da83e59e9d88c06feb12ec4462
+github.com/zmap/rc2,v0.0.0-20131011165748-24b9757f5521,h1:kKCF7VX/wTmdg2ZjEaqlq99Bjsoiz7vH6sFniF/vI4M=,fd70713ed40c95220e95c7c47f7e15051e8dc909d39253f403bb694f45fbe789
+github.com/zmap/zcertificate,v0.0.0-20180516150559-0e3d58b1bac4,h1:17HHAgFKlLcZsDOjBOUrd5hDihb1ggf+1a5dTbkgkIY=,7dc2c0bedccfdeb9c42ef41ef502f404befa9ef073c35db3b15c99cae6697b41
+github.com/zmap/zcrypto,v0.0.0-20190729165852-9051775e6a2e,h1:mvOa4+/DXStR4ZXOks/UsjeFdn5O5JpLUtzqk9U8xXw=,871979cf16453ddb4db7f153f449af4e346f68b51355c74b5eee832225618ff0
+github.com/zmap/zlint,v0.0.0-20190806154020-fd021b4cfbeb,h1:vxqkjztXSaPVDc8FQCdHTaejm2x747f6yPbnu1h2xkg=,e62f5cd5f434d84f53d336261e3a6e50c8902152ce8f2f5ce918270d6d201cab
+github.com/zondax/hid,v0.9.0,h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8=,9c72a6bdbf03d9465dfdf1ba876eabf5fa923d5bb9e726c9e4a994098dc9bd79
+github.com/zondax/ledger-go,v0.9.0,h1:oTrtFqPFA4VdCPRvqMaN45mQnJxkPc0JxoVZfCoUpjI=,6c6a7e036f9a621ce951939d7d13ae1f0c098f58829307c78f9312e02e78e438
+github.com/zquestz/grab,v0.0.0-20190224022517-abcee96e61b1,h1:1qKTeMTSIEvRIjvVYzgcRp0xVp0eoiRTTiHSncb5gD8=,4decd67f1252df4ee34968cb0cb4e7dc6010302b24ce8edd418f1c2520f1c351
+gitlab.com/NebulousLabs/errors,v0.0.0-20171229012116-7ead97ef90b8,h1:gZfMjx7Jr6N8b7iJO4eUjDsn6xJqoyXg8D+ogdoAfKY=,b355474f1a2ef2722ae450ef6df7209d223188ae413706be122b472fcc053c48
+gitlab.com/NebulousLabs/fastrand,v0.0.0-20181126182046-603482d69e40,h1:dizWJqTWjwyD8KGcMOwgrkqu1JIkofYgKkmDeNE7oAs=,a56acdda993c7a4795028fe38844d54de9b1877d22e8ae09f205e488ce2284bc
+go.bug.st/serial.v1,v0.0.0-20180827123349-5f7892a7bb45,h1:mACY1anK6HNCZtm/DK2Rf2ZPHggVqeB0+7rY9Gl6wyI=,f0ea4cd4c51228f1a3cf14c6b92888169944f267e1ee778909512a4c8ac4762f
+go.cryptoscope.co/luigi,v0.3.4,h1:eDrtCoUL5Vl2Atr5ty2dq0uFbzFCc6Pz1HEqU1e7I1I=,949612e92dcb2fc919e506740f36d0cfe0797c1f85579a98763aad0135a4580a
+go.dedis.ch/fixbuf,v1.0.3,h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs=,dfa737543a5873b14cdfd0eec675c63044b16d3dbe481b2289c758ae4186ae95
+go.dedis.ch/kyber/v3,v3.0.8,h1:qnHzOBaxEO3+ZYuZAfwPTOPzX+F6QMmWGo8YJvENh68=,d69db17bd37bf14c4e508eb84974c3df9a82b8cb30b55ddc3ac0ee2784abcbac
+go.dedis.ch/kyber/v4,v4.0.0-pre1,h1:1f5OPESkyxK6kPaCSV3J9BlpnoysIpbGLNujX9Ov8m4=,d082a41e2178f7e18c088e414e020928794245a9dae41d07da842ebb667a337e
+go.dedis.ch/onet/v3,v3.0.26,h1:wQhVGB+SCdG7B0tbo6ZeZINQKWkU4u9TNMkGBH16EEM=,a41978897a3371f2eaaab5c84c354c95b4fdbd7b8207afa7c79f32b85f857d5d
+go.elastic.co/apm,v1.5.0,h1:arba7i+CVc36Jptww3R1ttW+O10ydvnBtidyd85DLpg=,447a5954db3f7fc61575c83782be0b6d69e453f1e667b0534d3bf5336039238a
+go.elastic.co/apm/module/apmhttp,v1.5.0,h1:sxntP97oENyWWi+6GAwXUo05oEpkwbiarZLqrzLRA4o=,1e6bc42b2e3ab10165036afd95a8a4d910acadce451c0b4e7c998cbb5c06da73
+go.elastic.co/apm/module/apmot,v1.5.0,h1:rPyHRI6Ooqjwny67au6e2eIxLZshqd7bJfAUpdgOw/4=,235fb0c1d0e107ffb7c5056e49226152063ac87ebc657428ea410d5170804d2e
+go.elastic.co/fastjson,v1.0.0,h1:ooXV/ABvf+tBul26jcVViPT3sBir0PvXgibYB1IQQzg=,451e29b2854f9e09c58e3fe4c1b3a72d9b2ee293628ab4c4323e8192af015c6c
+go.etcd.io/bbolt,v1.3.3,h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=,1ea076dbe18dabe78909e1fb7ec2954fc2d58cd72e7730ad69b35248a30049fd
+go.etcd.io/etcd,v3.3.17+incompatible,h1:g8iRku1SID8QAW8cDlV0L/PkZlw63LSiYEHYHoE6j/s=,7bd292878f70e154a061ed6b85fc70502aa270fcf0072340cbde1a0cb35b0d2d
+go.mongodb.org/mongo-driver,v1.1.2,h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA=,6b3141ced32d7a41ebd0539df957b76331fc3efdca22eae68da54d41aad23fed
+go.opencensus.io,v0.22.1,h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50=,b8d9a5fca5e714c4bf66f6497dd905992113cfd6aae948bb7fad5ce987a520ed
+go.starlark.net,v0.0.0-20191021185836-28350e608555,h1:FhmD1D59MmncMfRVTRa889iERZG3jdaKj/1FtOQB1G0=,add124cd355e714f076a385eb3f2ddcfb8ce0c7c8e6611e2e03acc427a4c32bf
+go.uber.org/atomic,v1.5.0,h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=,7e32f8f75b2029aa53399c2cd6e581398ac4e971c17a763980377279ede95c77
+go.uber.org/automaxprocs,v1.2.0,h1:+RUihKM+nmYUoB9w0D0Ov5TJ2PpFO2FgenTxMJiZBZA=,4c7bf41eab5dd7781c69130aa37011427531dee231ffbdc3c9ed4267c06aa93c
+go.uber.org/multierr,v1.3.0,h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=,29b25df332dea2dbfaaa308013fc6d3673ecd3d9ee09c666c69df504533d0714
+go.uber.org/ratelimit,v0.1.0,h1:U2AruXqeTb4Eh9sYQSTrMhH8Cb7M0Ian2ibBOnBcnAw=,78f82854809625c784088b9dec5dfb4810fbbd09c24891b8aaf2c2679212dfd8
+go.uber.org/thriftrw,v1.20.2,h1:0JlCE7dOyWHEQdfDm0MWIbgTn6vXkiMA6LNIe8FQXjw=,148b93f97a6ab865e2dbe0eb09b9f9504248808efc437e20efc1bf9b7896de9a
+go.uber.org/tools,v0.0.0-20190618225709-2cfd321de3ee,h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=,988dba9c5074080240d33d98e8ce511532f728698db7a9a4ac316c02c94030d6
+go.uber.org/zap,v1.12.0,h1:dySoUQPFBGj6xwjmBzageVL8jGi8uxc6bEmJQjA06bw=,d4b304046a3f9443e4abe217889b5b2a4ecef35d52f175bcacf2baff18646595
+go4.org,v0.0.0-20191010144846-132d2879e1e9,h1:zHLoVtbywceo2hE4Wqv8CmIufe7jDERQ2KJHZoSDfCU=,21811f50d48c55047df1d6bf68db778087afe9116f1f32faf79f8ca459d29d89
+gobot.io/x/gobot,v1.14.0,h1:IJv4A9f5/lUz4JQaS37UW8bRVl3lG+jCGUcNmJ2F0vE=,95ad64d1bf33ee46816b2c87edb10d7b3bfe118b6f7026bf4b5f762867d1e776
+gocloud.dev,v0.17.0,h1:UuDiCphYsiNhRNLtgHVL/eZheQeCt00hL3XjDfbt820=,0df8e26a2356735d596e8a3917ec4b69f61fb5e9f6f291b51f6145a51b646a9b
+gocv.io/x/gocv,v0.21.0,h1:dVjagrupZrfCRY0qPEaYWgoNMRpBel6GYDH4mvQOK8Y=,9e1a70258d72b873d9605a2939b38f9e560650472d70b97f5dd0fc2657eaf35f
+golang.org/x/arch,v0.0.0-20191101135251-a0d8588395bd,h1:e1iK2rWppIPlzzqtjXT/p6WR/+ritGZ8xkfL8uDZb0g=,daba41c9150ebf192ce54952d69ef12fe47c5c6250a33c01f0624befea35354e
+golang.org/x/build,v0.0.0-20191031202223-0706ea4fce0c,h1:jjNoDZTS0vmbqBhqD5MPXauZW+kcGyflfDDFBNCPSVI=,a675f674bcee677f1dc9a15ca4d84bb2e842c29d745b165ba3e5423c09367d29
+golang.org/x/crypto,v0.0.0-20191029031824-8986dd9e96cf,h1:fnPsqIDRbCSgumaMCRpoIoF2s4qxv0xSSS0BVZUE/ss=,0a303100f9afba8628988bef45404b23c2e0c6aa73b5ad4ac9259af14a0e53ae
+golang.org/x/exp,v0.0.0-20191030013958-a1ab85dbe136,h1:A1gGSx58LAGVHUUsOf7IiR0u8Xb6W51gRwfDBhkdcaw=,18ff05b39d29a3fd4c7f9071e7013264994ac18f7faa72f66b2f514fcdd141b0
+golang.org/x/image,v0.0.0-20191009234506-e7c1f5e7dbb8,h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=,aebca4c096dac7c20d9024b73bd0b4a87a85f4c6b50aae7615dec504c5f478c8
+golang.org/x/lint,v0.0.0-20190930215403-16217165b5de,h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=,91323fe1a77f13de722a0ce8efc5c5f2da4f26216d858acec64cb23c956fa163
+golang.org/x/mobile,v0.0.0-20191031020345-0945064e013a,h1:CrJ8+QyIm2tcw/zt9Rp/vGFsey+jndL1y5EnFwzgGOg=,5ee0c7eed83b64cc851d6ddb76346413d7c43213ea1241385b588c66e2169854
+golang.org/x/mod,v0.1.0,h1:sfUMP1Gu8qASkorDVjnMuvgJzwFbTZSeXFiGBYAVdl4=,e0d9b32f6f66103f777e8357b5b60f94a486330d46c6c8ea87789dab1a14cefa
+golang.org/x/net,v0.0.0-20191101175033-0deb6923b6d9,h1:DPz9iiH3YoKiKhX/ijjoZvT0VFwK2c6CWYWQ7Zyr8TU=,b07094a5589a436fd98c6700cd5898f2094d9c02f8385f9331a7ace46305c7ae
+golang.org/x/oauth2,v0.0.0-20190604053449-0f29369cfe45,h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=,f72b6c3c2b734ad053fadf5fa2adb2ad23024cfeacd567fec31a751526d1dfe0
+golang.org/x/perf,v0.0.0-20180704124530-6e6d33e29852,h1:xYq6+9AtI+xP3M4r0N1hCkHrInHDBohhquRgx9Kk6gI=,a2c7d02cc94c4ba767b6322f70ddcba4941cb5f60fed1bada3aa7a4d3a8128f1
+golang.org/x/sync,v0.0.0-20190911185100-cd5d95a43a6e,h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=,9c63fe51b0c533b258d3acc30d9319fe78679ce1a051109c9dea3105b93e2eef
+golang.org/x/sys,v0.0.0-20191029155521-f43be2a4598c,h1:S/FtSvpNLtFBgjTqcKsRpsa6aVsI6iztaz1bQd9BJwE=,c5a8efb84e706e4ec1e1fa5cda44d1d571e8b3f46afe165d5e93b90e777a15fc
+golang.org/x/text,v0.3.2,h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=,f755c0e7f4693f170e2f03c161f500b33f82accb8184a38dcfda63fed883f13c
+golang.org/x/time,v0.0.0-20191024005414-555d28b269f0,h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=,e0ca5eceb4840bcc264237408ff8942044e19b503d6e8e5546ed9f7e1f4bf82e
+golang.org/x/tools,v0.0.0-20191101200257-8dbcdeb83d3f,h1:+QO45yvqhfD79HVNFPAgvstYLFye8zA+rd0mHFsGV9s=,c3beb2acb726571e4cca3e922dd1eb037dcb6ef66ca562e9544716a53b6a1026
+golang.org/x/xerrors,v0.0.0-20191011141410-1b5146add898,h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=,5059c7b7e95f139b8c42d9001972fa5fa688b3581ef946c912c1dbc52415ff16
+gomodules.xyz/envconfig,v1.3.0,h1:w1laMNVtP05uOKqmRAY6Vx7HvfPL9yc388gcVtUiI/M=,ae5b4ee26eeb143c16bfb5316eb97e8ff4418bce379ae74e2a0bba367706d69c
+gomodules.xyz/jsonpatch/v2,v2.0.1,h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0=,3c97ac5b7cfa3388f3dc157e20e6ad7b7a5789a4df1d5257a39589cf66edd462
+gonum.org/v1/gonum,v0.6.0,h1:DJy6UzXbahnGUf1ujUNkh/NEtK14qMo2nvlBPs4U5yw=,98857b431471c87facf3cd779eadc5d33760c9edee4b56a8228af4b383b90aa2
+gonum.org/v1/netlib,v0.0.0-20190331212654-76723241ea4e,h1:jRyg0XfpwWlhEV8mDfdNGBeSJM2fuyh9Yjrnd8kF2Ts=,ed4dca5026c9ab5410d23bbe21c089433ca58a19bd2902311c6a91791142a687
+gonum.org/v1/plot,v0.0.0-20191004082913-159cd04f920c,h1:Ssc2Jy4xun3/JMt2asledr/xSPAvX7ZZ7HimX2Gwz1w=,9246b6f7a9299061b31d99e50b2ac2685853dc478a6c2c730fada016c7268ea1
+google.golang.org/api,v0.13.0,h1:Q3Ui3V3/CVinFWFiW39Iw0kMuVrRzYX0wN6OPFp0lTA=,4c853034281c673829b7a7f3e39c62640d01895d20a666f003f855ad5f55ec30
+google.golang.org/appengine,v1.6.5,h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=,24ddb4adf72189738dc8340b28f9493a385515e680eb0bfbffe08951412b6655
+google.golang.org/genproto,v0.0.0-20191028173616-919d9bdd9fe6,h1:UXl+Zk3jqqcbEVV7ace5lrt4YdA4tXiz3f/KbmD29Vo=,cb4eec9cf94aa450efbb0d131cf1484f6334f1e8c1e1475b76c3ab2dea76c72a
+google.golang.org/grpc,v1.24.0,h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s=,eb4433685a85e20f934c2a98e35d104db2d77abe438a242d75d5aae9f78898fb
+google.golang.org/protobuf,v0.0.0-20191101204728-ef19a2a99470,h1:wSgCzfaFwg6Q4Eh+T7XknFfgswhFaeYkEs8t5endA/c=,73a49a6e5fd3330de7364564ab0954146e25ad8bbdff0ea6180f8ace153b0c1b
+gopkg.in/Acconut/lockfile.v1,v1.1.0,h1:c5AMZOxgM1y+Zl8eSbaCENzVYp/LCaWosbQSXzb3FVI=,66e89c98908e2b9295de1a32cdd90f626a2468c256ce6182d6339e6659548e71
+gopkg.in/AlecAivazis/survey.v1,v1.8.7,h1:oBJqtgsyBLg9K5FK9twNUbcPnbCPoh+R9a+7nag3qJM=,c924df9f9d79f015cc619b1ecede52c92618c0ab8d020cd63e2c783f46b3907d
+gopkg.in/DataDog/dd-trace-go.v1,v1.19.0,h1:aFSFd6oDMdvPYiToGqTv7/ERA6QrPhGaXSuueRCaM88=,f8eb14519d62c80eea88fca1daa69b274a0b492aa8b775890424b48d362c32b3
+gopkg.in/Shopify/sarama.v1,v1.18.0,h1:f9aTXuIEFEjVvLG9p+kMSk01dMfFumHsySRk1okTdqU=,beeb8546c4202289f282529630bc3db4452dc5f7eb69c3d8546196470c7d8be3
+gopkg.in/VividCortex/ewma.v1,v1.1.1,h1:tWHEKkKq802K/JT9RiqGCBU5fW3raAPnJGTE9ostZvg=,fe7800182ce944f2b28834d6cf60c620de0cbba1d691d9442f3473baf2a3d50d
+gopkg.in/airbrake/gobrake.v2,v2.0.9,h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=,2db903664908e5a9afafefba94821b9579bbf271e2929c1f0b7b1fdd23f7bbcf
+gopkg.in/alecthomas/gometalinter.v2,v2.0.12,h1:/xBWwtjmOmVxn8FXfIk9noV8m2E2Id9jFfUY/Mh9QAI=,7e6b56f4b985a08d11c1494f9dcc2b595676e787afe7a1caa9c522d41cab9487
+gopkg.in/alecthomas/kingpin.v2,v2.2.6,h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=,638080591aefe7d2642f2575b627d534c692606f02ea54ba89f42db112ba8839
+gopkg.in/alecthomas/kingpin.v3-unstable,v3.0.0-20180810215634-df19058c872c,h1:vTxShRUnK60yd8DZU+f95p1zSLj814+5CuEh7NjF2/Y=,0e35a5bb02770611e4c53c611529b95b96d0bc573f05d10bb43f7441abef2fde
+gopkg.in/alexcesaro/quotedprintable.v3,v3.0.0-20150716171945-2caba252f4dc,h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=,1a310c5e55038937be3e69765276449601ca582f681129f7d9d47e052846cafc
+gopkg.in/asn1-ber.v1,v1.0.0-20181015200546-f715ec2f112d,h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=,fee158570ba9cbfc11156afbe9b9ab0833ab00d0f1a2a2af29a6325984a79903
+gopkg.in/bblfsh/sdk.v1,v1.17.0,h1:Ez/4P0S0Zaq30iZKfiTlhOtqMx6dfQHMTYpqKFvnv4A=,172521b9f2bdd4180751ed5122971c9c37a8c0bca2e0710bc255bc0e5ff8c106
+gopkg.in/bblfsh/sdk.v2,v2.16.4,h1:Ta/kBVRGXf8UOBYDw/ih8mw13/8NND+AdR0JiXBQrOw=,eb7a8a7d08bd80cd0673a6b9c90fa524bda9db24242bd6ef82fb414941c4ef0f
+gopkg.in/bsm/ratelimit.v1,v1.0.0-20160220154919-db14e161995a,h1:stTHdEoWg1pQ8riaP5ROrjS6zy6wewH/Q2iwnLCQUXY=,fea8af18591a0ac50d29c8db124d13a43da6bee7a624c411b7449a99ee87b489
+gopkg.in/bufio.v1,v1.0.0-20140618132640-567b2bfa514e,h1:wGA78yza6bu/mWcc4QfBuIEHEtc06xdiU0X8sY36yUU=,9d63fe986f79edba7fca9bcd3bee0c7dcff7787cd30b43b5f2ae8a59feae512c
+gopkg.in/check.v1,v1.0.0-20190902080502-41f04d3bba15,h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=,004537cb19dbe45954ec1605f331705f6685ccc267eddd4289c1eb27513ab817
+gopkg.in/cheggaaa/pb.v1,v1.0.28,h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk=,39725f9f37aac44dd55bdc9ade65a2d066953a090456298d34203257fc7e8ee9
+gopkg.in/cheggaaa/pb.v2,v2.0.7,h1:beaAg8eacCdMQS9Y7obFEtkY7gQl0uZ6Zayb3ry41VY=,a6ba73f81893f0eca8c0a60c238a705a12bae499a44fe6217a4471687766ef02
+gopkg.in/clog.v1,v1.2.0,h1:BHfwHRNQy497iBNsRBassPixSAxRbn2z5KVkdBFbwxc=,51eb8901943d1cec850b55556a9989e21488a9636ac692d6f7575db057804f3d
+gopkg.in/editorconfig/editorconfig-core-go.v1,v1.3.0,h1:oxOEwvhxLMpWpN+0pb2r9TWrM0DCFBHxbuIlS27tmFg=,b5371885f56b40c03da4fd05006c717fabdfb8ee9ea1ceef4cc5b7caeda35041
+gopkg.in/errgo.v1,v1.0.1,h1:oQFRXzZ7CkBGdm1XZm/EbQYaYNNEElNBOd09M6cqNso=,32f45f7cfacfc04ae9e7e8c9fc55a53812554799da7c2bd17b043068b5fd5171
+gopkg.in/errgo.v2,v2.1.0,h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=,6b8954819a20ec52982a206fd3eb94629ff53c5790aa77534e6d8daf7de01bee
+gopkg.in/fatih/color.v1,v1.7.0,h1:bYGjb+HezBM6j/QmgBfgm1adxHpzzrss6bj4r9ROppk=,ed20c58de8c575144c2cc1c924121ee1a240e0621c77918231547b576d46d3ce
+gopkg.in/fatih/set.v0,v0.2.1,h1:Xvyyp7LXu34P0ROhCyfXkmQCAoOUKb1E2JS9I7SE5CY=,d743141e21d20f6d5ae8e784dd4644c0947948103b63404a878b0298f14a9e62
+gopkg.in/fsnotify.v1,v1.4.7,h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=,ce003d540f42b3c0a3dec385deb387b255b536b25ea4438baa65b89458b28f75
+gopkg.in/fsnotify/fsnotify.v1,v1.4.7,h1:XNNYLJHt73EyYiCZi6+xjupS9CpvmiDgjPTAjrBlQbo=,6f74f844c970ff3059d1639c8a850d9ba7029dd059b5d9a305f87bd307c05491
+gopkg.in/gavv/httpexpect.v1,v1.0.0-20170111145843-40724cf1e4a0,h1:r5ptJ1tBxVAeqw4CrYWhXIMr0SybY3CDHuIbCg5CFVw=,4fe4a5e78a26ac5b60fc16405d3a5918d83cd645d36bd9dc0d558824136930b6
+gopkg.in/gcfg.v1,v1.2.3,h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs=,06cdad29610507bafb35e2e73d64fd7aa6c5c2ce1e5feff30a622af5475bca3b
+gopkg.in/gemnasium/logrus-airbrake-hook.v2,v2.1.2,h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=,ce35c69d2a1f49d8672447bced4833c02cc7af036aa9df94d5a6a0f5d871cccd
+gopkg.in/go-playground/assert.v1,v1.2.1,h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=,11da2f608d82304df2384a2301e0155fe72e8414e1a17776f1966c3a4c403bc4
+gopkg.in/go-playground/validator.v8,v8.18.2,h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ=,fea7482c7122c2573d964b7d294a78f2162fa206ccd4b808d0c82f3d87b4d159
+gopkg.in/go-playground/validator.v9,v9.30.0,h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss=,f4769db84ddc2db880bc190a5420762ef45f80ebbce678b622c4fa82b422b890
+gopkg.in/gobwas/glob.v0,v0.2.3,h1:uLMy+ys6BqRCutdUNyWLlmEnd7VULqh1nsxxV1kj0qQ=,3a5fe045be1ff9b47c5e21a9f97bdefaada31463f365503d6b176b76e18a0257
+gopkg.in/gographics/imagick.v3,v3.2.0,h1:eUwlkCw2fa20OGu47G39Im8c50S9n/CVkh8PwtOKExA=,99695d22cf7d5609887609cc9dc63ca1031b5a3238c26f6b779f32e39d572a01
+gopkg.in/gomail.v2,v2.0.0-20160411212932-81ebce5c23df,h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=,08b3372836aef3a403b0a01e6867a3a2252a07f65c28e0d33fe9c4b1b3ac517a
+gopkg.in/gorp.v1,v1.7.2,h1:j3DWlAyGVv8whO7AcIWznQ2Yj7yJkn34B8s63GViAAw=,eaad3325e8b5358d5d54a1ca8b1e6aa19d16968a1f11f3dc45671588d914ef25
+gopkg.in/guregu/null.v3,v3.4.0,h1:AOpMtZ85uElRhQjEDsFx21BkXqFPwA7uoJukd4KErIs=,b38d62a816c5905933396a02eb11e23cbe2c17f8837563cc10794274e5af7e6e
+gopkg.in/h2non/gentleman.v2,v2.0.3,h1:exsUPKJDFwNjJykboVj8+BKPWMNOxR/AmPL3f7Hutwo=,7a71dc2dd74e413832782e4478f85cc0617aed125e078e308b46207f34d6a500
+gopkg.in/h2non/gock.v1,v1.0.15,h1:SzLqcIlb/fDfg7UvukMpNcWsu7sI5tWwL+KCATZqks0=,c6a3d33e638b56ddd050c1dc6c1c6c8e9007c70cacfcc29e778fcf421f1fc029
+gopkg.in/httprequest.v1,v1.2.0,h1:YTGV1oXzaoKI6oPzQ0knoIPcrrVzeRG3amkoxoP7Xng=,3960019870090d0de3fca818633111186d46a908b4bcac6d87e5f08e7fb58770
+gopkg.in/inconshreveable/log15.v2,v2.0.0-20180818164646-67afb5ed74ec,h1:RlWgLqCMMIYYEVcAR5MDsuHlVkaIPDAF+5Dehzg8L5A=,799307ed46ca30ca0ac2dc0332f3673814b8ff6cc1ee905a462ccfd438e8e695
+gopkg.in/inf.v0,v0.9.1,h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=,08abac18c95cc43b725d4925f63309398d618beab68b4669659b61255e5374a0
+gopkg.in/ini.v1,v1.49.0,h1:MW0aLMiezbm/Ray0gJJ+nQFE2uOC9EpK2p5zPN3NqpM=,579074067ceacbf11e938940d65647094da4f23f627645b5c58218bf05c060f0
+gopkg.in/jarcoal/httpmock.v1,v1.0.0-20181117152235-275e9df93516,h1:H6trpavCIuipdInWrab8l34Mf+GGVfphniHostMdMaQ=,5b896c9e5e44146260a066533409c1b86268458301a7155624ef27f784e5d94a
+gopkg.in/jcmturner/aescts.v1,v1.0.1,h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hrEw=,8bfd83c7204032fb16946202d5d643bd9a7e618005bd39578f29030a7d51dcf9
+gopkg.in/jcmturner/dnsutils.v1,v1.0.1,h1:cIuC1OLRGZrld+16ZJvvZxVJeKPsvd5eUIvxfoN5hSM=,4fb8b6a5471cb6dda1d0aabd1e01e4d54cb5ee83c395849916392b19153f5203
+gopkg.in/jcmturner/goidentity.v3,v3.0.0,h1:1duIyWiTaYvVx3YX2CYtpJbUFd7/UuPYCfgXtQ3VTbI=,1be44bee93d9080ce89f40827c57e8a396b7c801e2d19a1f5446a4325afa755e
+gopkg.in/jcmturner/gokrb5.v7,v7.2.3,h1:hHMV/yKPwMnJhPuPx7pH2Uw/3Qyf+thJYlisUc44010=,3eec5b25adb89633174beb9798d8092e91ff4eed146a4b4cb950dd02414bd75e
+gopkg.in/jcmturner/rpc.v1,v1.1.0,h1:QHIUxTX1ISuAv9dD2wJ9HWQVuWDX/Zc0PfeC2tjc4rU=,83d897b60ecb5a66d25232b775ed04c182ca8e02431f351b3768d4d2876d07ae
+gopkg.in/jmcvetta/napping.v3,v3.2.0,h1:NpSZLAL6VgiyhdqaOkxwVtHXOLrQJZ6fFOMQgp7G8PQ=,887358529a8cd287b6a8232b43cc48636463fa266bac5ba48328cb0609d1dcb6
+gopkg.in/juju/charm.v6,v6.0.0-20191031115626-f595bfd8a049,h1:+isWLR3tDZyDacru13gHH0ooIuuDB28kuZJjSc8kOqU=,8d404b146f31d35148015de3f5bd4d25260f0a4b9f22a540a9167864d9e5d082
+gopkg.in/juju/charmrepo.v3,v3.0.1,h1:mm7/CwCczsO7JYHlYkw4iCUYR7X8upEOaY5bYj7eUkw=,8f673109a6d98e4abe4ef612f85dea26bdbd7de5c66b6722c546a08aefb548fc
+gopkg.in/juju/environschema.v1,v1.0.0,h1:51vT1bzbP9fntQ0I9ECSlku2p19Szj/N2beZFeIH2kM=,46ae8efc5a450745fea959dc8532d2a013aa741ab7193d3cea8b0735f09c6e8a
+gopkg.in/juju/names.v2,v2.0.0-20190813004204-e057c73bd1be,h1:xDxN+Fe8olIH8sTqvFJBMsuflBYzeHVeYC4Iz97+f5M=,72ac554c125260751aadf6d41eb82d85de22ef8bff1d59c6602e9e0f5b84a28c
+gopkg.in/juju/worker.v1,v1.0.0-20191018043616-19a698a7150f,h1:UAHa7z4EdrOcMN+9p5P+ojJshcIC34vwi0hCmEL6Qf8=,2e0da8053029ca9da961f8e6f1037a9d7ba12623e5c16fc5f88bf1a724c5dd23
+gopkg.in/karalabe/cookiejar.v2,v2.0.0-20150724131613-8dcd6a7f4951,h1:DMTcQRFbEH62YPRWwOI647s2e5mHda3oBPMHfrLs2bw=,07aae15601f54a5806705d218e313794118d54d9dda7addc1bf4bda4332dfc16
+gopkg.in/kothar/go-backblaze.v0,v0.0.0-20190520213052-702d4e7eb465,h1:DKgyTtKkmpZZesLue2fz/LxEhzBDUWg4N8u/BVRJqlA=,215300ce3726c40f51ee43c41a27c204441e756c8cb4f4b76b1a4dd08f509eef
+gopkg.in/ldap.v2,v2.5.1,h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU=,4fd426691e674164a701ef3ec3548596574f95447cde1fa331018f7d73f8399b
+gopkg.in/ldap.v3,v3.0.2,h1:R6RBtabK6e1GO0eQKtkyOFbAHO73QesLzI2w2DZ6b9w=,f79d1cb87a0a6d571e671c2028409056d65e6bfa7d3d0563ded0edbe8ff0998e
+gopkg.in/macaron.v1,v1.3.4,h1:HvIscOwxhFhx3swWM/979wh2QMYyuXrNmrF9l+j3HZs=,f9aca15b099dada4382e47898516d500876aae45d36895314cde86700636c05c
+gopkg.in/macaroon-bakery.v2,v2.1.0,h1:9Jw/+9XHBSutkaeVpWhDx38IcSNLJwWUICkOK98DHls=,0a12f46df7290b131ee74ec6a4d4760170192920a091939aa2d7a39a4d0fb310
+gopkg.in/macaroon-bakery.v2-unstable,v2.0.0-20171026135619-38b77b89a624,h1:FIOL4YpoNbXH6K+LnOoAEMa/1ebliK7B9mj5NuJHmiA=,51476e40e03bd1f64fd3cdf936d1cde4b8c1395884af9376ff65755041c247aa
+gopkg.in/macaroon.v2,v2.1.0,h1:HZcsjBCzq9t0eBPMKqTN/uSN6JOm78ZJ2INbqcBQOUI=,ae47a93d20ce5c053eafc9d6a76c01b2b06784f9886137dc73a99302928046eb
+gopkg.in/macaroon.v2-unstable,v2.0.0-20180319203259-5c9beabe0e9e,h1:yPxshueS06kvTVlsymSbHvk6VQ1WhX1Ou3hCqqWBp/s=,e09a1f8268d65e3dc28da85c75e78f15f1f742d1dcd31cce427fd885b1962bc4
+gopkg.in/mail.v2,v2.0.0-20180731213649-a0242b2233b4,h1:a3llQg4+Czqaf+QH4diHuHiKv4j1abMwuRXwaRNHTPU=,d7d60701b95fd7f62d3f83bc026f42c0fa69c3f16cc445d2b20497c9dd182ff6
+gopkg.in/mattes/migrate.v1,v1.3.2,h1:tWus4MPMhDY/htX+NCvASiQVRU2pj4Jyj4T8AIv6vUw=,c50f590108871c25d55631addd6bc267f311830d4306ff4d36a6feaad0b23255
+gopkg.in/mattn/go-colorable.v0,v0.1.0,h1:WYuADWvfvYC07fm8ygYB3LMcsc5CunpxfMGKawHkAos=,337a25f7f87a87097e5fb853313c1fac3d3126ed0eb9bb88511d52ba9a0eb4e0
+gopkg.in/mattn/go-isatty.v0,v0.0.4,h1:NtS1rQGQr4IaFWBGz4Cz4BhB///gyys4gDVtKA7hIsc=,18500935e08e5b74487537b8b78a30778a5b2304a138f53aa8758b86266773ff
+gopkg.in/mattn/go-runewidth.v0,v0.0.4,h1:r0P71TnzQDlNIcizCqvPSSANoFa3WVGtcNJf3TWurcY=,e0307a435e39658f761b7526dda9149e7664b7250958494c1a4eebd14884b82d
+gopkg.in/mcuadros/go-syslog.v2,v2.2.1,h1:60g8zx1BijSVSgLTzLCW9UC4/+i1Ih9jJ1DR5Tgp9vE=,1f444e24504b6a21c0d204441a84336ab1240f77a1280b60e48f68ea1b99da7b
+gopkg.in/mgo.v2,v2.0.0-20190816093944-a6b53ec6cb22,h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=,14edbec0d97107b0e0980b66166400f8a4c3844b03bd3240fc57be2b82734b16
+gopkg.in/natefinch/lumberjack.v2,v2.0.0,h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=,8c268e36660d6ce36af808d74b9be80207c05463679703e93d857e954c637aaa
+gopkg.in/neurosnap/sentences.v1,v1.0.6,h1:v7ElyP020iEZQONyLld3fHILHWOPs+ntzuQTNPkul8E=,e3df38d6fc6097f9d1d76ee13e24fec69103c43248ca6a7f3ade2afec5e85bdd
+gopkg.in/ns1/ns1-go.v2,v2.0.0-20190730140822-b51389932cbc,h1:GAcf+t0o8gdJAdSFYdE9wChu4bIyguMVqz0RHiFL5VY=,c51d0889ff5eb72df2f9e4adc28e9f3602e6eb567c3824bebb3c7d315a60710a
+gopkg.in/olivere/elastic.v2,v2.0.61,h1:7cpl3MW8ysa4GYFBXklpo5mspe4NK0rpZTdyZ+QcD4U=,0a20d84f6003850343937ef79179cabe99feef9b038c281fd65ec32ec6c7e85c
+gopkg.in/olivere/elastic.v5,v5.0.82,h1:QH7ere4lvOAWnnOd0VLJ54W8LzExZszoGIRijnb1h2Y=,3c66a7606b226d19f61651b3ad58aecda3155edc802029bd21cd4b8724bd0c9f
+gopkg.in/ory-am/dockertest.v3,v3.3.4,h1:oen8RiwxVNxtQ1pRoV4e4jqh6UjNsOuIZ1NXns6jdcw=,73b01a1d025d30c8f11def182179b873410eae72f7b2fd9f9394b0fcf4683c93
+gopkg.in/redis.v2,v2.3.2,h1:GPVIIB/JnL1wvfULefy3qXmPu1nfNu2d0yA09FHgwfs=,abe2fa39afa36f8186ee287bcf82f9f4bc083aa35d17dd82a2ccbf5850ecdde8
+gopkg.in/redis.v3,v3.6.4,h1:u7XgPH1rWwsdZnR+azldXC6x9qDU2luydOIeU/l52fE=,749ef3e08eb4eda43969f88135040ae4517b450b27dbd48aefb9bf5e72465621
+gopkg.in/redis.v4,v4.2.4,h1:y3XbwQAiHwgNLUng56mgWYK39vsPqo8sT84XTEcxjr0=,6403d2b45edf2804bfd07b6d697184fc97377168589ad43ad19b2433e1dcee34
+gopkg.in/redis.v5,v5.2.9,h1:MNZYOLPomQzZMfpN3ZtD1uyJ2IDonTTlxYiV/pEApiw=,3c30e42670d1ef5f0b33876928b3bd5693ef3b5be1df6b2710d48c2667ca7133
+gopkg.in/resty.v1,v1.12.0,h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI=,43487bb0bb40626d16502b1fe9e719cf751e7a5b4e4233276971873e7863d3cf
+gopkg.in/robfig/cron.v2,v2.0.0-20150107220207-be2e0b0deed5,h1:E846t8CnR+lv5nE+VuiKTDG/v1U2stad0QzddfJC7kY=,b25da9b8747e664334044e581d1a8fb700237239e7f182fd226d6296e6180bc0
+gopkg.in/satori/go.uuid.v1,v1.2.0,h1:AH9uksa7bGe9rluapecRKBCpZvxaBEyu0RepitcD0Hw=,794cefc3062e09b17f4300eb6b02622ac348af9d368341ff71a655a15884547f
+gopkg.in/sourcemap.v1,v1.0.5,h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=,05b5f382bfa60212f444c7207168e9eb0c722e26b57a688123cb8bbf234de692
+gopkg.in/spacemonkeygo/monkit.v2,v2.0.0-20190623001553-09813957f0a8,h1:nyw4hxw2zz4S0EHqr5nQfA3zGbMFJDRJlQPM4PCb7O4=,4a8e607c4f16b32bb9ee380627716979b19ac3df74ca2a4f80aefbaf0b411784
+gopkg.in/square/go-jose.v2,v2.4.0,h1:0kXPskUMGAXXWJlP05ktEMOV0vmzFQUWw6d+aZJQU8A=,d00c4af5a633ab9cf7645b68f6fa389c8f0d9ffebc486742c7a5292280cae84b
+gopkg.in/src-d/go-billy.v4,v4.3.2,h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=,c49871e1d08bba07b2261626b929096b6dc5c839e781adfc24fcc410067cc2bf
+gopkg.in/src-d/go-cli.v0,v0.0.0-20181105080154-d492247bbc0d,h1:mXa4inJUuWOoA4uEROxtJ3VMELMlVkIxIfcR0HBekAM=,86042ffc0c8492845917453682c5bdba46beb2f0c067b61e495a92b9a8621076
+gopkg.in/src-d/go-errors.v1,v1.0.0,h1:cooGdZnCjYbeS1zb1s6pVAAimTdKceRrpn7aKOnNIfc=,f7d9f00c057d4b49bc6e57167561a7fb508ebb113a1946cb2b6f71dac5b14cfb
+gopkg.in/src-d/go-git-fixtures.v3,v3.5.0,h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg=,282dc6474c5ecf62c1169d04ad1f6d75e6058922897b4709a16a1007a5f22eb7
+gopkg.in/src-d/go-git.v4,v4.13.1,h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=,13364fe60f2316a179e912fb4eb6c576e2aabd67e8d390651a155e85c69146d2
+gopkg.in/src-d/go-log.v1,v1.0.1,h1:heWvX7J6qbGWbeFS/aRmiy1eYaT+QMV6wNvHDyMjQV4=,48f6c8a7bdc5436d296f388cd5d40ffb9c749e1e4ab1e455984efc61008fd5d7
+gopkg.in/stack.v0,v0.0.0-20141108040640-9b43fcefddd0,h1:lMH45EKqD8Nf6LwoF+43YOKjOAEEHQRVgDyG8RCV4MU=,a88c4cb4af34bb5c4dd69d0c771829331be7416d2f18d58ff599126f7b291984
+gopkg.in/stretchr/testify.v1,v1.2.2,h1:yhQC6Uy5CqibAIlk1wlusa/MJ3iAN49/BsR/dCCKz3M=,0126e73e5f2ce5687dec597bb276e11dc4031dbdf199e68de735bc67bf808149
+gopkg.in/telegram-bot-api.v3,v3.0.0,h1:Y6QmqOMwRKv5NUdlvzEBtEZChjsrqdTS6O858cvuCww=,03c58e32567a5cc4ec631cc226ecc99dd1113a7a98bab4778b02cde073ab5ed4
+gopkg.in/telegram-bot-api.v4,v4.6.4,h1:hpHWhzn4jTCsAJZZ2loNKfy2QWyPDRJVl3aTFXeMW8g=,01a91b240fb416bf83bcaaa07133cafac28fd8eb8f0f251f6a616beec88c92ac
+gopkg.in/testfixtures.v2,v2.5.0,h1:N08B7l2GzFQenyYbzqthDnKAA+cmb17iAZhhFxr7JHw=,05baac4af6e2855d296a5c045b27deb1b33d0a04cd0df96f029927f0742765a3
+gopkg.in/tomb.v1,v1.0.0-20141024135613-dd632973f1e7,h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=,34898dc0e38ba7a792ab74a3e0fa113116313fd9142ffb444b011fd392762186
+gopkg.in/tomb.v2,v2.0.0-20161208151619-d5d1b5820637,h1:yiW+nvdHb9LVqSHQBXfZCieqV4fzYhNBql77zY0ykqs=,15d93d96e1e8b2d8daf7b9e57a2a9193c0e676a2c6b63d9325bf34b53e93db00
+gopkg.in/tylerb/graceful.v1,v1.2.15,h1:1JmOyhKqAyX3BgTXMI84LwT6FOJ4tP2N9e2kwTCM0nQ=,0a8639cfe62508438ebf2cae721468b64d8cd2992fc0f80439c83c718f4608e0
+gopkg.in/urfave/cli.v1,v1.20.0,h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=,413704688402027dc0f51666bac42152eb1668a73fa0e33858c3d2123c0592e5
+gopkg.in/warnings.v0,v0.1.2,h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=,c412b1f704c1e8ba59b6cfdb1072f8be847c03f77d6507c692913d6d9454e51c
+gopkg.in/yaml.v1,v1.0.0-20140924161607-9f9df34309c0,h1:POO/ycCATvegFmVuPpQzZFJ+pGZeX22Ufu6fibxDVjU=,7abff7973fdab7386de5a1e9e197d8dc50d41ded9d24ff914685900caa0eb742
+gopkg.in/yaml.v2,v2.2.4,h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=,815be785649ae218b51efd8e40b3b75de8f9b57dd43162386ffe3e76709f2a5d
+gorgonia.org/tensor,v0.9.2,h1:bVTWB68apbLfdrAlz5Ev3daGhfOhKuPkVFacMSNzpHs=,17562e7c1c6477b8b530d6236ab9a61228edbabe01c1cfb9ba23286c2394ba4c
+gorgonia.org/vecf32,v0.9.0,h1:PClazic1r+JVJ1dEzRXgeiVl4g1/Hf/w+wUSqnco1Xg=,618df2e604236a2d143958a3571f9939c8264ab2aaae7d8c71b897b728240a23
+gorgonia.org/vecf64,v0.9.0,h1:bgZDP5x0OzBF64PjMGC3EvTdOoMEcmfAh1VCUnZFm1A=,f57695832a12a6f1fbcc04cdaa267ed01fb6b8105f518590d64b2c63b9ac4c61
+gotest.tools,v2.2.0+incompatible,h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=,55fab831b2660201183b54d742602563d4e17e7125ee75788a309a4f6cb7285e
+grpc.go4.org,v0.0.0-20170609214715-11d0a25b4919,h1:tmXTu+dfa+d9Evp8NpJdgOy6+rt8/x4yG7qPBrtNfLY=,58b5c3cccf3e765d0f42918d458cddcd03fc28ff5d701790783677513a8446e3
+h12.io/socks,v1.0.0,h1:oiFI7YXv4h/0kBNcmAb5EkkoFJgYsOF88EQjMBxjitc=,3bf83125284ccabf811aa238954b442e39f53e3e068d4ddb6bf679ba2be28bbe
+honnef.co/go/js/dom,v0.0.0-20190526011328-ebc4cf92d81f,h1:b3Q9PqH+5NYHfIjNUEN+f8lYvBh9A25AX+kPh8dpYmc=,a65720d9c0339450c8818226693a85986549fb156ee4df65913682c350bd4d60
+honnef.co/go/js/util,v0.0.0-20150216223935-96b8dd9d1621,h1:QBApQyt1KyR3SvDWU8sHcIXeWTSCUamO7xQopvwuLWI=,db5638addc7638cc5cf2245cb9bcb19cf04a5912120330560149b54b4575ae50
+honnef.co/go/js/xhr,v0.0.0-20150307031022-00e3346113ae,h1:2dIKMawnBWvHzZrS8STyu/KdhYIOpnKQpp1WZm+K7TE=,d2a4a85c43fb4ccd9b5be6521450d272406a1722f7547f188f4a1d0cc65c4e13
+honnef.co/go/tools,v0.0.1-2019.2.3,h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=,539825114c487680f99df80f6107410e1e53bbfd5deb931b84d1faf2d221638e
+howett.net/plist,v0.0.0-20181124034731-591f970eefbb,h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M=,58c94cd949be714c0ee320d1be0cff3116fc829c412b9e7b816b03fb3c85f463
+istio.io/api,v0.0.0-20191029012234-9fe6a7da3673,h1:wxFykuQoScKAnEtKujAPqjwR8Aqo2LNtkoIvodxyCSs=,9ba545b9c5411725b709287b590082d140d3b29d924be351e38942f46c33ff55
+istio.io/gogo-genproto,v0.0.0-20190930162913-45029607206a,h1:w7zILua2dnYo9CxImhpNW4NE/8ZxEoc/wfBfHrhUhrE=,3b5a81f1807f48117d6691c8d007402a94b648f45f4446841a3f56229aa94aba
+istio.io/pkg,v0.0.0-20191029184635-5c2f5ef63692,h1:MT7e5hpQ8cGtKCeWIjtdluEVkIhkN2tw4iVkAzhWHYA=,887882f7e721e6d00dee301f0b029792bd04bd38c455ab7e5cf4f2bc5bf309df
+k8s.io/api,v0.0.0-20191031065753-b19d8caf39be,h1:X0MqzqUHuZj50SrMQFExejJfy67RKPf30Vt2nnpa4AA=,00a67ed9b84be18f621701796b42cee630c770c858582753fe0eb9c146ef93ff
+k8s.io/apiextensions-apiserver,v0.0.0-20191028232452-c47e10e6d5a3,h1:XxkWdWvPKTParJ1sXpUIvHJsJ2iIIj5Ebjxxy5YU1Zo=,2cb12eb8b2b0f95fb5d69b1f80b754b32ae46ef1f9636333fe27c6b17b1a6e19
+k8s.io/apimachinery,v0.0.0-20191030190112-bb31b70367b7,h1:81UYA9Qq3JXPpZMmRBnq6T3qU+b71Dvnm6sV3NSQTVk=,4c16a440acf7559b0974d99650c876969ad4811ddc76f9f5b7aa43afc34f66ec
+k8s.io/apiserver,v0.0.0-20191031110436-8cb875160ee0,h1:BGkQMPpKpx07hvq9AW64gifbf+zbAh/xUbB5OYXPvQ0=,baefad9177a1f8077c94a2d88b7e85deb7df79317d3d6d6afe8ca0be8261b1ae
+k8s.io/cli-runtime,v0.0.0-20191025231729-08207da42a69,h1:05z+vSvn9yPr7GTAt3MXpVc9VeU4D80HHwvJU6jC3D4=,46264219a6e1c8263acd610841a156086bbbdd43436a836effcd7285c37b0e8a
+k8s.io/client-go,v11.0.0+incompatible,h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o=,70925f536d409accf4f6ae3f20dafd81370ac096f848e99009141bea971103c2
+k8s.io/cloud-provider,v0.0.0-20191025232453-66dd06a864dd,h1:CxSfhPPmLwYFZquskmKvODMeEm82ZLc4eph47AdUp+o=,55623701c005f824ae847ecad409c6e61ef5fcfc6588b8dd2995a4a0991eeae8
+k8s.io/cluster-bootstrap,v0.0.0-20191025232351-410fafc3baf5,h1:P1mMVQngKW9pj1haVjyAtqViIBqkJmsITXsfuaHGRko=,ff50816340cdb73313e7233c3ff6df383c350102762b88ea0cc744910053c7bd
+k8s.io/code-generator,v0.0.0-20191029223907-9f431a56fdbc,h1:klQ4aWfZ3uk4UiSLkZZt5qQDI+7DwSdvbvyL5QUBHsQ=,1f63d3191c255d8fcc47ad24b3bd979865a3c12eca678b39f278c194c2ae560a
+k8s.io/component-base,v0.0.0-20191029070825-5e0e35147053,h1:W9/+uFw7olz+qQOCmSOG92c6j2YgIwagxqR9RWai/cE=,45bd9877048a57c3dfe7eb9c98bc1939775c73fdd6451afd055d7e4f7b9659bc
+k8s.io/cri-api,v0.0.0-20191025232916-446748cffdda,h1:HVTA1bXCQek+NF0xTZkryScnkGYWHkoeYAQVEVs73r8=,7aea277309740df8d1fad1c620901d60633569d755d2d0715d97bc553988d7be
+k8s.io/csi-api,v0.0.0-20190313123203-94ac839bf26c,h1:m3xih+9aI7l7Z/PvwzizV1J4vBvaUpkHrmagnGa5UNg=,0579fba2111dfd5b3cb62d7d234e52c54051176d9564ae3f0f2fdc69b31872b0
+k8s.io/gengo,v0.0.0-20191010091904-7fa3014cb28f,h1:eW/6wVuHNZgQJmFesyAxu0cvj0WAHHUuGaLbPcmNY3Q=,7fe69109e947204ee0b95705626e3c3b540faefb947d3426260f2991d1e4c036
+k8s.io/helm,v2.15.2+incompatible,h1:UjEb+c5BUZDGR9zU3dWG3OXASLIeqLeY0FCIx6ZyfTY=,377860d9db9fb1d45ffa90fe6ee79d7cfc4e91e5bc04183921480a823cf79ede
+k8s.io/klog,v1.0.0,h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=,a564b06078ddf014c5b793a7d36643d6fda31fc131e36b95cdea94ff838b99be
+k8s.io/kube-aggregator,v0.0.0-20191025230902-aa872b06629d,h1:ls0BmbSFkF5BhZN7grE+W5/X49QMU42RH6J9DWdP7UQ=,9a51f29a98f603acde33e3a10625e9ab603d7db29b3c2b2256d145adf7396393
+k8s.io/kube-controller-manager,v0.0.0-20191025232249-6de08162fd59,h1:bTAKwqwK2HvJVmpowb/ccyeV3wsxQZUtFQE1AqhMZ6I=,a1183bb172f19f6ae319da09c111a3f5dded663a9be85e18b9bceb131f03a342
+k8s.io/kube-openapi,v0.0.0-20190918143330-0270cf2f1c1d,h1:Xpe6sK+RY4ZgCTyZ3y273UmFmURhjtoJiwOMbQsXitY=,fb1dcd1508144991be0a243cea9a066944775ba4e9fa23c7ea038822e4e8e232
+k8s.io/kubelet,v0.0.0-20191025232041-e9c3b1e8a9ed,h1:ISiRMWhiLjmSsx24QQ6NJSgW1oKmAN59LCFzB7llrSk=,8c409ac5922dfb4cb0b8e6bb52823b2132e82faa3756dc3a94cdeabeaa3ff51e
+k8s.io/kubernetes,v1.11.10,h1:wCo67+wmguioiYv0ipIiTaXbVPfFBBjOTgIngeGGG+A=,7c8ca4ca473e9f2b5c6586a714209e98d99f193af84cdb3e8536a3d1e26be4bf
+k8s.io/metrics,v0.0.0-20191026071343-a166cc0bce8f,h1:D4AcfwGLY2gFDQaeK2QVyb8g4fy4Xzs0GopdwAgfSGc=,f4243455881a38d4962483ba5f2888220743a6ddece179c2b8f706815b75778f
+k8s.io/node-api,v0.0.0-20191025232816-761e5a80fde0,h1:V3FaBxwSQWPjPScXd5ioFx9+aREXGU24yFl8Gm7ib8w=,cb8718b6e148a66097f8cae4e4544dc55c674748202f9c21d07a2139b6e83fd1
+k8s.io/sample-apiserver,v0.0.0-20191030110742-cbfc6c263d7e,h1:9bsKcUCncu1Qg3A4pB5ZySTM0JMEZW4qgybjVhmaS4A=,91d701af12da2ff6cde6f07d53547885faafa32c2eadfa8d4614b4d814a854b9
+k8s.io/sample-controller,v0.0.0-20191025231305-d7b8b8302943,h1:ZYb6if7+Qa5kXFidUsQRLFDyZjCjRyG1sFf6GpZaA70=,07c3e3a95d0fac07a247a98c38448a8fc4ab0069ad599ec06ac9405df88b470b
+k8s.io/utils,v0.0.0-20191030222137-2b95a09bc58d,h1:1P0iBJsBzxRmR+dIFnM+Iu4aLxnoa7lBqozW/0uHbT8=,e21be6d971127d4650bd13525a2d2627b2a98dbb8589f168b734a45d50f3ea22
+launchpad.net/gocheck,v0.0.0-20140225173054-000000000087,h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=,1a1d9b10f2c69564e69993e4340d5299392a518d895ec06502e842e6c69f4857
+layeh.com/radius,v0.0.0-20190322222518-890bc1058917,h1:BDXFaFzUt5EIqe/4wrTc4AcYZWP6iC6Ult+jQWLh5eU=,5eb6b6a05a5f89bc114f37085deda268f895a46621aee2e36649b8d80061357e
+leb.io/aeshash,v0.0.0-20190627052759-9e6b40329b3b,h1:MG17Tc0pA3XmFTsPwklMMEfcos3pTFnVYM4A0YfVSbU=,a78b48ac18e98ea68dacce16cd94c9074688a0b125f824f047313a33b264ea88
+leb.io/hashland,v0.0.0-20171003003232-07375b562dea,h1:s9IkzZTqYqw77voO6taUZHc0C1B096h4T/kQtujGApE=,0698177f24cbde0a7b45495e7fe976fe7623f2b9205995b7d91fd2e7b0f0e243
+leb.io/hrff,v0.0.0-20170927164517-757f8bd43e20,h1:9CHS8LIq9MDwUsAaCHUsbUq7zb5lSjLQYWlJ/AbMZKg=,538008712599401a903a7982714c0a9ae745221042d3dfb1437bc508d8fb9e96
+modernc.org/cc,v1.0.0,h1:nPibNuDEx6tvYrUAtvDTTw98rx5juGsa5zuDnKwEEQQ=,24711e9b28b0d79dd32438eeb7debd86b850350f5f7749b7af640422ecf6b93b
+modernc.org/golex,v1.0.0,h1:wWpDlbK8ejRfSyi0frMyhilD3JBvtcx2AdGDnU+JtsE=,335133038991d7feaba5349ac2385db7b49601bba0904abf680803ee2d3c99df
+modernc.org/mathutil,v1.0.0,h1:93vKjrJopTPrtTNpZ8XIovER7iCIH1QU7wNbOQXC60I=,766ad95195543fe1ac217ce9f54e1fb43119c25db2b89013b9ef5477ad2dd9d1
+modernc.org/strutil,v1.0.0,h1:XVFtQwFVwc02Wk+0L/Z/zDDXO81r5Lhe6iMKmGX3KhE=,4bbca362df97450c6f24b90b7dc80b97ecf19e5f0f5954655b26f335a0b8f378
+modernc.org/xc,v1.0.0,h1:7ccXrupWZIS3twbUGrtKmHS2DXY6xegFua+6O3xgAFU=,ef80e60acacc023cd294eef2555bd348f74c1bcd22c8cfbbd2472cb91e35900d
+moul.io/http2curl,v1.0.0,h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8=,422e2b8833089b001da02c6d7235ecb4c0591bb585fee125cbd0d72b1371dba5
+mvdan.cc/sh,v2.6.0+incompatible,h1:BLDuJ+D75OCaBF7W70+2oALi8aKAjcAiDBNmmwR8BQA=,c5c335f4ae8f1c4228a01710b84ba8f847709b1920d2beeddc4648e62cdd25f7
+mvdan.cc/sh/v3,v3.0.0-alpha1,h1:ao/4li6H9nZe5HDXA14cynXoq90+DLZz0HmjZE/qjhA=,5da16556569786a039c24229b55eb0f76049c2293ac96a9b978cede87676962e
+mvdan.cc/xurls/v2,v2.0.0,h1:r1zSOSNS/kqtpmATyMMMvaZ4/djsesbYz5kr0+qMRWc=,67e609a744e93b7ba05adee985d7e3471e6d414cea611ac73206e007a5e03082
+myitcv.io,v0.0.0-20190927111909-7837eed0ff8e,h1:aTqeLMcNZAhWxtvBgs0fbjTxg5BuNvHYnLo1lhSq9hE=,0d734b4e576c5c34dd9788481761864faef6cacdd735296d22f885b211fe9c70
+pack.ag/amqp,v0.11.2,h1:cuNDWLUTbKRtEZwhB0WQBXf9pGbm87pUBXQhvcFxBWg=,7cdc81d1aeef4ad24c4a49f6227aac060ee193587c95d48bfe4437beaf08310a
+periph.io/x/periph,v3.6.2+incompatible,h1:B9vqhYVuhKtr6bXua8N9GeBEvD7yanczCvE0wU2LEqw=,aeb77a51a9e20e0414e7ea7c9a3a30302fcb5ffc5cf4dd41c3455ec0c3d7b1bc
+perkeep.org,v0.0.0-20190926184543-d342b0e26632,h1:6ZKRr0VZtsfdHyYDJ/G9rCy7z8jGfrpmYANf0BR+vJM=,fd9e06dfc30d3bcb49399fd062094dfdf364a8344d409541896cb96d36465ade
+rsc.io/binaryregexp,v0.2.0,h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE=,b3e706aa278fa7f880d32fa1cc40ef8282d1fc7d6e00356579ed0db88f3b0047
+rsc.io/goversion,v1.2.0,h1:SPn+NLTiAG7w30IRK/DKp1BjvpWabYgxlLp/+kx5J8w=,f8426f6078b1d1b4e29a8c6223603680169c7c0a8789d2aee7e401a46ff6343f
+rsc.io/pdf,v0.1.1,h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4=,79bf310e399cf0e2d8aa61536750d2a6999c5ca884e7a27faf88d3701cd5ba8f
+rsc.io/qr,v0.1.0,h1:M/sAxsU2J5mlQ4W84Bxga2EgdQqOaAliipcjPmMUM5Q=,fd09c124eb71d01dab3a0116eac47a6fce78f34bbdd84620b2dc01b90582b11c
+sigs.k8s.io/cluster-api,v0.2.7,h1:WjhtuvyjnMgo62kKlVizhI/nYs4DJxHNf+ZMSk/uUsM=,1e3767e7d0f655b72a52eab40e122779ccd1f734c06b9c6488ea9615a3db7b24
+sigs.k8s.io/controller-runtime,v0.3.0,h1:ZtdgqJXVHsIytjdmDuk0QjagnzyLq9FjojXRqIp+dU4=,f37a21668e57315e7248169bec6d4a71f86bcf53d7528c9752e7b459ee74efe0
+sigs.k8s.io/kustomize,v2.0.3+incompatible,h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=,e0f6ad3aaaf7160abcb5e7b16f711c13aebe876833ae9e6ad6f858f31641bf62
+sigs.k8s.io/structured-merge-diff,v0.0.0-20191023203907-336d3378ca53,h1:WCMuuk4OLJ1WdEK3fx+hroiutCODdAGwDlL2Dj4mpa0=,b389a2eafcce0dcef4ca1052942980f26b62030da007b3a84a653de5c0f91668
+sigs.k8s.io/testing_frameworks,v0.1.2-0.20190130140139-57f07443c2d4,h1:GtDhkj3cF4A4IW+A9LScsuxvJqA9DE7G7PGH1f8B07U=,bfb65beb3dda386efc0c0ff9237a07877cec71922f4d3dc1f4a40d5fcaa090a9
+sigs.k8s.io/yaml,v1.1.0,h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=,a0d39252e8665a428a8cb9d4dfc9cbea07b7ae90ae62e7cf3651be719adf515a
+sofastack.io/sofa-mosn,v0.0.0-20191101130505-becc7a6dc50c,h1:8IAozA6SkwfqCAF7fVyy8gu4FdyJvH5iBC12WhiocB8=,0ed9cc5b20e6233051bb4de2ffee5c7f3365704fe01d28e87237d9e8041a786d
+sourcegraph.com/sourcegraph/appdash,v0.0.0-20190107175209-d9ea5c54f7dc,h1:lmf242UNy8ucQUSUse9oXtyxHb6kaF82XRLqeVDXXhA=,49e3fd73d6218c97f49266f0e32bbdab1b6352f2f40da8d1aa98ee8dfdeec072
+sourcegraph.com/sourcegraph/appdash-data,v0.0.0-20151005221446-73f23eafcf67,h1:e1sMhtVq9AfcEy8AXNb8eSg6gbzfdpYhoNqnPJa+GzI=,382adefecd62bb79172e2552bcfb7d45f47122f9bd22259b0566b26fb2627b87
+sourcegraph.com/sourcegraph/go-diff,v0.5.0,h1:eTiIR0CoWjGzJcnQ3OkhIl/b9GJovq4lSAVRt0ZFEG8=,2c5eaad1d3743b3d4bd6de70459a413e62d1753673d5b96402dda27508454b3b
+sourcegraph.com/sqs/pbtypes,v0.0.0-20180604144634-d3ebe8f20ae4,h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c=,6750f8618ecbde1668de332800ec01d713debb145dee395c23fc9a373c207fe3
+storj.io/drpc,v0.0.7-0.20191021224058-08e7133752cd,h1:Oh7Nww1cgFA3fhrCOheDwQ0VcUKFcO1LsBSJEgiGgUQ=,51befd9e6e3aa6cfb9f5b56e47b3cd59715dbe656d0a12cfbb0282609b5456dd
+storj.io/storj,v0.24.5,h1:dWqApMsdhPoUufrljPQC1gZWkYcSTjRr5AoZ7mrSjCw=,ce0628bdcce2b8f0241d27993431d343d212b2e55323510bf657928001c2fb26
+strk.kbt.io/projects/go/libravatar,v0.0.0-20160628055650-5eed7bff870a,h1:8q33ShxKXRwQ7JVd1ZnhIU3hZhwwn0Le+4fTeAackuM=,be48b3949775d6ba0dd3105d7d31d338fede9fbd1471b41fe861f1cfcabbf85c
+v.io/x/lib,v0.1.4,h1:PCDfluqBeRbA7OgDIs9tIpT+z6ZNZ5VMeR+t7h/K2ig=,411c5ded56ba1b69269c37748d184954089c320f43ee76beb0c53f7c598baeaf
+vbom.ml/util,v0.0.0-20180919145318-efcd4e0f9787,h1:O69FD9pJA4WUZlEwYatBEEkRWKQ5cKodWpdKTrCS/iQ=,abbc7a9ac1d820f336ccbe247404800d0f79859b4e4412f0d107aebbb564f920
+vitess.io/vitess,v2.1.1+incompatible,h1:nuuGHiWYWpudD3gOCLeGzol2EJ25e/u5Wer2wV1O130=,8f823ede6775b4f5b3f6cd4c04b3b6be453416e124362a8d68fa2e829429fa68
+xorm.io/builder,v0.3.6,h1:ha28mQ2M+TFx96Hxo+iq6tQgnkC9IZkM6D8w9sKHHF8=,8f16bb96bf2f75b4813be77072a966d1f2248a38f2c7afff4132b666876310a7
+xorm.io/core,v0.7.2,h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw=,24c93962a78b2a177ff5c66cd43921eb1e8b13290d0e8a4d87c6f075a81c4531
diff --git a/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go b/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go
new file mode 100644
index 0000000..16cc145
--- /dev/null
+++ b/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go
@@ -0,0 +1,232 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package zip_sum_test tests that the module zip files produced by modfetch
+// have consistent content sums. Ideally the zip files themselves are also
+// stable over time, though this is not strictly necessary.
+//
+// This test loads a table from testdata/zip_sums.csv. The table has columns
+// for module path, version, content sum, and zip file hash. The table
+// includes a large number of real modules. The test downloads these modules
+// in direct mode and verifies the zip files.
+//
+// This test is very slow, and it depends on outside modules that change
+// frequently, so this is a manual test. To enable it, pass the -zipsum flag.
+package zip_sum_test
+
+import (
+ "context"
+ "crypto/sha256"
+ "encoding/csv"
+ "encoding/hex"
+ "flag"
+ "fmt"
+ "internal/testenv"
+ "io"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/modfetch"
+ "cmd/go/internal/modload"
+
+ "golang.org/x/mod/module"
+)
+
+var (
+ updateTestData = flag.Bool("u", false, "when set, tests may update files in testdata instead of failing")
+ enableZipSum = flag.Bool("zipsum", false, "enable TestZipSums")
+ debugZipSum = flag.Bool("testwork", false, "when set, TestZipSums will preserve its test directory")
+ modCacheDir = flag.String("zipsumcache", "", "module cache to use instead of temp directory")
+ shardCount = flag.Int("zipsumshardcount", 1, "number of shards to divide TestZipSums into")
+ shardIndex = flag.Int("zipsumshard", 0, "index of TestZipSums shard to test (0 <= zipsumshard < zipsumshardcount)")
+)
+
+const zipSumsPath = "testdata/zip_sums.csv"
+
+type zipSumTest struct {
+ m module.Version
+ wantSum, wantFileHash string
+}
+
+func TestZipSums(t *testing.T) {
+ if !*enableZipSum {
+ // This test is very slow and heavily dependent on external repositories.
+ // Only run it explicitly.
+ t.Skip("TestZipSum not enabled with -zipsum")
+ }
+ if *shardCount < 1 {
+ t.Fatal("-zipsumshardcount must be a positive integer")
+ }
+ if *shardIndex < 0 || *shardCount <= *shardIndex {
+ t.Fatal("-zipsumshard must be between 0 and -zipsumshardcount")
+ }
+
+ testenv.MustHaveGoBuild(t)
+ testenv.MustHaveExternalNetwork(t)
+ testenv.MustHaveExecPath(t, "bzr")
+ testenv.MustHaveExecPath(t, "git")
+ // TODO(jayconrod): add hg, svn, and fossil modules to testdata.
+ // Could not find any for now.
+
+ tests, err := readZipSumTests()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if *modCacheDir != "" {
+ cfg.BuildContext.GOPATH = *modCacheDir
+ } else {
+ tmpDir, err := os.MkdirTemp("", "TestZipSums")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if *debugZipSum {
+ fmt.Fprintf(os.Stderr, "TestZipSums: modCacheDir: %s\n", tmpDir)
+ } else {
+ defer os.RemoveAll(tmpDir)
+ }
+ cfg.BuildContext.GOPATH = tmpDir
+ }
+
+ cfg.GOPROXY = "direct"
+ cfg.GOSUMDB = "off"
+ modload.Init()
+
+ // Shard tests by downloading only every nth module when shard flags are set.
+ // This makes it easier to test small groups of modules quickly. We avoid
+ // testing similarly named modules together (the list is sorted by module
+ // path and version).
+ if *shardCount > 1 {
+ r := *shardIndex
+ w := 0
+ for r < len(tests) {
+ tests[w] = tests[r]
+ w++
+ r += *shardCount
+ }
+ tests = tests[:w]
+ }
+
+ // Download modules with a rate limit. We may run out of file descriptors
+ // or cause timeouts without a limit.
+ needUpdate := false
+ for i := range tests {
+ test := &tests[i]
+ name := fmt.Sprintf("%s@%s", strings.ReplaceAll(test.m.Path, "/", "_"), test.m.Version)
+ t.Run(name, func(t *testing.T) {
+ t.Parallel()
+ ctx := context.Background()
+
+ zipPath, err := modfetch.DownloadZip(ctx, test.m)
+ if err != nil {
+ if *updateTestData {
+ t.Logf("%s: could not download module: %s (will remove from testdata)", test.m, err)
+ test.m.Path = "" // mark for deletion
+ needUpdate = true
+ } else {
+ t.Errorf("%s: could not download module: %s", test.m, err)
+ }
+ return
+ }
+
+ sum := modfetch.Sum(ctx, test.m)
+ if sum != test.wantSum {
+ if *updateTestData {
+ t.Logf("%s: updating content sum to %s", test.m, sum)
+ test.wantSum = sum
+ needUpdate = true
+ } else {
+ t.Errorf("%s: got content sum %s; want sum %s", test.m, sum, test.wantSum)
+ return
+ }
+ }
+
+ h := sha256.New()
+ f, err := os.Open(zipPath)
+ if err != nil {
+ t.Errorf("%s: %v", test.m, err)
+ }
+ defer f.Close()
+ if _, err := io.Copy(h, f); err != nil {
+ t.Errorf("%s: %v", test.m, err)
+ }
+ zipHash := hex.EncodeToString(h.Sum(nil))
+ if zipHash != test.wantFileHash {
+ if *updateTestData {
+ t.Logf("%s: updating zip file hash to %s", test.m, zipHash)
+ test.wantFileHash = zipHash
+ needUpdate = true
+ } else {
+ t.Errorf("%s: got zip file hash %s; want hash %s (but content sum matches)", test.m, zipHash, test.wantFileHash)
+ }
+ }
+ })
+ }
+
+ if needUpdate {
+ // Remove tests marked for deletion
+ r, w := 0, 0
+ for r < len(tests) {
+ if tests[r].m.Path != "" {
+ tests[w] = tests[r]
+ w++
+ }
+ r++
+ }
+ tests = tests[:w]
+
+ if err := writeZipSumTests(tests); err != nil {
+ t.Error(err)
+ }
+ }
+}
+
+func readZipSumTests() ([]zipSumTest, error) {
+ f, err := os.Open(filepath.FromSlash(zipSumsPath))
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ r := csv.NewReader(f)
+
+ var tests []zipSumTest
+ for {
+ line, err := r.Read()
+ if err == io.EOF {
+ break
+ } else if err != nil {
+ return nil, err
+ } else if len(line) != 4 {
+ return nil, fmt.Errorf("%s:%d: malformed line", f.Name(), len(tests)+1)
+ }
+ test := zipSumTest{m: module.Version{Path: line[0], Version: line[1]}, wantSum: line[2], wantFileHash: line[3]}
+ tests = append(tests, test)
+ }
+ return tests, nil
+}
+
+func writeZipSumTests(tests []zipSumTest) (err error) {
+ f, err := os.Create(filepath.FromSlash(zipSumsPath))
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if cerr := f.Close(); err == nil && cerr != nil {
+ err = cerr
+ }
+ }()
+ w := csv.NewWriter(f)
+ line := make([]string, 0, 4)
+ for _, test := range tests {
+ line = append(line[:0], test.m.Path, test.m.Version, test.wantSum, test.wantFileHash)
+ if err := w.Write(line); err != nil {
+ return err
+ }
+ }
+ w.Flush()
+ return nil
+}