Moved morph dependency to new repo (#19618)

```release-note
NONE
```

Co-authored-by: Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>
Этот коммит содержится в:
Agniva De Sarker
2022-02-23 20:11:12 +05:30
коммит произвёл GitHub
родитель 9534efe534
Коммит 2a59047d07
30 изменённых файлов: 329 добавлений и 242 удалений

1
vendor/github.com/mattermost/morph/.gitignore сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1 @@
.idea

12
vendor/github.com/mattermost/morph/AUTHORS сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,12 @@
# This is the official list of go-morph authors for copyright purposes.
#
# This does not necessarily list everyone who has contributed code, since in
# some cases, their employer may be the copyright holder. To see the full list
# of contributors, see the revision history in source control or
# https://github.com/go-morph/morph/graphs/contributors.
#
# Authors who wish to be recognized in this file should add themselves (or
# their employer, as appropriate).
mgdelacroix
nronas

22
vendor/github.com/mattermost/morph/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2021 The go-morph AUTHORS. All rights reserved.
https://github.com/go-morph/morph
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

42
vendor/github.com/mattermost/morph/Makefile сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,42 @@
all: test
GO=go
.PHONY: test
test:
$(GO) clean -testcache
make test-drivers
make test-rest
.PHONY: test-rest
test-rest:
$(GO) clean -testcache
$(GO) test -race -v --tags=!drivers,sources ./...
.PHONY: test-drivers
test-drivers:
$(GO) clean -testcache
$(GO) test -race -v --tags=drivers,!sources ./...
.PHONY: update-dependencies
update-dependencies:
$(GO) get -u ./...
$(GO) mod vendor
$(GO) mod tidy
.PHONY: vendor
vendor:
$(GO) mod vendor
$(GO) mod tidy
.PHONY: check
check:
$(GO) fmt ./...
.PHONY: run-databases
run-databases:
docker-compose up --no-recreate -d
.PHONY: install
install:
$(GO) install -mod=readonly -trimpath ./cmd/morph

80
vendor/github.com/mattermost/morph/README.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,80 @@
![](https://avatars.githubusercontent.com/u/80110794?s=200&v=4)
[![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/mattermost/morph/CI)](https://github.com/mattermost/morph/actions/workflows/ci.yml?query=branch%3Amaster)
[![GoDoc](https://pkg.go.dev/badge/github.com/mattermost/migrate)](https://pkg.go.dev/github.com/mattermost/morph)
# Morph
Morph is a database migration tool that helps you to apply your migrations. It is written with Go so you can use it from your Go application as well.
## Usage
It can be used as a library or a CLI tool.
### Library
```Go
import (
"context"
"github.com/mattermost/morph"
"github.com/mattermost/morph/drivers/mysql"
bindata "github.com/mattermost/morph/sources/go_bindata"
)
src, err := bindata.WithInstance(&bindata.AssetSource{
Names: []string{}, // add migration file names
AssetFunc: func(name string) ([]byte, error) {
return []byte{}, nil // should return the file contents
},
})
if err != nil {
return err
}
defer src.Close()
driver, err := mysql.WithInstance(db, &mysql.Config{})
if err != nil {
return err
}
engine, err := morph.New(context.Background(), driver, src)
if err != nil {
return err
}
defer engine.Close()
engine.ApplyAll()
```
### CLI
To install `morph` you can use:
```bash
go install github.com/mattermost/morph/cmd/morph@latest
```
Then you can apply your migrations like below:
```bash
morph apply up --driver postgres --dsn "postgres://user:pass@localhost:5432/mydb?sslmode=disable" --path ./db/migrations/postgres --number 1
```
## Migration Files
The migrations files should have an `up` and `down` versions. The program requires each migration to be reversible, and the naming of the migration should be in the following form:
```
0000000001_create_user.up.sql
0000000001_create_user.down.sql
```
The first part will be used to determine the order in which the migrations should be applied and the next part until the `up|down.sql` suffix will be the migration name.
The program requires this naming convention to be followed as it saves the order and names of the migrations. Also, it can rollback migrations with the `down` files.
## LICENSE
[MIT](LICENSE)

36
vendor/github.com/mattermost/morph/color_logger.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,36 @@
package morph
import (
"log"
"github.com/fatih/color"
)
var (
ErrorLogger = color.New(color.FgRed, color.Bold)
ErrorLoggerLight = color.New(color.FgRed)
InfoLogger = color.New(color.FgCyan, color.Bold)
InfoLoggerLight = color.New(color.FgCyan)
SuccessLogger = color.New(color.FgGreen, color.Bold)
)
type Logger interface {
Printf(format string, v ...interface{})
Println(v ...interface{})
}
type colorLogger struct {
log *log.Logger
}
func newColorLogger(log *log.Logger) *colorLogger {
return &colorLogger{log: log}
}
func (l *colorLogger) Printf(format string, v ...interface{}) {
l.log.Println(InfoLoggerLight.Sprintf(format, v...))
}
func (l *colorLogger) Println(v ...interface{}) {
l.log.Println(InfoLoggerLight.Sprint(v...))
}

20
vendor/github.com/mattermost/morph/docker-compose.yml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,20 @@
version: '3.1'
services:
postgres:
image: postgres
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: morph
mysql:
image: "mysql:5.7"
restart: always
ports:
- "3307:3306"
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_DATABASE: morph_test
MYSQL_USER: morph
MYSQL_PASSWORD: morph
MYSQL_ROOT_PASSWORD: morph

23
vendor/github.com/mattermost/morph/drivers/driver.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,23 @@
package drivers
import (
"github.com/mattermost/morph/models"
)
type Config struct {
MigrationsTable string
// StatementTimeoutInSecs is used to set a timeout for each migration file.
// Set below zero to disable timeout. Zero value will result in default value, which is 60 seconds.
StatementTimeoutInSecs int
MigrationMaxSize int
}
type Driver interface {
Ping() error
// Close closes the underlying db connection. If the driver is created via Open() function
// this method will also going to call Close() on the sql.db instance.
Close() error
Apply(migration *models.Migration, saveVersion bool) error
AppliedMigrations() ([]*models.Migration, error)
SetConfig(key string, value interface{}) error
}

25
vendor/github.com/mattermost/morph/drivers/error.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,25 @@
package drivers
import "fmt"
type AppError struct {
OrigErr error
Driver string
Message string
}
type DatabaseError struct {
OrigErr error
Driver string
Message string
Command string
Query []byte
}
func (ae *AppError) Error() string {
return fmt.Sprintf("driver: %s, message: %s, originalError: %v ", ae.Driver, ae.Message, ae.OrigErr)
}
func (de *DatabaseError) Error() string {
return fmt.Sprintf("driver: %s, message: %s, command: %s, originalError: %v, query: \n\n%s\n", de.Driver, de.Message, de.Command, de.OrigErr, string(de.Query))
}

85
vendor/github.com/mattermost/morph/drivers/lock.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,85 @@
package drivers
import (
"context"
"errors"
"math/rand"
"time"
)
const (
// MutexTableName is the name being used for the mutex table
MutexTableName = "db_lock"
// minWaitInterval is the minimum amount of time to wait between locking attempts
minWaitInterval = 1 * time.Second
// maxWaitInterval is the maximum amount of time to wait between locking attempts
maxWaitInterval = 5 * time.Minute
// pollWaitInterval is the usual time to wait between unsuccessful locking attempts
pollWaitInterval = 1 * time.Second
// jitterWaitInterval is the amount of jitter to add when waiting to avoid thundering herds
jitterWaitInterval = minWaitInterval / 2
// TTL is the interval after which a locked mutex will expire unless refreshed
TTL = time.Second * 15
// RefreshInterval is the interval on which the mutex will be refreshed when locked
RefreshInterval = TTL / 2
)
// MakeLockKey returns the prefixed key used to namespace mutex keys.
func MakeLockKey(key string) (string, error) {
if key == "" {
return "", errors.New("must specify valid mutex key")
}
return key, nil
}
// NextWaitInterval determines how long to wait until the next lock retry.
func NextWaitInterval(lastWaitInterval time.Duration, err error) time.Duration {
nextWaitInterval := lastWaitInterval
if nextWaitInterval <= 0 {
nextWaitInterval = minWaitInterval
}
if err != nil {
nextWaitInterval *= 2
if nextWaitInterval > maxWaitInterval {
nextWaitInterval = maxWaitInterval
}
} else {
nextWaitInterval = pollWaitInterval
}
// Add some jitter to avoid unnecessary collision between competing other instances.
nextWaitInterval += time.Duration(rand.Int63n(int64(jitterWaitInterval)) - int64(jitterWaitInterval)/2)
return nextWaitInterval
}
type Locker interface {
Lock() error
Unlock() error
// LockWithContext locks m unless the context is canceled. If the mutex is already locked by any other
// instance, including the current one, the calling goroutine blocks until the mutex can be locked,
// or the context is canceled.
//
// The mutex is locked only if a nil error is returned.
LockWithContext(ctx context.Context) error
}
type Lockable interface {
DriverName() string
}
// IsLockable returns whether the given instance satisfies
// drivers.Lockable or not.
func IsLockable(x interface{}) bool {
_, ok := x.(Lockable)
return ok
}

269
vendor/github.com/mattermost/morph/drivers/mysql/lock.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,269 @@
package mysql
import (
"context"
"database/sql"
"errors"
"fmt"
"sync"
"time"
"github.com/mattermost/morph/drivers"
)
// Mutex is similar to sync.Mutex, except usable by morph to lock the db.
//
// Pick a unique name for each mutex your plugin requires.
//
// A Mutex must not be copied after first use.
type Mutex struct {
noCopy
key string
// lock guards the variables used to manage the refresh task, and is not itself related to
// the db lock.
lock sync.Mutex
stopRefresh chan bool
refreshDone chan bool
conn *sql.Conn
}
// NewMutex creates a mutex with the given key name.
//
// returns error if key is empty.
func NewMutex(key string, driver drivers.Driver) (*Mutex, error) {
key, err := drivers.MakeLockKey(key)
if err != nil {
return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), drivers.TTL)
defer cancel()
ms, ok := driver.(*mysql)
if !ok {
return nil, errors.New("incorrect implementation of the driver")
}
conn, err := ms.db.Conn(context.Background())
if err != nil {
return nil, err
}
createTableIfNotExistsQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (Id varchar(64) NOT NULL, ExpireAt bigint(20) NOT NULL, PRIMARY KEY (Id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", drivers.MutexTableName)
if _, err = conn.ExecContext(ctx, createTableIfNotExistsQuery); err != nil {
return nil, err
}
return &Mutex{
key: key,
conn: conn,
}, nil
}
// lock makes a single attempt to lock the mutex, returning true only if successful.
func (m *Mutex) tryLock(ctx context.Context) (bool, error) {
now := time.Now()
tx, err := m.conn.BeginTx(ctx, nil)
if err != nil {
return false, err
}
query := fmt.Sprintf("INSERT INTO %s (Id, ExpireAt) VALUES (?, ?)", drivers.MutexTableName)
if _, err := tx.Exec(query, m.key, now.Add(drivers.TTL).Unix()); err != nil {
err2 := m.releaseLock(tx, now)
if err2 == nil { // lock has been released due to expiration
return true, nil
}
return false, fmt.Errorf("failed to lock mutex: %w", err)
}
err = tx.Commit()
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return false, txErr
}
return false, err
}
return true, nil
}
func (m *Mutex) releaseLock(tx *sql.Tx, t time.Time) error {
e, err := m.getExpireAt(tx)
if err != nil {
return err
}
if t.Unix() < e {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback: %w", txErr)
}
return errors.New("could not release the lock")
}
query := fmt.Sprintf("UPDATE %s SET ExpireAt = ? WHERE Id = ?", drivers.MutexTableName)
if err = executeTx(tx, query, t.Add(drivers.TTL).Unix(), m.key); err != nil {
return err
}
err = tx.Commit()
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback transaction: %w", txErr)
}
return fmt.Errorf("unable to set new expireat for mutex: %w", err)
}
return nil
}
func (m *Mutex) getExpireAt(tx *sql.Tx) (int64, error) {
var expireAt int64
query := fmt.Sprintf("SELECT ExpireAt FROM %s WHERE Id = ?", drivers.MutexTableName)
err := tx.QueryRow(query, m.key).Scan(&expireAt)
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return -1, fmt.Errorf("could not rollback: %w", txErr)
}
return -1, fmt.Errorf("failed to fetch mutex from db: %w", err)
}
return expireAt, nil
}
// refreshLock rewrites the lock key value with a new expiry, returning nil only if successful.
func (m *Mutex) refreshLock(ctx context.Context) error {
tx, err := m.conn.BeginTx(ctx, nil)
if err != nil {
return err
}
e, err := m.getExpireAt(tx)
if err != nil {
return err
}
tmp := time.Unix(e, 0)
query := fmt.Sprintf("UPDATE %s SET ExpireAt = ? WHERE Id = ?", drivers.MutexTableName)
if err = executeTx(tx, query, tmp.Add(drivers.TTL).Unix(), m.key); err != nil {
return err
}
err = tx.Commit()
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback: %w", txErr)
}
return fmt.Errorf("unable to refresh expireat for mutex: %w", err)
}
return nil
}
// Lock locks m. If the mutex is already locked by any other morph instance, including the current one,
// the calling goroutine blocks until the mutex can be locked.
func (m *Mutex) Lock() error {
return m.LockWithContext(context.Background())
}
// LockWithContext locks m unless the context is canceled. If the mutex is already locked by any other
// instance, including the current one, the calling goroutine blocks until the mutex can be locked,
// or the context is canceled.
//
// The mutex is locked only if a nil error is returned.
func (m *Mutex) LockWithContext(ctx context.Context) error {
var waitInterval time.Duration
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(waitInterval):
}
ok, err := m.tryLock(ctx)
if err != nil || !ok {
waitInterval = drivers.NextWaitInterval(waitInterval, err)
continue
}
break
}
stop := make(chan bool)
done := make(chan bool)
go func() {
defer close(done)
t := time.NewTicker(drivers.RefreshInterval)
for {
select {
case <-t.C:
err := m.refreshLock(ctx)
if err != nil {
return
}
case <-stop:
return
}
}
}()
m.lock.Lock()
m.stopRefresh = stop
m.refreshDone = done
m.lock.Unlock()
return nil
}
// Unlock unlocks m. It is a run-time error if m is not locked on entry to Unlock.
//
// Just like sync.Mutex, a locked Lock is not associated with a particular goroutine or a process.
func (m *Mutex) Unlock() error {
m.lock.Lock()
if m.stopRefresh == nil {
m.lock.Unlock()
panic("mutex has not been acquired")
}
close(m.stopRefresh)
m.stopRefresh = nil
<-m.refreshDone
m.lock.Unlock()
defer m.conn.Close()
// If an error occurs deleting, the mutex will still expire, allowing later retry.
query := fmt.Sprintf("DELETE FROM %s WHERE Id = ?", drivers.MutexTableName)
_, err := m.conn.ExecContext(context.Background(), query, m.key)
return err
}
func executeTx(tx *sql.Tx, query string, args ...interface{}) error {
if _, err := tx.Exec(query, args...); err != nil {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback transaction: %w", txErr)
}
return err
}
return nil
}
// noCopy may be embedded into structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
type noCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock() {}

335
vendor/github.com/mattermost/morph/drivers/mysql/mysql.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,335 @@
// Initial code generated by generator.
package mysql
import (
"context"
"database/sql"
"fmt"
"strconv"
"github.com/pkg/errors"
_ "github.com/go-sql-driver/mysql"
"github.com/mattermost/morph/drivers"
"github.com/mattermost/morph/models"
)
const driverName = "mysql"
const defaultMigrationMaxSize = 10 * 1 << 20 // 10 MB
// add here any custom driver configuration
var configParams = []string{
"x-migration-max-size",
"x-migrations-table",
"x-statement-timeout",
}
type Config struct {
drivers.Config
databaseName string
closeDBonClose bool
}
type mysql struct {
conn *sql.Conn
db *sql.DB
config *Config
}
func WithInstance(dbInstance *sql.DB, config *Config) (drivers.Driver, error) {
driverConfig := mergeConfigs(config, getDefaultConfig())
conn, err := dbInstance.Conn(context.Background())
if err != nil {
return nil, &drivers.DatabaseError{Driver: driverName, Command: "grabbing_connection", OrigErr: err, Message: "failed to grab connection to the database"}
}
if driverConfig.databaseName, err = currentDatabaseNameFromDB(conn, driverConfig); err != nil {
return nil, err
}
return &mysql{config: driverConfig, conn: conn, db: dbInstance}, nil
}
func Open(connURL string) (drivers.Driver, error) {
customParams, err := drivers.ExtractCustomParams(connURL, configParams)
if err != nil {
return nil, &drivers.AppError{Driver: driverName, OrigErr: err, Message: "failed to parse custom parameters from url"}
}
sanitizedConnURL, err := drivers.RemoveParamsFromURL(connURL, configParams)
if err != nil {
return nil, &drivers.AppError{Driver: driverName, OrigErr: err, Message: "failed to sanitize url from custom parameters"}
}
driverConfig, err := mergeConfigWithParams(customParams, getDefaultConfig())
if err != nil {
return nil, &drivers.AppError{Driver: driverName, OrigErr: err, Message: "failed to merge custom params to driver config"}
}
db, err := sql.Open(driverName, sanitizedConnURL)
if err != nil {
return nil, &drivers.DatabaseError{Driver: driverName, Command: "opening_connection", OrigErr: err, Message: "failed to open connection with the database"}
}
conn, err := db.Conn(context.Background())
if err != nil {
return nil, &drivers.DatabaseError{Driver: driverName, Command: "grabbing_connection", OrigErr: err, Message: "failed to grab connection to the database"}
}
if driverConfig.databaseName, err = extractDatabaseNameFromURL(sanitizedConnURL); err != nil {
return nil, &drivers.AppError{Driver: driverName, OrigErr: err, Message: "failed to extract database name from connection url"}
}
driverConfig.closeDBonClose = true
return &mysql{
conn: conn,
db: db,
config: driverConfig,
}, nil
}
func (driver *mysql) Ping() error {
ctx, cancel := drivers.GetContext(driver.config.StatementTimeoutInSecs)
defer cancel()
return driver.conn.PingContext(ctx)
}
func (mysql) DriverName() string {
return driverName
}
func (driver *mysql) Close() error {
if driver.conn != nil {
if err := driver.conn.Close(); err != nil {
return &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed to close database connection",
Command: "mysql_conn_close",
Query: nil,
}
}
}
if driver.db != nil && driver.config.closeDBonClose {
if err := driver.db.Close(); err != nil {
return &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed to close database",
Command: "mysql_db_close",
Query: nil,
}
}
driver.db = nil
}
driver.conn = nil
return nil
}
func (driver *mysql) createSchemaTableIfNotExists() (err error) {
ctx, cancel := drivers.GetContext(driver.config.StatementTimeoutInSecs)
defer cancel()
createTableIfNotExistsQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (Version bigint(20) NOT NULL, Name varchar(64) NOT NULL, PRIMARY KEY (Version)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", driver.config.MigrationsTable)
if _, err = driver.conn.ExecContext(ctx, createTableIfNotExistsQuery); err != nil {
return &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed while executing query",
Command: "create_migrations_table_if_not_exists",
Query: []byte(createTableIfNotExistsQuery),
}
}
return nil
}
func (driver *mysql) Apply(migration *models.Migration, saveVersion bool) (err error) {
query, readErr := migration.Query()
if readErr != nil {
return &drivers.AppError{
OrigErr: readErr,
Driver: driverName,
Message: fmt.Sprintf("failed to read migration query: %s", migration.Name),
}
}
defer migration.Close()
ctx, cancel := drivers.GetContext(driver.config.StatementTimeoutInSecs)
defer cancel()
if _, err := driver.conn.ExecContext(ctx, query); err != nil {
return &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed when applying migration",
Command: "apply_migration",
Query: []byte(query),
}
}
updateVersionContext, cancel := drivers.GetContext(driver.config.StatementTimeoutInSecs)
defer cancel()
if !saveVersion {
return nil
}
updateVersionQuery := driver.addMigrationQuery(migration)
if _, err := driver.conn.ExecContext(updateVersionContext, updateVersionQuery); err != nil {
return &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed when updating migrations table with the new version",
Command: "update_version",
Query: []byte(updateVersionQuery),
}
}
return nil
}
func (driver *mysql) AppliedMigrations() (migrations []*models.Migration, err error) {
if driver.conn == nil {
return nil, &drivers.AppError{
OrigErr: errors.New("driver has no connection established"),
Message: "database connection is missing",
Driver: driverName,
}
}
if err := driver.createSchemaTableIfNotExists(); err != nil {
return nil, err
}
query := fmt.Sprintf("SELECT version, name FROM %s", driver.config.MigrationsTable)
ctx, cancel := drivers.GetContext(driver.config.StatementTimeoutInSecs)
defer cancel()
var appliedMigrations []*models.Migration
var version uint32
var name string
rows, err := driver.conn.QueryContext(ctx, query)
if err != nil {
return nil, &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed to fetch applied migrations",
Command: "select_applied_migrations",
Query: []byte(query),
}
}
defer rows.Close()
for rows.Next() {
if err := rows.Scan(&version, &name); err != nil {
return nil, &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed to scan applied migration row",
Command: "scan_applied_migrations",
}
}
appliedMigrations = append(appliedMigrations, &models.Migration{
Name: name,
Version: version,
Direction: models.Up,
})
}
return appliedMigrations, nil
}
func currentDatabaseNameFromDB(conn *sql.Conn, config *Config) (string, error) {
query := "SELECT DATABASE()"
ctx, cancel := drivers.GetContext(config.StatementTimeoutInSecs)
defer cancel()
var databaseName string
if err := conn.QueryRowContext(ctx, query).Scan(&databaseName); err != nil {
return "", &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed to fetch database name",
Command: "current_database",
Query: []byte(query),
}
}
return databaseName, nil
}
func mergeConfigs(config *Config, defaultConfig *Config) *Config {
if config.MigrationsTable == "" {
config.MigrationsTable = defaultConfig.MigrationsTable
}
if config.StatementTimeoutInSecs == 0 {
config.StatementTimeoutInSecs = defaultConfig.StatementTimeoutInSecs
}
if config.MigrationMaxSize == 0 {
config.MigrationMaxSize = defaultConfig.MigrationMaxSize
}
return config
}
func mergeConfigWithParams(params map[string]string, config *Config) (*Config, error) {
var err error
for _, configKey := range configParams {
if v, ok := params[configKey]; ok {
switch configKey {
case "x-migration-max-size":
if config.MigrationMaxSize, err = strconv.Atoi(v); err != nil {
return nil, errors.New(fmt.Sprintf("failed to cast config param %s of %s", configKey, v))
}
case "x-migrations-table":
config.MigrationsTable = v
case "x-statement-timeout":
if config.StatementTimeoutInSecs, err = strconv.Atoi(v); err != nil {
return nil, errors.New(fmt.Sprintf("failed to cast config param %s of %s", configKey, v))
}
}
}
}
return config, nil
}
func (driver *mysql) addMigrationQuery(migration *models.Migration) string {
if migration.Direction == models.Down {
return fmt.Sprintf("DELETE FROM %s WHERE (Version=%d AND NAME='%s')", driver.config.MigrationsTable, migration.Version, migration.Name)
}
return fmt.Sprintf("INSERT INTO %s (Version, Name) VALUES (%d, '%s')", driver.config.MigrationsTable, migration.Version, migration.Name)
}
func (driver *mysql) SetConfig(key string, value interface{}) error {
if driver.config != nil {
switch key {
case "StatementTimeoutInSecs":
n, ok := value.(int)
if ok {
driver.config.StatementTimeoutInSecs = n
return nil
}
return fmt.Errorf("incorrect value type for %s", key)
case "MigrationsTable":
n, ok := value.(string)
if ok {
driver.config.MigrationsTable = n
return nil
}
return fmt.Errorf("incorrect value type for %s", key)
}
}
return fmt.Errorf("incorrect key name %q", key)
}

34
vendor/github.com/mattermost/morph/drivers/mysql/utils.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,34 @@
package mysql
import (
mysqlDriver "github.com/go-sql-driver/mysql"
"github.com/mattermost/morph/drivers"
)
func ExtractMysqlDSNParams(conn string) (map[string]string, error) {
cfg, err := mysqlDriver.ParseDSN(conn)
if err != nil {
return nil, err
}
return cfg.Params, nil
}
func extractDatabaseNameFromURL(conn string) (string, error) {
cfg, err := mysqlDriver.ParseDSN(conn)
if err != nil {
return "", err
}
return cfg.DBName, nil
}
func getDefaultConfig() *Config {
return &Config{
Config: drivers.Config{
MigrationsTable: "db_migrations",
StatementTimeoutInSecs: 60,
MigrationMaxSize: defaultMigrationMaxSize,
},
}
}

269
vendor/github.com/mattermost/morph/drivers/postgres/lock.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,269 @@
package postgres
import (
"context"
"database/sql"
"errors"
"fmt"
"sync"
"time"
"github.com/mattermost/morph/drivers"
)
// Mutex is similar to sync.Mutex, except usable by morph to lock the db.
//
// Pick a unique name for each mutex your plugin requires.
//
// A Mutex must not be copied after first use.
type Mutex struct {
noCopy
key string
// lock guards the variables used to manage the refresh task, and is not itself related to
// the db lock.
lock sync.Mutex
stopRefresh chan bool
refreshDone chan bool
conn *sql.Conn
}
// NewMutex creates a mutex with the given key name.
//
// returns error if key is empty.
func NewMutex(key string, driver drivers.Driver) (*Mutex, error) {
key, err := drivers.MakeLockKey(key)
if err != nil {
return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), drivers.TTL)
defer cancel()
ps, ok := driver.(*postgres)
if !ok {
return nil, errors.New("incorrect implementation of the driver")
}
conn, err := ps.db.Conn(context.Background())
if err != nil {
return nil, err
}
createTableIfNotExistsQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (id varchar(64) PRIMARY KEY, expireat bigint);", drivers.MutexTableName)
if _, err = conn.ExecContext(ctx, createTableIfNotExistsQuery); err != nil {
return nil, err
}
return &Mutex{
key: key,
conn: conn,
}, nil
}
// lock makes a single attempt to lock the mutex, returning true only if successful.
func (m *Mutex) tryLock(ctx context.Context) (bool, error) {
now := time.Now()
tx, err := m.conn.BeginTx(ctx, nil)
if err != nil {
return false, err
}
query := fmt.Sprintf("INSERT INTO %s (id, expireat) VALUES ($1, $2)", drivers.MutexTableName)
if _, err := tx.Exec(query, m.key, now.Add(drivers.TTL).Unix()); err != nil {
err2 := m.releaseLock(tx, now)
if err2 == nil { // lock has been released due to expiration
return true, nil
}
return false, fmt.Errorf("failed to lock mutex: %w", err)
}
err = tx.Commit()
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return false, txErr
}
return false, err
}
return true, nil
}
func (m *Mutex) releaseLock(tx *sql.Tx, t time.Time) error {
e, err := m.getExpireAt(tx)
if err != nil {
return err
}
if t.Unix() < e {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback: %w", txErr)
}
return errors.New("could not release the lock")
}
query := fmt.Sprintf("UPDATE %s SET expireat = $1 WHERE id = $2", drivers.MutexTableName)
if err = executeTx(tx, query, t.Add(drivers.TTL).Unix(), m.key); err != nil {
return err
}
err = tx.Commit()
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback transaction: %w", txErr)
}
return fmt.Errorf("unable to set new expireat for mutex: %w", err)
}
return nil
}
func (m *Mutex) getExpireAt(tx *sql.Tx) (int64, error) {
var expireAt int64
query := fmt.Sprintf("SELECT expireat FROM %s WHERE id = $1", drivers.MutexTableName)
err := tx.QueryRow(query, m.key).Scan(&expireAt)
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return -1, fmt.Errorf("could not rollback: %w", txErr)
}
return -1, fmt.Errorf("failed to fetch mutex from db: %w", err)
}
return expireAt, nil
}
// refreshLock rewrites the lock key value with a new expiry, returning nil only if successful.
func (m *Mutex) refreshLock(ctx context.Context) error {
tx, err := m.conn.BeginTx(ctx, nil)
if err != nil {
return err
}
e, err := m.getExpireAt(tx)
if err != nil {
return err
}
tmp := time.Unix(e, 0)
query := fmt.Sprintf("UPDATE %s SET expireat = $1 WHERE id = $2", drivers.MutexTableName)
if err = executeTx(tx, query, tmp.Add(drivers.TTL).Unix(), m.key); err != nil {
return err
}
err = tx.Commit()
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback: %w", txErr)
}
return fmt.Errorf("unable to refresh expireat for mutex: %w", err)
}
return nil
}
// Lock locks m. If the mutex is already locked by any other morph instance, including the current one,
// the calling goroutine blocks until the mutex can be locked.
func (m *Mutex) Lock() error {
return m.LockWithContext(context.Background())
}
// LockWithContext locks m unless the context is canceled. If the mutex is already locked by any other
// instance, including the current one, the calling goroutine blocks until the mutex can be locked,
// or the context is canceled.
//
// The mutex is locked only if a nil error is returned.
func (m *Mutex) LockWithContext(ctx context.Context) error {
var waitInterval time.Duration
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(waitInterval):
}
ok, err := m.tryLock(ctx)
if err != nil || !ok {
waitInterval = drivers.NextWaitInterval(waitInterval, err)
continue
}
break
}
stop := make(chan bool)
done := make(chan bool)
go func() {
defer close(done)
t := time.NewTicker(drivers.RefreshInterval)
for {
select {
case <-t.C:
err := m.refreshLock(ctx)
if err != nil {
return
}
case <-stop:
return
}
}
}()
m.lock.Lock()
m.stopRefresh = stop
m.refreshDone = done
m.lock.Unlock()
return nil
}
// Unlock unlocks m. It is a run-time error if m is not locked on entry to Unlock.
//
// Just like sync.Mutex, a locked Lock is not associated with a particular goroutine or a process.
func (m *Mutex) Unlock() error {
m.lock.Lock()
if m.stopRefresh == nil {
m.lock.Unlock()
panic("mutex has not been acquired")
}
close(m.stopRefresh)
m.stopRefresh = nil
<-m.refreshDone
m.lock.Unlock()
defer m.conn.Close()
// If an error occurs deleting, the mutex will still expire, allowing later retry.
query := fmt.Sprintf("DELETE FROM %s WHERE id = $1", drivers.MutexTableName)
_, err := m.conn.ExecContext(context.Background(), query, m.key)
return err
}
func executeTx(tx *sql.Tx, query string, args ...interface{}) error {
if _, err := tx.Exec(query, args...); err != nil {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback transaction: %w", txErr)
}
return err
}
return nil
}
// noCopy may be embedded into structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
type noCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock() {}

392
vendor/github.com/mattermost/morph/drivers/postgres/postgres.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,392 @@
package postgres
import (
"context"
"database/sql"
"fmt"
"strconv"
"github.com/pkg/errors"
_ "github.com/lib/pq"
"github.com/mattermost/morph/drivers"
"github.com/mattermost/morph/models"
)
var (
driverName = "postgres"
defaultMigrationMaxSize = 10 * 1 << 20 // 10 MB
configParams = []string{
"x-migration-max-size",
"x-migrations-table",
"x-statement-timeout",
}
)
type Config struct {
drivers.Config
databaseName string
schemaName string
closeDBonClose bool
}
type postgres struct {
conn *sql.Conn
db *sql.DB
config *Config
}
func WithInstance(dbInstance *sql.DB, config *Config) (drivers.Driver, error) {
driverConfig := mergeConfigs(config, getDefaultConfig())
conn, err := dbInstance.Conn(context.Background())
if err != nil {
return nil, &drivers.DatabaseError{Driver: driverName, Command: "grabbing_connection", OrigErr: err, Message: "failed to grab connection to the database"}
}
if driverConfig.databaseName, err = currentDatabaseNameFromDB(conn, driverConfig); err != nil {
return nil, err
}
if driverConfig.schemaName, err = currentSchema(conn, driverConfig); err != nil {
return nil, err
}
return &postgres{
conn: conn,
db: dbInstance,
config: driverConfig,
}, nil
}
func Open(connURL string) (drivers.Driver, error) {
customParams, err := drivers.ExtractCustomParams(connURL, configParams)
if err != nil {
return nil, &drivers.AppError{Driver: driverName, OrigErr: err, Message: "failed to parse custom parameters from url"}
}
sanitizedConnURL, err := drivers.RemoveParamsFromURL(connURL, configParams)
if err != nil {
return nil, &drivers.AppError{Driver: driverName, OrigErr: err, Message: "failed to sanitize url from custom parameters"}
}
driverConfig, err := mergeConfigWithParams(customParams, getDefaultConfig())
if err != nil {
return nil, &drivers.AppError{Driver: driverName, OrigErr: err, Message: "failed to merge custom params to driver config"}
}
db, err := sql.Open(driverName, sanitizedConnURL)
if err != nil {
return nil, &drivers.DatabaseError{Driver: driverName, Command: "opening_connection", OrigErr: err, Message: "failed to open connection with the database"}
}
conn, err := db.Conn(context.Background())
if err != nil {
return nil, &drivers.DatabaseError{Driver: driverName, Command: "grabbing_connection", OrigErr: err, Message: "failed to grab connection to the database"}
}
if driverConfig.databaseName, err = extractDatabaseNameFromURL(connURL); err != nil {
return nil, &drivers.AppError{Driver: driverName, OrigErr: err, Message: "failed to extract database name from connection url"}
}
if driverConfig.schemaName, err = currentSchema(conn, driverConfig); err != nil {
return nil, err
}
driverConfig.closeDBonClose = true
return &postgres{
db: db,
config: driverConfig,
conn: conn,
}, nil
}
func currentSchema(conn *sql.Conn, config *Config) (string, error) {
query := "SELECT CURRENT_SCHEMA()"
ctx, cancel := drivers.GetContext(config.StatementTimeoutInSecs)
defer cancel()
var schemaName string
if err := conn.QueryRowContext(ctx, query).Scan(&schemaName); err != nil {
return "", &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed to fetch current schema",
Command: "current_schema",
Query: []byte(query),
}
}
return schemaName, nil
}
func mergeConfigWithParams(params map[string]string, config *Config) (*Config, error) {
var err error
for _, configKey := range configParams {
if v, ok := params[configKey]; ok {
switch configKey {
case "x-migration-max-size":
if config.MigrationMaxSize, err = strconv.Atoi(v); err != nil {
return nil, errors.New(fmt.Sprintf("failed to cast config param %s of %s", configKey, v))
}
case "x-migrations-table":
config.MigrationsTable = v
case "x-statement-timeout":
if config.StatementTimeoutInSecs, err = strconv.Atoi(v); err != nil {
return nil, errors.New(fmt.Sprintf("failed to cast config param %s of %s", configKey, v))
}
}
}
}
return config, nil
}
func mergeConfigs(config, defaultConfig *Config) *Config {
if config.MigrationsTable == "" {
config.MigrationsTable = defaultConfig.MigrationsTable
}
if config.StatementTimeoutInSecs == 0 {
config.StatementTimeoutInSecs = defaultConfig.StatementTimeoutInSecs
}
if config.MigrationMaxSize == 0 {
config.MigrationMaxSize = defaultConfig.MigrationMaxSize
}
return config
}
func (pg *postgres) Ping() error {
ctx, cancel := drivers.GetContext(pg.config.StatementTimeoutInSecs)
defer cancel()
return pg.conn.PingContext(ctx)
}
func (pg *postgres) createSchemaTableIfNotExists() (err error) {
ctx, cancel := drivers.GetContext(pg.config.StatementTimeoutInSecs)
defer cancel()
createTableIfNotExistsQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (version bigint not null primary key, name varchar not null)", pg.config.MigrationsTable)
if _, err = pg.conn.ExecContext(ctx, createTableIfNotExistsQuery); err != nil {
return &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed while executing query",
Command: "create_migrations_table_if_not_exists",
Query: []byte(createTableIfNotExistsQuery),
}
}
return nil
}
func (postgres) DriverName() string {
return driverName
}
func (pg *postgres) Close() error {
if pg.conn != nil {
if err := pg.conn.Close(); err != nil {
return &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed to close database connection",
Command: "pg_conn_close",
Query: nil,
}
}
}
if pg.db != nil && pg.config.closeDBonClose {
if err := pg.db.Close(); err != nil {
return &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed to close database",
Command: "pg_db_close",
Query: nil,
}
}
pg.db = nil
}
pg.conn = nil
return nil
}
func (pg *postgres) Apply(migration *models.Migration, saveVersion bool) (err error) {
query, readErr := migration.Query()
if readErr != nil {
return &drivers.AppError{
OrigErr: readErr,
Driver: driverName,
Message: fmt.Sprintf("failed to read migration query: %s", migration.Name),
}
}
defer migration.Close()
ctx, cancel := drivers.GetContext(pg.config.StatementTimeoutInSecs)
defer cancel()
transaction, err := pg.conn.BeginTx(ctx, nil)
if err != nil {
return &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "error while opening a transaction to the database",
Command: "begin_transaction",
}
}
if err = executeQuery(transaction, query); err != nil {
return err
}
if saveVersion {
if err = executeQuery(transaction, pg.addMigrationQuery(migration)); err != nil {
return err
}
}
err = transaction.Commit()
if err != nil {
return &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "error while committing a transaction to the database",
Command: "commit_transaction",
}
}
return nil
}
func (pg *postgres) AppliedMigrations() (migrations []*models.Migration, err error) {
if pg.conn == nil {
return nil, &drivers.AppError{
OrigErr: errors.New("driver has no connection established"),
Message: "database connection is missing",
Driver: driverName,
}
}
if err := pg.createSchemaTableIfNotExists(); err != nil {
return nil, err
}
query := fmt.Sprintf("SELECT version, name FROM %s", pg.config.MigrationsTable)
ctx, cancel := drivers.GetContext(pg.config.StatementTimeoutInSecs)
defer cancel()
var appliedMigrations []*models.Migration
var version uint32
var name string
rows, err := pg.conn.QueryContext(ctx, query)
if err != nil {
return nil, &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed to fetch applied migrations",
Command: "select_applied_migrations",
Query: []byte(query),
}
}
defer rows.Close()
for rows.Next() {
if err := rows.Scan(&version, &name); err != nil {
return nil, &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed to scan applied migration row",
Command: "scan_applied_migrations",
}
}
appliedMigrations = append(appliedMigrations, &models.Migration{
Name: name,
Version: version,
Direction: models.Up,
})
}
return appliedMigrations, nil
}
func (pg *postgres) addMigrationQuery(migration *models.Migration) string {
if migration.Direction == models.Down {
return fmt.Sprintf("DELETE FROM %s WHERE (Version=%d AND NAME='%s')", pg.config.MigrationsTable, migration.Version, migration.Name)
}
return fmt.Sprintf("INSERT INTO %s (version, name) VALUES (%d, '%s')", pg.config.MigrationsTable, migration.Version, migration.Name)
}
func executeQuery(transaction *sql.Tx, query string) error {
if _, err := transaction.Exec(query); err != nil {
if txErr := transaction.Rollback(); txErr != nil {
err = errors.Wrap(errors.New(err.Error()+txErr.Error()), "failed to execute query in migration transaction")
return &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Command: "rollback_transaction",
}
}
return &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed to execute migration",
Command: "executing_query",
Query: []byte(query),
}
}
return nil
}
func currentDatabaseNameFromDB(conn *sql.Conn, config *Config) (string, error) {
query := "SELECT CURRENT_DATABASE()"
ctx, cancel := drivers.GetContext(config.StatementTimeoutInSecs)
defer cancel()
var databaseName string
if err := conn.QueryRowContext(ctx, query).Scan(&databaseName); err != nil {
return "", &drivers.DatabaseError{
OrigErr: err,
Driver: driverName,
Message: "failed to fetch database name",
Command: "current_database",
Query: []byte(query),
}
}
return databaseName, nil
}
func (pg *postgres) SetConfig(key string, value interface{}) error {
if pg.config != nil {
switch key {
case "StatementTimeoutInSecs":
n, ok := value.(int)
if ok {
pg.config.StatementTimeoutInSecs = n
return nil
}
return fmt.Errorf("incorrect value type for %s", key)
case "MigrationsTable":
n, ok := value.(string)
if ok {
pg.config.MigrationsTable = n
return nil
}
return fmt.Errorf("incorrect value type for %s", key)
}
}
return fmt.Errorf("incorrect key name %q", key)
}

26
vendor/github.com/mattermost/morph/drivers/postgres/utils.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,26 @@
package postgres
import (
"net/url"
"github.com/mattermost/morph/drivers"
)
func extractDatabaseNameFromURL(URL string) (string, error) {
uri, err := url.Parse(URL)
if err != nil {
return "", err
}
return uri.Path[1:], nil
}
func getDefaultConfig() *Config {
return &Config{
Config: drivers.Config{
MigrationsTable: "db_migrations",
StatementTimeoutInSecs: 60,
MigrationMaxSize: defaultMigrationMaxSize,
},
}
}

58
vendor/github.com/mattermost/morph/drivers/utils.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,58 @@
package drivers
import (
"context"
"fmt"
"hash/crc32"
"regexp"
"strings"
"time"
)
func ExtractCustomParams(conn string, params []string) (map[string]string, error) {
result := make(map[string]string)
for _, param := range params {
reg := regexp.MustCompile(fmt.Sprintf("%s=(\\w+)", param))
match := reg.FindStringSubmatch(conn)
if len(match) > 1 {
result[param] = match[1]
}
}
return result, nil
}
func RemoveParamsFromURL(conn string, params []string) (string, error) {
prefixCorrection := regexp.MustCompile(`\?&+`)
repeatedAmber := regexp.MustCompile("&+")
for _, param := range params {
reg := regexp.MustCompile(fmt.Sprintf("%s=\\w+", param))
conn = string(reg.ReplaceAll([]byte(conn), []byte(``)))
}
parts := strings.Split(conn, "/")
urlParams := parts[len(parts)-1]
urlParams = string(prefixCorrection.ReplaceAll([]byte(urlParams), []byte(`?`)))
urlParams = string(repeatedAmber.ReplaceAll([]byte(urlParams), []byte(`&`)))
parts[len(parts)-1] = urlParams
return strings.Join(parts, "/"), nil
}
const advisoryLockIDSalt uint = 1486364155
func GenerateAdvisoryLockID(databaseName, schemaName string) (string, error) {
databaseName = schemaName + databaseName + "\x00"
sum := crc32.ChecksumIEEE([]byte(databaseName))
sum = sum * uint32(advisoryLockIDSalt)
return fmt.Sprint(sum), nil
}
func GetContext(timeoutInSeconds int) (context.Context, context.CancelFunc) {
if t := timeoutInSeconds; t > 0 {
return context.WithTimeout(context.Background(), time.Second*time.Duration(t))
}
return context.WithCancel(context.Background())
}

14
vendor/github.com/mattermost/morph/go.mod сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,14 @@
module github.com/mattermost/morph
go 1.16
require (
github.com/dave/jennifer v1.4.1
github.com/fatih/color v1.10.0
github.com/go-sql-driver/mysql v1.6.0
github.com/lib/pq v1.10.0
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.1.3
github.com/stretchr/testify v1.3.0
modernc.org/sqlite v1.14.3
)

457
vendor/github.com/mattermost/morph/go.sum сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,457 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/dave/jennifer v1.4.1 h1:XyqG6cn5RQsTj3qlWQTKlRGAyrTcsk1kUmWdZBzRjDw=
github.com/dave/jennifer v1.4.1/go.mod h1:7jEdnm+qBcxl8PC0zyp7vxcpSRnzXSt9r39tpTVGlwA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.18 h1:rMZhRcWrba0y3nVmdiQ7kxAgOOSq2m2f2VzjHLgEs6U=
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI=
modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag=
modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw=
modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ=
modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c=
modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo=
modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg=
modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I=
modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs=
modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8=
modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE=
modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk=
modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w=
modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE=
modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8=
modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc=
modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU=
modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE=
modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk=
modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI=
modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE=
modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg=
modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74=
modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU=
modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU=
modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc=
modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM=
modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ=
modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84=
modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ=
modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY=
modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w=
modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU=
modernc.org/ccgo/v3 v3.12.88/go.mod h1:0MFzUHIuSIthpVZyMWiFYMwjiFnhrN5MkvBrUwON+ZM=
modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko=
modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA=
modernc.org/ccgo/v3 v3.12.95 h1:Ym2JG2G3P4IyZqjTTojHTl7qO0RysXeGSYPSoKPSBxc=
modernc.org/ccgo/v3 v3.12.95/go.mod h1:ZcLyvtocXYi8uF+9Ebm3G8EF8HNY5hGomBqthDp4eC8=
modernc.org/ccorpus v1.11.1 h1:K0qPfpVG1MJh5BYazccnmhywH4zHuOgJXgbjzyp6dWA=
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg=
modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M=
modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU=
modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE=
modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso=
modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8=
modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8=
modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I=
modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk=
modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY=
modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE=
modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg=
modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM=
modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg=
modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo=
modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8=
modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ=
modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA=
modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM=
modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg=
modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE=
modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM=
modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU=
modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw=
modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M=
modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18=
modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8=
modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw=
modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0=
modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI=
modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE=
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY=
modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ=
modernc.org/libc v1.11.90/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
modernc.org/libc v1.11.99/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
modernc.org/libc v1.11.104 h1:gxoa5b3HPo7OzD4tKZjgnwXk/w//u1oovvjSMP3Q96Q=
modernc.org/libc v1.11.104/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ=
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14=
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.14.3 h1:psrTwgpEujgWEP3FNdsC9yNh5tSeA77U0GeWhHH4XmQ=
modernc.org/sqlite v1.14.3/go.mod h1:xMpicS1i2MJ4C8+Ap0vYBqTwYfpFvdnPE6brbFOtV2Y=
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.9.2 h1:YA87dFLOsR2KqMka371a2Xgr+YsyUwo7OmHVSv/kztw=
modernc.org/tcl v1.9.2/go.mod h1:aw7OnlIoiuJgu1gwbTZtrKnGpDqH9wyH++jZcxdqNsg=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.2.20 h1:DyboxM1sJR2NB803j2StnbnL6jcQXz273OhHDGu8dGk=
modernc.org/z v1.2.20/go.mod h1:zU9FiF4PbHdOTUxw+IF8j7ArBMRPsHgq10uVPt6xTzo=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

58
vendor/github.com/mattermost/morph/models/migration.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,58 @@
package models
import (
"bytes"
"fmt"
"io"
"strconv"
)
type Migration struct {
Bytes io.ReadCloser
Name string
RawName string
Version uint32
Direction Direction
}
func NewMigration(migrationBytes io.ReadCloser, fileName string) (*Migration, error) {
m := Regex.FindStringSubmatch(fileName)
var (
versionUint64 uint64
direction Direction
identifier string
err error
)
if len(m) == 5 {
versionUint64, err = strconv.ParseUint(m[1], 10, 64)
if err != nil {
return nil, err
}
identifier = m[2]
direction = Direction(m[3])
} else {
return nil, fmt.Errorf("could not parse file: %s", fileName)
}
return &Migration{
Version: uint32(versionUint64),
Name: identifier,
RawName: fileName,
Bytes: migrationBytes,
Direction: direction,
}, nil
}
func (m *Migration) Query() (string, error) {
buf := new(bytes.Buffer)
if _, err := buf.ReadFrom(m.Bytes); err != nil {
return "", err
}
return buf.String(), nil
}
func (m *Migration) Close() error {
return m.Bytes.Close()
}

23
vendor/github.com/mattermost/morph/models/parse.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,23 @@
package models
import (
"fmt"
"regexp"
)
// Direction is either up or down.
type Direction string
const (
Down Direction = "down"
Up Direction = "up"
)
var (
ErrParse = fmt.Errorf("no match")
)
// Regex matches the following pattern:
// 123_name.up.ext
// 123_name.down.ext
var Regex = regexp.MustCompile(`^([0-9]+)_(.*)\.(` + string(Down) + `|` + string(Up) + `)\.(.*)$`)

294
vendor/github.com/mattermost/morph/morph.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,294 @@
package morph
import (
"context"
"errors"
"fmt"
"log"
"os"
"sort"
"strings"
"time"
"github.com/mattermost/morph/models"
"github.com/mattermost/morph/drivers"
"github.com/mattermost/morph/sources"
ms "github.com/mattermost/morph/drivers/mysql"
ps "github.com/mattermost/morph/drivers/postgres"
_ "github.com/mattermost/morph/sources/file"
_ "github.com/mattermost/morph/sources/go_bindata"
)
var migrationProgressStart = "== %s: migrating ================================================="
var migrationProgressFinished = "== %s: migrated (%s) ========================================"
const maxProgressLogLength = 100
type Morph struct {
config *Config
driver drivers.Driver
source sources.Source
mutex drivers.Locker
}
type Config struct {
Logger Logger
LockTimeout time.Duration
LockKey string
}
type EngineOption func(*Morph)
func WithLogger(logger Logger) EngineOption {
return func(m *Morph) {
m.config.Logger = logger
}
}
func WithLockTimeout(lockTimeout time.Duration) EngineOption {
return func(m *Morph) {
m.config.LockTimeout = lockTimeout
}
}
func SetMigrationTableName(name string) EngineOption {
return func(m *Morph) {
_ = m.driver.SetConfig("MigrationsTable", name)
}
}
func SetSatementTimeoutInSeconds(n int) EngineOption {
return func(m *Morph) {
_ = m.driver.SetConfig("StatementTimeoutInSecs", n)
}
}
// WithLock creates a lock table in the database so that the migrations are
// guaranteed to be executed from a single instance. The key is used for naming
// the mutex.
func WithLock(key string) EngineOption {
return func(m *Morph) {
m.config.LockKey = key
}
}
// New creates a new instance of the migrations engine from an existing db instance and a migrations source.
// If the driver implements the Lockable interface, it will also wait until it has acquired a lock.
func New(ctx context.Context, driver drivers.Driver, source sources.Source, options ...EngineOption) (*Morph, error) {
engine := &Morph{
config: &Config{
Logger: newColorLogger(log.New(os.Stderr, "", log.LstdFlags)), // add default logger
},
source: source,
driver: driver,
}
for _, option := range options {
option(engine)
}
if err := driver.Ping(); err != nil {
return nil, err
}
if impl, ok := driver.(drivers.Lockable); ok && engine.config.LockKey != "" {
var mx drivers.Locker
var err error
switch impl.DriverName() {
case "mysql":
mx, err = ms.NewMutex(engine.config.LockKey, driver)
case "postgres":
mx, err = ps.NewMutex(engine.config.LockKey, driver)
default:
err = errors.New("driver does not support locking")
}
if err != nil {
return nil, err
}
engine.mutex = mx
err = mx.LockWithContext(ctx)
if err != nil {
return nil, err
}
}
return engine, nil
}
// Close closes the underlying database connection of the engine.
func (m *Morph) Close() error {
if m.mutex != nil {
err := m.mutex.Unlock()
if err != nil {
return err
}
}
return m.driver.Close()
}
// ApplyAll applies all pending migrations.
func (m *Morph) ApplyAll() error {
_, err := m.Apply(-1)
return err
}
// Applies limited number of migrations upwards.
func (m *Morph) Apply(limit int) (int, error) {
appliedMigrations, err := m.driver.AppliedMigrations()
if err != nil {
return -1, err
}
pendingMigrations, err := computePendingMigrations(appliedMigrations, m.source.Migrations())
if err != nil {
return -1, err
}
migrations := make([]*models.Migration, 0)
sortedMigrations := sortMigrations(pendingMigrations)
for _, migration := range sortedMigrations {
if migration.Direction != models.Up {
continue
}
migrations = append(migrations, migration)
}
steps := limit
if len(migrations) < steps {
return -1, fmt.Errorf("there are only %d migrations avaliable, but you requested %d", len(migrations), steps)
}
if limit < 0 {
steps = len(migrations)
}
var applied int
for i := 0; i < steps; i++ {
start := time.Now()
migrationName := migrations[i].Name
m.config.Logger.Println(formatProgress(fmt.Sprintf(migrationProgressStart, migrationName)))
if err := m.driver.Apply(migrations[i], true); err != nil {
return applied, err
}
applied++
elapsed := time.Since(start)
m.config.Logger.Println(formatProgress(fmt.Sprintf(migrationProgressFinished, migrationName, fmt.Sprintf("%.4fs", elapsed.Seconds()))))
}
return applied, nil
}
// ApplyDown rollbacks a limited number of migrations
// if limit is given below zero, all down scripts are going to be applied.
func (m *Morph) ApplyDown(limit int) (int, error) {
appliedMigrations, err := m.driver.AppliedMigrations()
if err != nil {
return -1, err
}
sortedMigrations := reverseSortMigrations(appliedMigrations)
downMigrations, err := findDownScripts(sortedMigrations, m.source.Migrations())
if err != nil {
return -1, err
}
steps := limit
if len(sortedMigrations) < steps {
return -1, fmt.Errorf("there are only %d migrations avaliable, but you requested %d", len(sortedMigrations), steps)
}
if limit < 0 {
steps = len(sortedMigrations)
}
var applied int
for i := 0; i < steps; i++ {
start := time.Now()
migrationName := sortedMigrations[i].Name
m.config.Logger.Println(formatProgress(fmt.Sprintf(migrationProgressStart, migrationName)))
down := downMigrations[migrationName]
if err := m.driver.Apply(down, true); err != nil {
return applied, err
}
applied++
elapsed := time.Since(start)
m.config.Logger.Println(formatProgress(fmt.Sprintf(migrationProgressFinished, migrationName, fmt.Sprintf("%.4fs", elapsed.Seconds()))))
}
return applied, nil
}
func reverseSortMigrations(migrations []*models.Migration) []*models.Migration {
sort.Slice(migrations, func(i, j int) bool {
return migrations[i].Version > migrations[j].Version
})
return migrations
}
func sortMigrations(migrations []*models.Migration) []*models.Migration {
sort.Slice(migrations, func(i, j int) bool {
return migrations[i].RawName < migrations[j].RawName
})
return migrations
}
func computePendingMigrations(appliedMigrations []*models.Migration, sourceMigrations []*models.Migration) ([]*models.Migration, error) {
// sourceMigrations has to be greater or equal to databaseMigrations
if len(appliedMigrations) > len(sourceMigrations) {
return nil, errors.New("migration mismatch, there are more migrations applied than those were specified in source")
}
dict := make(map[string]*models.Migration)
for _, appliedMigration := range appliedMigrations {
dict[appliedMigration.Name] = appliedMigration
}
var pendingMigrations []*models.Migration
for _, sourceMigration := range sourceMigrations {
if _, ok := dict[sourceMigration.Name]; !ok {
pendingMigrations = append(pendingMigrations, sourceMigration)
}
}
return pendingMigrations, nil
}
func findDownScripts(appliedMigrations []*models.Migration, sourceMigrations []*models.Migration) (map[string]*models.Migration, error) {
tmp := make(map[string]*models.Migration)
for _, m := range sourceMigrations {
if m.Direction != models.Down {
continue
}
tmp[m.Name] = m
}
for _, m := range appliedMigrations {
_, ok := tmp[m.Name]
if !ok {
return nil, fmt.Errorf("could not find down script for %s", m.Name)
}
}
return tmp, nil
}
func formatProgress(p string) string {
if len(p) < maxProgressLogLength {
return p + strings.Repeat("=", maxProgressLogLength-len(p))
}
if len(p) > maxProgressLogLength {
return p[:maxProgressLogLength]
}
return p
}

105
vendor/github.com/mattermost/morph/sources/file/file.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,105 @@
package file
import (
"fmt"
"net/url"
"os"
"path/filepath"
"github.com/mattermost/morph/models"
"github.com/mattermost/morph/sources"
)
func init() {
sources.Register("file", &File{})
}
type File struct {
url string
path string
migrations []*models.Migration
}
func (f *File) Open(sourceURL string) (sources.Source, error) {
uri, err := url.Parse(sourceURL)
if err != nil {
return nil, err
}
// host might be "." for relative URLs like file://./migrations
p := uri.Opaque
if len(p) == 0 {
p = uri.Host + uri.Path
}
// if no path provided, default to current directory
if len(p) == 0 {
wd, err := os.Getwd()
if err != nil {
return nil, err
}
p = wd
} else if p[0:1] != "/" {
// make path absolute if required
abs, err := filepath.Abs(p)
if err != nil {
return nil, err
}
p = abs
}
nf := &File{
url: sourceURL,
path: p,
}
if err := nf.readMigrations(); err != nil {
return nil, fmt.Errorf("cannot read migrations in path %q: %w", p, err)
}
return nf, nil
}
func (f *File) readMigrations() error {
info, err := os.Stat(f.path)
if err != nil {
return err
}
if !info.IsDir() {
return fmt.Errorf("file %q is not a directory", info.Name())
}
migrations := []*models.Migration{}
walkerr := filepath.Walk(f.path, func(path string, info os.FileInfo, _ error) error {
if info.IsDir() {
return nil
}
file, err := os.Open(path)
if err != nil {
return err
}
m, err := models.NewMigration(file, filepath.Base(path))
if err != nil {
return fmt.Errorf("could not create migration: %w", err)
}
migrations = append(migrations, m)
return nil
})
if walkerr != nil {
return walkerr
}
f.migrations = migrations
return nil
}
func (f *File) Close() error {
return nil
}
func (f *File) Migrations() []*models.Migration {
return f.migrations
}

31
vendor/github.com/mattermost/morph/sources/go_bindata/README.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,31 @@
# go-bindata source
This source reads migrations from a
[go-bindata](github.com/go-bindata/go-bindata) embedded binary file.
## Usage
To read the embedded data, create a migration source through the
`WithInstance` method and then instantiate `morph`:
```go
import (
"github.com/mattermost/morph"
"github.com/mattermost/morph/sources/go_bindata"
"github.com/mattermost/morph/sources/go_bindata/testdata"
)
func main() {
res := bindata.Resource(testdata.AssetNames(), func(name string) ([]byte, error) {
return testdata.Asset(name)
})
src, err := bindata.WithInstance(res)
if err != nil {
panic(err)
}
// create the morph instance from the source and driver
m := morph.NewFromConnURL("postgres://...", src, opts)
}
```

68
vendor/github.com/mattermost/morph/sources/go_bindata/go-bindata.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,68 @@
package bindata
import (
"bytes"
"fmt"
"io/ioutil"
"github.com/mattermost/morph/models"
"github.com/mattermost/morph/sources"
)
type AssetFunc func(name string) ([]byte, error)
func Resource(names []string, fn AssetFunc) *AssetSource {
return &AssetSource{
Names: names,
AssetFunc: fn,
}
}
type AssetSource struct {
Names []string
AssetFunc AssetFunc
}
func init() {
sources.Register("go-bindata", &Bindata{})
}
type Bindata struct {
assetSource *AssetSource
migrations []*models.Migration
}
func (b *Bindata) Open(url string) (sources.Source, error) {
return nil, fmt.Errorf("not implemented")
}
func WithInstance(assetSource *AssetSource) (sources.Source, error) {
b := &Bindata{
assetSource: assetSource,
migrations: []*models.Migration{},
}
for _, filename := range assetSource.Names {
migrationBytes, err := b.assetSource.AssetFunc(filename)
if err != nil {
return nil, fmt.Errorf("cannot read migration %q: %w", filename, err)
}
m, err := models.NewMigration(ioutil.NopCloser(bytes.NewReader(migrationBytes)), filename)
if err != nil {
return nil, fmt.Errorf("could not create migration: %w", err)
}
b.migrations = append(b.migrations, m)
}
return b, nil
}
func (b *Bindata) Close() error {
return nil
}
func (b *Bindata) Migrations() []*models.Migration {
return b.migrations
}

47
vendor/github.com/mattermost/morph/sources/source.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,47 @@
package sources
import (
"fmt"
"sync"
"github.com/mattermost/morph/models"
)
var sourcesMu sync.RWMutex
var registeredSources = make(map[string]Source)
type Source interface {
Open(sourceURL string) (source Source, err error)
Close() (err error)
Migrations() (migrations []*models.Migration)
}
func Register(name string, source Source) {
sourcesMu.Lock()
defer sourcesMu.Unlock()
registeredSources[name] = source
}
func List() []string {
sourcesMu.Lock()
defer sourcesMu.Unlock()
sources := make([]string, 0, len(registeredSources))
for source := range registeredSources {
sources = append(sources, source)
}
return sources
}
func Open(sourceName, sourceURL string) (Source, error) {
sourcesMu.RLock()
source, ok := registeredSources[sourceName]
sourcesMu.RUnlock()
if !ok {
return nil, fmt.Errorf("unsupported source %q found", sourceName)
}
return source.Open(sourceURL)
}