mirror of
https://github.com/foomo/posh.git
synced 2025-10-16 12:45:38 +00:00
initial commit
This commit is contained in:
commit
e2ad376b6c
12
.editorconfig
Normal file
12
.editorconfig
Normal file
@ -0,0 +1,12 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = tab
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{yaml,yml,md,mdx}]
|
||||
indent_style = space
|
||||
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# General
|
||||
.*
|
||||
._*
|
||||
bin/
|
||||
tmp/
|
||||
*.log
|
||||
!.posh
|
||||
!.gitignore
|
||||
!.posh.yaml
|
||||
!.editorconfig
|
||||
!.golangci.yml
|
||||
114
.golangci.yml
Normal file
114
.golangci.yml
Normal file
@ -0,0 +1,114 @@
|
||||
run:
|
||||
go: "1.19"
|
||||
skip-dirs:
|
||||
- tmp
|
||||
|
||||
linters-settings:
|
||||
revive:
|
||||
rules:
|
||||
- name: indent-error-flow
|
||||
disabled: true
|
||||
# https://golangci-lint.run/usage/linters/#gocritic
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- assignOp
|
||||
- ifElseChain
|
||||
- singleCaseSwitch
|
||||
- commentFormatting
|
||||
linters:
|
||||
|
||||
enable:
|
||||
# Enabled by default linters:
|
||||
- errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases [fast: false, auto-fix: false]
|
||||
- gosimple # (megacheck): Linter for Go source code that specializes in simplifying code [fast: false, auto-fix: false]
|
||||
- govet # (vet, vetshadow): Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string [fast: false, auto-fix: false]
|
||||
- ineffassign # Detects when assignments to existing variables are not used [fast: true, auto-fix: false]
|
||||
- staticcheck # (megacheck): It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary. The author of staticcheck doesn't support or approve the use of staticcheck as a library inside golangci-lint. [fast: false, auto-fix: false]
|
||||
- typecheck # Like the front-end of a Go compiler, parses and type-checks Go code [fast: false, auto-fix: false]
|
||||
- unused # (megacheck): Checks Go code for unused constants, variables, functions and types [fast: false, auto-fix: false]
|
||||
|
||||
# Disabled by default linters:
|
||||
- asasalint # check for pass []any as any in variadic func(...any) [fast: false, auto-fix: false]
|
||||
- asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers [fast: true, auto-fix: false]
|
||||
- bidichk # Checks for dangerous unicode character sequences [fast: true, auto-fix: false]
|
||||
- bodyclose # checks whether HTTP response body is closed successfully [fast: false, auto-fix: false]
|
||||
#- containedctx # containedctx is a linter that detects struct contained context.Context field [fast: true, auto-fix: false]
|
||||
- contextcheck # check the function whether to use a non-inherited context [fast: false, auto-fix: false]
|
||||
- cyclop # checks function and package cyclomatic complexity [fast: false, auto-fix: false]
|
||||
- decorder # check declaration order and count of types, constants, variables and functions [fast: true, auto-fix: false]
|
||||
- depguard # Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false]
|
||||
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]
|
||||
- dupl # Tool for code clone detection [fast: true, auto-fix: false]
|
||||
- dupword # Checks for duplicate words in the source code [fast: true, auto-fix: true]
|
||||
- durationcheck # check for two durations multiplied together [fast: false, auto-fix: false]
|
||||
- errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted. [fast: false, auto-fix: false]
|
||||
- errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. [fast: false, auto-fix: false]
|
||||
- errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. [fast: false, auto-fix: false]
|
||||
- execinquery # execinquery is a linter about query string checker in Query function which reads your Go src files and warning it finds [fast: false, auto-fix: false]
|
||||
- exhaustive # check exhaustiveness of enum switch statements [fast: false, auto-fix: false]
|
||||
#- exhaustruct # Checks if all structure fields are initialized [fast: false, auto-fix: false]
|
||||
- exportloopref # checks for pointers to enclosing loop variables [fast: false, auto-fix: false]
|
||||
#- forbidigo # Forbids identifiers [fast: true, auto-fix: false]
|
||||
- forcetypeassert # finds forced type assertions [fast: true, auto-fix: false]
|
||||
#- funlen # Tool for detection of long functions [fast: true, auto-fix: false]
|
||||
#- gci # Gci controls golang package import order and makes it always deterministic. [fast: true, auto-fix: false]
|
||||
#- gochecknoglobals # check that no global variables exist [fast: true, auto-fix: false]
|
||||
#- gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false]
|
||||
- gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false]
|
||||
- goconst # Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false]
|
||||
- gocritic # Provides diagnostics that check for bugs, performance and style issues. [fast: false, auto-fix: false]
|
||||
- gocyclo # Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false]
|
||||
#- godot # Check if comments end in a period [fast: true, auto-fix: true]
|
||||
#- godox # Tool for detection of FIXME, TODO and other comment keywords [fast: true, auto-fix: false]
|
||||
#- goerr113 # Golang linter to check the errors handling expressions [fast: false, auto-fix: false]
|
||||
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification [fast: true, auto-fix: true]
|
||||
#- gofumpt # Gofumpt checks whether code was gofumpt-ed. [fast: true, auto-fix: true]
|
||||
- goheader # Checks is file header matches to pattern [fast: true, auto-fix: false]
|
||||
- goimports # In addition to fixing imports, goimports also formats your code in the same style as gofmt. [fast: true, auto-fix: true]
|
||||
#- gomnd # An analyzer to detect magic numbers. [fast: true, auto-fix: false]
|
||||
#- gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false]
|
||||
- gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. [fast: true, auto-fix: false]
|
||||
- goprintffuncname # Checks that printf-like functions are named with `f` at the end [fast: true, auto-fix: false]
|
||||
- gosec # (gas): Inspects source code for security problems [fast: false, auto-fix: false]
|
||||
- grouper # An analyzer to analyze expression groups. [fast: true, auto-fix: false]
|
||||
- importas # Enforces consistent import aliases [fast: false, auto-fix: false]
|
||||
- interfacebloat # A linter that checks the number of methods inside an interface. [fast: true, auto-fix: false]
|
||||
#- ireturn # Accept Interfaces, Return Concrete Types [fast: false, auto-fix: false]
|
||||
- loggercheck # Checks key valur pairs for common logger libraries (kitlog,klog,logr,zap). [fast: false, auto-fix: false]
|
||||
- lll # Reports long lines [fast: true, auto-fix: false]
|
||||
- maintidx # maintidx measures the maintainability index of each function. [fast: true, auto-fix: false]
|
||||
- makezero # Finds slice declarations with non-zero initial length [fast: false, auto-fix: false]
|
||||
- misspell # Finds commonly misspelled English words in comments [fast: true, auto-fix: true]
|
||||
- nakedret # Finds naked returns in functions greater than a specified function length [fast: true, auto-fix: false]
|
||||
- nestif # Reports deeply nested if statements [fast: true, auto-fix: false]
|
||||
- nilerr # Finds the code that returns nil even if it checks that the error is not nil. [fast: false, auto-fix: false]
|
||||
- nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. [fast: false, auto-fix: false]
|
||||
#- nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity [fast: true, auto-fix: false]
|
||||
- noctx # noctx finds sending http request without context.Context [fast: false, auto-fix: false]
|
||||
- nolintlint # Reports ill-formed or insufficient nolint directives [fast: true, auto-fix: false]
|
||||
#- nonamedreturns # Reports all named returns [fast: false, auto-fix: false]
|
||||
- nosprintfhostport # Checks for misuse of Sprintf to construct a host with port in a URL. [fast: true, auto-fix: false]
|
||||
- paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test [fast: false, auto-fix: false]
|
||||
- prealloc # Finds slice declarations that could potentially be pre-allocated [fast: true, auto-fix: false]
|
||||
- predeclared # find code that shadows one of Go's predeclared identifiers [fast: true, auto-fix: false]
|
||||
- promlinter # Check Prometheus metrics naming via promlint [fast: true, auto-fix: false]
|
||||
- reassign # Checks that package variables are not reassigned [fast: false, auto-fix: false]
|
||||
- revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. [fast: false, auto-fix: false]
|
||||
- rowserrcheck # checks whether Err of rows is checked successfully [fast: false, auto-fix: false]
|
||||
- sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. [fast: false, auto-fix: false]
|
||||
- stylecheck # Stylecheck is a replacement for golint [fast: false, auto-fix: false]
|
||||
- tagliatelle # Checks the struct tags. [fast: true, auto-fix: false]
|
||||
- tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 [fast: false, auto-fix: false]
|
||||
- testableexamples # linter checks if examples are testable (have an expected output) [fast: true, auto-fix: false]
|
||||
- testpackage # linter that makes you use a separate _test package [fast: true, auto-fix: false]
|
||||
- thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers [fast: false, auto-fix: false]
|
||||
- tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes [fast: false, auto-fix: false]
|
||||
- unconvert # Remove unnecessary type conversions [fast: false, auto-fix: false]
|
||||
- unparam # Reports unused function parameters [fast: false, auto-fix: false]
|
||||
- usestdlibvars # A linter that detect the possibility to use variables/constants from the Go standard library. [fast: true, auto-fix: false]
|
||||
#- varnamelen # checks that the length of a variable's name matches its scope [fast: false, auto-fix: false]
|
||||
- wastedassign # wastedassign finds wasted assignment statements. [fast: false, auto-fix: false]
|
||||
- whitespace # Tool for detection of leading and trailing whitespace [fast: true, auto-fix: true]
|
||||
# - wrapcheck # Checks that errors returned from external packages are wrapped [fast: false, auto-fix: false]
|
||||
#- wsl # Whitespace Linter - Forces you to use empty lines! [fast: true, auto-fix: false]
|
||||
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Foomo web framework
|
||||
|
||||
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.
|
||||
86
Makefile
Normal file
86
Makefile
Normal file
@ -0,0 +1,86 @@
|
||||
.DEFAULT_GOAL:=help
|
||||
|
||||
## === Tasks ===
|
||||
|
||||
.PHONY: check
|
||||
## Run tests and linters
|
||||
check: tidy lint test
|
||||
|
||||
.PHONY: tidy
|
||||
## Run go mod tidy
|
||||
tidy: files=$(shell find . -type f -name go.mod)
|
||||
tidy: dirs=$(foreach file,$(files),$(dir $(file)) )
|
||||
tidy:
|
||||
@for dir in $(dirs); do cd $$dir && go mod tidy; done
|
||||
|
||||
.PHONY: outdated
|
||||
## Show outdated direct dependencies
|
||||
outdated: files=$(shell find . -type f -name go.mod)
|
||||
outdated: dirs=$(foreach file,$(files),$(dir $(file)) )
|
||||
outdated:
|
||||
@for dir in $(dirs); do cd $$dir && go list -u -m -json all | go-mod-outdated -update -direct; done
|
||||
|
||||
.PHONY: test
|
||||
## Run tests
|
||||
test:
|
||||
go test -v ./...
|
||||
|
||||
.PHONY: lint
|
||||
## Run linter
|
||||
lint: files=$(shell find . -type f -name go.mod)
|
||||
lint: dirs=$(foreach file,$(files),$(dir $(file)) )
|
||||
lint:
|
||||
@for dir in $(dirs); do cd $$dir && golangci-lint run; done
|
||||
|
||||
.PHONY: lint.fix
|
||||
## Fix lint violations
|
||||
lint.fix: files=$(shell find . -type f -name go.mod)
|
||||
lint.fix: dirs=$(foreach file,$(files),$(dir $(file)) )
|
||||
lint.fix:
|
||||
@for dir in $(dirs); do cd $$dir && golangci-lint run --fix; done
|
||||
|
||||
.PHONY: lint.super
|
||||
## Run super linter
|
||||
lint.super:
|
||||
docker run --rm -it \
|
||||
-e 'RUN_LOCAL=true' \
|
||||
-e 'DEFAULT_BRANCH=main' \
|
||||
-e 'IGNORE_GITIGNORED_FILES=true' \
|
||||
-e 'VALIDATE_JSCPD=false' \
|
||||
-e 'VALIDATE_GO=false' \
|
||||
-v $(PWD):/tmp/lint \
|
||||
github/super-linter
|
||||
|
||||
## === Utils ===
|
||||
|
||||
## Show help text
|
||||
help:
|
||||
@awk '{ \
|
||||
if ($$0 ~ /^.PHONY: [a-zA-Z\-\_0-9]+$$/) { \
|
||||
helpCommand = substr($$0, index($$0, ":") + 2); \
|
||||
if (helpMessage) { \
|
||||
printf "\033[36m%-23s\033[0m %s\n", \
|
||||
helpCommand, helpMessage; \
|
||||
helpMessage = ""; \
|
||||
} \
|
||||
} else if ($$0 ~ /^[a-zA-Z\-\_0-9.]+:/) { \
|
||||
helpCommand = substr($$0, 0, index($$0, ":")); \
|
||||
if (helpMessage) { \
|
||||
printf "\033[36m%-23s\033[0m %s\n", \
|
||||
helpCommand, helpMessage"\n"; \
|
||||
helpMessage = ""; \
|
||||
} \
|
||||
} else if ($$0 ~ /^##/) { \
|
||||
if (helpMessage) { \
|
||||
helpMessage = helpMessage"\n "substr($$0, 3); \
|
||||
} else { \
|
||||
helpMessage = substr($$0, 3); \
|
||||
} \
|
||||
} else { \
|
||||
if (helpMessage) { \
|
||||
print "\n "helpMessage"\n" \
|
||||
} \
|
||||
helpMessage = ""; \
|
||||
} \
|
||||
}' \
|
||||
$(MAKEFILE_LIST)
|
||||
29
README.md
Normal file
29
README.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Project Oriented SHELL (posh)
|
||||
|
||||
> think of `posh` as an interactive and hackable Makefile
|
||||
|
||||
## Installing
|
||||
|
||||
Install the latest release of the cli:
|
||||
|
||||
````bash
|
||||
$ brew update
|
||||
$ brew install brew install foomo/posh
|
||||
````
|
||||
|
||||
## Usage
|
||||
|
||||
To start using posh, go into your project and run:
|
||||
|
||||
```bash
|
||||
$ cd your/project
|
||||
$ posh init
|
||||
```
|
||||
|
||||
This will generate the standard layout for posh which can be changed as required through `.posh.yaml`.
|
||||
|
||||
Once initialized you can start posh through:
|
||||
|
||||
```bash
|
||||
$ posh prompt
|
||||
```
|
||||
33
cmd/depenencies.go
Normal file
33
cmd/depenencies.go
Normal file
@ -0,0 +1,33 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/foomo/posh/internal/util"
|
||||
"github.com/foomo/posh/pkg/config"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// dependenciesCmd represents the dependencies command
|
||||
var dependenciesCmd = &cobra.Command{
|
||||
Use: "dependencies",
|
||||
Short: "Run dependency validations",
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
var cfg config.Dependencies
|
||||
if err := viper.UnmarshalKey("dependencies", &cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
plg, err := util.LoadPlugin(cmd.Context(), m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return plg.Dependencies(cmd.Context(), cfg)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(dependenciesCmd)
|
||||
}
|
||||
40
cmd/exec.go
Normal file
40
cmd/exec.go
Normal file
@ -0,0 +1,40 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/foomo/posh/internal/util"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// execCmd represents the exec command
|
||||
var execCmd = &cobra.Command{
|
||||
Use: "exec",
|
||||
Short: "Execute a single Project Oriented Shell command",
|
||||
Args: cobra.ArbitraryArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("missing [cmd] argument")
|
||||
}
|
||||
|
||||
plg, err := util.LoadPlugin(cmd.Context(), m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return plg.Execute(cmd.Context(), args)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(execCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
// Cobra supports Persistent Flags which will work for this command
|
||||
// and all subcommands, e.g.:
|
||||
// execCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||
|
||||
// Cobra supports local flags which will only run when this command
|
||||
// is called directly, e.g.:
|
||||
// execCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
||||
49
cmd/init.go
Normal file
49
cmd/init.go
Normal file
@ -0,0 +1,49 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/foomo/posh/embed"
|
||||
"github.com/foomo/posh/pkg/scaffold"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// initCmd represents the init command
|
||||
var initCmd = &cobra.Command{
|
||||
Use: "init [path]",
|
||||
Short: "Initialize a Project Oriented Shell",
|
||||
Long: `Initialize (posh init) will create a new Project Oriented Shell with the appropriate structure.
|
||||
|
||||
Posh init must be run inside of a go module (please run "go mod init <MODNAME> first)"`,
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(args) > 0 && args[0] != "." {
|
||||
wd = filepath.Join(wd, args[0])
|
||||
}
|
||||
|
||||
fs, err := embed.Scaffold("init")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sc, err := scaffold.New(
|
||||
scaffold.WithLogger(l),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sc.Render(fs, wd, nil)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(initCmd)
|
||||
}
|
||||
33
cmd/packages.go
Normal file
33
cmd/packages.go
Normal file
@ -0,0 +1,33 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/foomo/posh/internal/util"
|
||||
"github.com/foomo/posh/pkg/config"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// packagesCmd represents the dependencies command
|
||||
var packagesCmd = &cobra.Command{
|
||||
Use: "packages",
|
||||
Short: "Check and install required packages.",
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
var cfg []config.Package
|
||||
if err := viper.UnmarshalKey("packages", &cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
plg, err := util.LoadPlugin(cmd.Context(), m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return plg.Packages(cmd.Context(), cfg)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(packagesCmd)
|
||||
}
|
||||
33
cmd/prompt.go
Normal file
33
cmd/prompt.go
Normal file
@ -0,0 +1,33 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/foomo/posh/internal/util"
|
||||
"github.com/foomo/posh/pkg/config"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// promptCmd represents the prompt command
|
||||
var promptCmd = &cobra.Command{
|
||||
Use: "prompt",
|
||||
Short: "Start the interactive Project Oriented Shell",
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
var cfg config.Prompt
|
||||
if err := viper.UnmarshalKey("prompt", &cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
plg, err := util.LoadPlugin(cmd.Context(), m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return plg.Prompt(cmd.Context(), cfg)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(promptCmd)
|
||||
}
|
||||
134
cmd/root.go
Normal file
134
cmd/root.go
Normal file
@ -0,0 +1,134 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/foomo/posh/pkg/plugin"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
const (
|
||||
EnvProjectRoot = "PROJECT_ROOT"
|
||||
)
|
||||
|
||||
var (
|
||||
l log.Logger
|
||||
m *plugin.Manager
|
||||
flagLevel string
|
||||
flagConfig string
|
||||
flagNoColor bool
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "posh",
|
||||
Short: "Start the Project Oriented Shell",
|
||||
Long: `Start the Project Oriented Shell in interactive mode.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// use the hypothetical UnknownArgs() pflag API
|
||||
fmt.Println(args)
|
||||
return
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
osInterrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(osInterrupt, os.Interrupt)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer func() {
|
||||
signal.Stop(osInterrupt)
|
||||
cancel()
|
||||
}()
|
||||
go func() {
|
||||
<-osInterrupt
|
||||
l.Debug("received interrupt")
|
||||
cancel()
|
||||
}()
|
||||
|
||||
if err := rootCmd.ExecuteContext(ctx); errors.Is(err, context.Canceled) {
|
||||
l.Warn(err.Error())
|
||||
os.Exit(0)
|
||||
} else if err != nil {
|
||||
l.Error(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
cobra.OnInitialize(initialize)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
|
||||
rootCmd.PersistentFlags().BoolVar(&flagNoColor, "no-color", false, "disabled colors (default is false)")
|
||||
rootCmd.PersistentFlags().StringVar(&flagLevel, "level", "info", "set log level (default is warn)")
|
||||
rootCmd.PersistentFlags().StringVar(&flagConfig, "config", "", "config file (default is $HOME/.posh.yaml)")
|
||||
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().Bool("no-validate", false, "Skip validation")
|
||||
}
|
||||
|
||||
// initialize reads in config file and ENV variables if set.
|
||||
func initialize() {
|
||||
// setup logger
|
||||
if value, err := log.NewPTerm(
|
||||
log.PTermWithDisableColor(flagNoColor),
|
||||
log.PTermWithLevel(log.GetLevel(flagLevel)),
|
||||
); err != nil {
|
||||
cobra.CheckErr(err)
|
||||
} else {
|
||||
l = value
|
||||
}
|
||||
|
||||
// setup viper
|
||||
if flagConfig != "" {
|
||||
// Use config file from the flag.
|
||||
viper.SetConfigFile(flagConfig)
|
||||
} else {
|
||||
wd, err := os.Getwd()
|
||||
l.Must(err)
|
||||
viper.AddConfigPath(wd)
|
||||
viper.SetConfigType("yaml")
|
||||
viper.SetConfigName(".posh")
|
||||
}
|
||||
|
||||
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||
viper.AutomaticEnv()
|
||||
|
||||
l.Must(viper.ReadInConfig())
|
||||
l.Debug("using config file:", viper.ConfigFileUsed())
|
||||
|
||||
// validate version
|
||||
if v := viper.GetString("version"); v != "v1.0" {
|
||||
l.Must(fmt.Errorf("invalid config version: %s (v1.0)", v))
|
||||
}
|
||||
|
||||
// setup env
|
||||
if value := os.Getenv(EnvProjectRoot); value != "" {
|
||||
// continue
|
||||
} else if value, err := os.Getwd(); err != nil {
|
||||
l.Must(errors.Wrap(err, "failed to retrieve project root"))
|
||||
} else if err := os.Setenv(EnvProjectRoot, value); err != nil {
|
||||
l.Must(errors.Wrap(err, "failed to set project root env"))
|
||||
}
|
||||
for key, value := range viper.GetStringMapString("env") {
|
||||
l.Must(os.Setenv(key, os.ExpandEnv(value)))
|
||||
}
|
||||
|
||||
// setup manager
|
||||
var err error
|
||||
m, err = plugin.NewManager(l)
|
||||
l.Must(err)
|
||||
}
|
||||
23
cmd/version.go
Normal file
23
cmd/version.go
Normal file
@ -0,0 +1,23 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const Version = "develop"
|
||||
|
||||
// versionCmd represents the version command
|
||||
var versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print the version",
|
||||
Long: `If unsure which version of the CLI you are using, you can use this command to print the version of the CLI.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(Version)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(versionCmd)
|
||||
}
|
||||
14
embed/embed.go
Normal file
14
embed/embed.go
Normal file
@ -0,0 +1,14 @@
|
||||
package embed
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
//go:embed scaffold
|
||||
var scaffold embed.FS
|
||||
|
||||
func Scaffold(path string) (fs.FS, error) {
|
||||
return fs.Sub(scaffold, filepath.Join("scaffold", path))
|
||||
}
|
||||
4
embed/scaffold/init/$.gitignore
Normal file
4
embed/scaffold/init/$.gitignore
Normal file
@ -0,0 +1,4 @@
|
||||
*.so
|
||||
*.lock
|
||||
tmp/
|
||||
config/
|
||||
1
embed/scaffold/init/$.posh.yaml
Normal file
1
embed/scaffold/init/$.posh.yaml
Normal file
@ -0,0 +1 @@
|
||||
Version: 1.0
|
||||
96
embed/scaffold/init/plugin.go
Normal file
96
embed/scaffold/init/plugin.go
Normal file
@ -0,0 +1,96 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/fender/fend"
|
||||
"github.com/foomo/posh/pkg/cache"
|
||||
"github.com/foomo/posh/pkg/command"
|
||||
"github.com/foomo/posh/pkg/config"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/foomo/posh/pkg/ownbrew"
|
||||
"github.com/foomo/posh/pkg/plugin"
|
||||
"github.com/foomo/posh/pkg/prompt"
|
||||
"github.com/foomo/posh/pkg/prompt/history"
|
||||
"github.com/foomo/posh/pkg/validate"
|
||||
)
|
||||
|
||||
type Plugin struct {
|
||||
l log.Logger
|
||||
c cache.Cache
|
||||
commands command.Commands
|
||||
}
|
||||
|
||||
func New(l log.Logger) (plugin.Plugin, error) {
|
||||
inst := &Plugin{
|
||||
l: l,
|
||||
commands: command.Commands{},
|
||||
}
|
||||
|
||||
// add commands
|
||||
inst.commands.Add(
|
||||
command.NewExit(l),
|
||||
command.NewHelp(l, inst.commands),
|
||||
)
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
func (p *Plugin) Prompt(ctx context.Context, cfg config.Prompt) error {
|
||||
sh, err := prompt.New(p.l,
|
||||
prompt.WithTitle(cfg.Title),
|
||||
prompt.WithPrefix(cfg.Prefix),
|
||||
prompt.WithContext(ctx),
|
||||
prompt.WithCommands(p.commands),
|
||||
prompt.WithFileHistory(
|
||||
history.FileWithLimit(cfg.History.Limit),
|
||||
history.FileWithFilename(cfg.History.Filename),
|
||||
history.FileWithLockFilename(cfg.History.LockFilename),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return sh.Run()
|
||||
}
|
||||
|
||||
func (p *Plugin) Execute(ctx context.Context, args []string) error {
|
||||
r, err := readline.New(p.l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := r.Parse(strings.Join(args, " ")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c := p.commands.Get(r.Cmd()); c == nil {
|
||||
return fmt.Errorf("invalid [cmd] argument: %s", r.Cmd())
|
||||
} else if err := c.Execute(ctx, r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Plugin) Dependencies(ctx context.Context, cfg config.Dependencies) error {
|
||||
var fends []fend.Fend
|
||||
fends = append(fends, validate.DependenciesEnvs(p.l, cfg.Envs)...)
|
||||
fends = append(fends, validate.DependenciesScripts(ctx, p.l, cfg.Scripts)...)
|
||||
fends = append(fends, validate.DependenciesPackages(ctx, p.l, cfg.Packages)...)
|
||||
if fendErr, err := fend.First(fends...); err != nil {
|
||||
return err
|
||||
} else if fendErr != nil {
|
||||
return fendErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Plugin) Packages(ctx context.Context, cfg []config.Package) error {
|
||||
brew, err := ownbrew.New(p.l,
|
||||
ownbrew.WithPackages(cfg...),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return brew.Install(ctx)
|
||||
}
|
||||
131
example/.posh.yaml
Normal file
131
example/.posh.yaml
Normal file
@ -0,0 +1,131 @@
|
||||
version: v1.0
|
||||
|
||||
prompt:
|
||||
title: "Demo"
|
||||
prefix: "demo >"
|
||||
history:
|
||||
limit: 100
|
||||
filename: .posh/history
|
||||
lockFilename: .posh/history.lock
|
||||
|
||||
env:
|
||||
GOPROXY: "https://proxy.golang.org,direct"
|
||||
PATH: "${PROJECT_ROOT}/node_modules/.bin:${PROJECT_ROOT}/bin:${PATH}"
|
||||
|
||||
plugin:
|
||||
source: .posh/plugin.go
|
||||
provider: New
|
||||
|
||||
packages:
|
||||
- name: gotsrpc
|
||||
version: 2.6.2
|
||||
# - name: helm
|
||||
# version: 3.8.1
|
||||
# - name: husky
|
||||
# version: 1.7.0
|
||||
# - name: hygen
|
||||
# version: 6.1.0
|
||||
# - name: k6
|
||||
# version: 0.34.1
|
||||
# - name: k9s
|
||||
# version: 0.24.15
|
||||
#
|
||||
|
||||
dependencies:
|
||||
envs:
|
||||
- name: GITHUB_TOKEN
|
||||
help: |
|
||||
You need to export a GITHUB_TOKEN in your environment!
|
||||
|
||||
To do so, create an access token on https://github.com/settings/tokens with the following permissions:
|
||||
|
||||
- repo
|
||||
- write:packages
|
||||
- delete:packages
|
||||
|
||||
and export it into your environment e.g. ZSH:
|
||||
|
||||
$ vi ~/.zshenv
|
||||
|
||||
export GITHUB_TOKEN=XXX
|
||||
# scripts:
|
||||
# - name: op
|
||||
# command: op account --account <ACCOUNT> get > /dev/null 2>&1
|
||||
# help: |
|
||||
# You're not yet logged into the 1Password account!
|
||||
#
|
||||
# $ op signin <ACCOUNT>.1password.eu <EMAIL>
|
||||
# - name: npm
|
||||
# command: op account --account <ACCOUNT> get > /dev/null 2>&1
|
||||
# help: |
|
||||
# You're not yet logged into the github npm registry!
|
||||
#
|
||||
# $ npm login --scope=@<SCOPE> --registry=https://npm.pkg.github.com
|
||||
# Username: [GITHUB_USERNAME]
|
||||
# Password: [GITHUB_TOKEN]
|
||||
# Email: [EMAIL]
|
||||
packages:
|
||||
- name: git
|
||||
version: '~2'
|
||||
command: git version | awk '{print $3}'
|
||||
help: |
|
||||
Please ensure you have 'git' installed in the required version: %s!
|
||||
|
||||
$ brew update
|
||||
$ brew install git
|
||||
- name: go
|
||||
version: '>=1.19.4'
|
||||
command: go env GOVERSION | cut -c3-
|
||||
help: |
|
||||
Please ensure you have 'go' installed in the required version: %s!
|
||||
|
||||
$ brew update
|
||||
$ brew install go
|
||||
- name: op
|
||||
version: '~2'
|
||||
command: op --version
|
||||
help: |
|
||||
Please ensure you have the 1Password cli 'op' installed in the required version: %s!
|
||||
|
||||
$ brew update
|
||||
$ brew install 1password-cli
|
||||
- name: node
|
||||
version: '~16'
|
||||
command: node --version
|
||||
help: |
|
||||
Please ensure you have 'node' installed in the required version: %s!
|
||||
|
||||
We strongly recommend installing 'nvm' trough:
|
||||
|
||||
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash
|
||||
|
||||
If you already have installed 'nvm' just run the following command to read in the .nvmrc:
|
||||
|
||||
$ nvm use
|
||||
- name: yarn
|
||||
version: '~1'
|
||||
command: yarn --version
|
||||
help: |
|
||||
Please ensure you have 'yarn' installed in the required version: %s!
|
||||
|
||||
$ npm install -g yarn
|
||||
- name: tsh
|
||||
version: '>=10'
|
||||
command: tsh version --skip-version-check | awk 'NR==1{print $2}'
|
||||
help: |
|
||||
Please ensure you have 'teleport' installed in the required version: %s!
|
||||
|
||||
$ brew update
|
||||
$ brew install teleport
|
||||
- name: goimports
|
||||
version: '>=2022'
|
||||
command: date -r $(which goimports) +%Y.%-m.%-d
|
||||
help: |
|
||||
Please ensure you have 'goimports' installed in a recent version: %s!
|
||||
|
||||
$ go install golang.org/x/tools/cmd/goimports@latest
|
||||
|
||||
# 1Password
|
||||
onePassword:
|
||||
account: <ACCOUNT>
|
||||
tokenFilename: .posh/config/.op
|
||||
4
example/.posh/.gitignore
vendored
Normal file
4
example/.posh/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*.so
|
||||
*.lock
|
||||
tmp/
|
||||
config/
|
||||
130
example/.posh/command/gogenerate.go
Normal file
130
example/.posh/command/gogenerate.go
Normal file
@ -0,0 +1,130 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/fs"
|
||||
"os"
|
||||
|
||||
"github.com/charlievieth/fastwalk"
|
||||
"github.com/foomo/posh/pkg/cache"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/foomo/posh/pkg/prompt"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
"github.com/foomo/posh/pkg/shell"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// GoGenerate command
|
||||
type GoGenerate struct {
|
||||
l log.Logger
|
||||
name string
|
||||
cache cache.Namespace
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// NewGoGenerate command
|
||||
func NewGoGenerate(l log.Logger, cache cache.Cache) *GoGenerate {
|
||||
return &GoGenerate{
|
||||
l: l,
|
||||
name: "gogenerate",
|
||||
cache: cache.Get("gogenerate"),
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c *GoGenerate) Name() string {
|
||||
return c.name
|
||||
}
|
||||
|
||||
func (c *GoGenerate) Description() string {
|
||||
return "run go generate on generate.go files"
|
||||
}
|
||||
|
||||
func (c *GoGenerate) Complete(ctx context.Context, r *readline.Readline, d prompt.Document) (suggests []prompt.Suggest) {
|
||||
if r.Args().LenLte(1) {
|
||||
suggests = c.completePaths()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *GoGenerate) Validate(ctx context.Context, r *readline.Readline) error {
|
||||
switch {
|
||||
case r.Args().LenIs(0):
|
||||
return nil
|
||||
case r.Args().LenGt(1):
|
||||
return errors.New("too many parameters")
|
||||
}
|
||||
if info, err := os.Stat(r.Args().At(1)); err != nil || info.IsDir() {
|
||||
return errors.Errorf("invalid [path] parameter: %s", r.Args().At(1))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *GoGenerate) Execute(ctx context.Context, r *readline.Readline) error {
|
||||
var paths []string
|
||||
if r.Args().HasIndex(0) {
|
||||
paths = append(paths, r.Args().At(0))
|
||||
} else {
|
||||
paths = c.paths()
|
||||
}
|
||||
|
||||
for _, value := range paths {
|
||||
c.l.Info("go generate:", value)
|
||||
if err := shell.New(ctx, c.l,
|
||||
"go", "generate", value,
|
||||
).
|
||||
Args(r.AdditionalArgs()...).
|
||||
Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *GoGenerate) Help() string {
|
||||
return `Looks for generate.go files and runs them.
|
||||
|
||||
Usage:
|
||||
gogenerate [path]
|
||||
|
||||
Examples:
|
||||
gogenerate tidy ./path/to/generate.go
|
||||
`
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c *GoGenerate) completePaths() (suggest []prompt.Suggest) {
|
||||
for _, value := range c.paths() {
|
||||
suggest = append(suggest, prompt.Suggest{Text: value})
|
||||
}
|
||||
return suggest
|
||||
}
|
||||
|
||||
func (c *GoGenerate) paths() []string {
|
||||
return c.cache.Get("paths", func() interface{} {
|
||||
var ret []string
|
||||
if err := fastwalk.Walk(&fastwalk.Config{
|
||||
Follow: false,
|
||||
}, ".", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.Name() == "generate.go" {
|
||||
ret = append(ret, path)
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
c.l.Debug("failed to walk files", err.Error())
|
||||
}
|
||||
return ret
|
||||
}).([]string)
|
||||
}
|
||||
197
example/.posh/command/gomod.go
Normal file
197
example/.posh/command/gomod.go
Normal file
@ -0,0 +1,197 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/fs"
|
||||
"path"
|
||||
|
||||
"github.com/charlievieth/fastwalk"
|
||||
"github.com/foomo/posh/pkg/cache"
|
||||
"github.com/foomo/posh/pkg/command/tree"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/foomo/posh/pkg/prompt"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
"github.com/foomo/posh/pkg/shell"
|
||||
)
|
||||
|
||||
// GoMod command
|
||||
type GoMod struct {
|
||||
l log.Logger
|
||||
cache cache.Namespace
|
||||
parser *tree.Root
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// NewGoMod command
|
||||
func NewGoMod(l log.Logger, cache cache.Cache) *GoMod {
|
||||
inst := &GoMod{
|
||||
l: l,
|
||||
cache: cache.Get("gomod"),
|
||||
}
|
||||
|
||||
pathArg := &tree.Arg{
|
||||
Name: "path",
|
||||
Optional: true,
|
||||
Suggest: inst.completePaths,
|
||||
}
|
||||
|
||||
inst.parser = &tree.Root{
|
||||
Name: "gomod",
|
||||
Nodes: []*tree.Node{
|
||||
{
|
||||
Name: "tidy",
|
||||
Description: "run go mod tidy",
|
||||
Args: []*tree.Arg{pathArg},
|
||||
Execute: inst.tidy,
|
||||
},
|
||||
{
|
||||
Name: "download",
|
||||
Description: "run go mod download",
|
||||
Args: []*tree.Arg{pathArg},
|
||||
Execute: inst.download,
|
||||
},
|
||||
{
|
||||
Name: "outdated",
|
||||
Description: "show go mod outdated",
|
||||
Args: []*tree.Arg{pathArg},
|
||||
Execute: inst.outdated,
|
||||
},
|
||||
},
|
||||
}
|
||||
return inst
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c *GoMod) Name() string {
|
||||
return c.parser.Name
|
||||
}
|
||||
|
||||
func (c *GoMod) Description() string {
|
||||
return "run go mod"
|
||||
}
|
||||
|
||||
func (c *GoMod) Complete(ctx context.Context, r *readline.Readline, d prompt.Document) (suggests []prompt.Suggest) {
|
||||
return c.parser.Complete(ctx, r)
|
||||
}
|
||||
|
||||
func (c *GoMod) Execute(ctx context.Context, r *readline.Readline) error {
|
||||
return c.parser.Execute(ctx, r)
|
||||
}
|
||||
|
||||
func (c *GoMod) Help() string {
|
||||
return `Looks for go.mod files and runs the given command.
|
||||
|
||||
Usage:
|
||||
gomod [command] <path>
|
||||
|
||||
Available commands:
|
||||
tidy run go mod tidy on specific or all paths
|
||||
download run go mod download on specific or all paths
|
||||
outdated list outdated packages on specific or all paths
|
||||
|
||||
Examples:
|
||||
gomod tidy ./path
|
||||
`
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c *GoMod) tidy(ctx context.Context, r *readline.Readline) error {
|
||||
var paths []string
|
||||
if r.Args().HasIndex(1) {
|
||||
paths = []string{r.Args().At(1)}
|
||||
} else {
|
||||
paths = c.paths()
|
||||
}
|
||||
for _, value := range paths {
|
||||
c.l.Info("go mod tidy:", value)
|
||||
if err := shell.New(ctx, c.l,
|
||||
"go", "mod", "tidy",
|
||||
).
|
||||
Args(r.AdditionalArgs()...).
|
||||
Dir(value).
|
||||
Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *GoMod) download(ctx context.Context, r *readline.Readline) error {
|
||||
var paths []string
|
||||
if r.Args().HasIndex(1) {
|
||||
paths = []string{r.Args().At(1)}
|
||||
} else {
|
||||
paths = c.paths()
|
||||
}
|
||||
for _, value := range paths {
|
||||
c.l.Info("go mod download:", value)
|
||||
if err := shell.New(ctx, c.l,
|
||||
"go", "mod", "tidy",
|
||||
).
|
||||
Args(r.AdditionalArgs()...).
|
||||
Dir(value).
|
||||
Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *GoMod) outdated(ctx context.Context, r *readline.Readline) error {
|
||||
var paths []string
|
||||
if r.Args().HasIndex(1) {
|
||||
paths = []string{r.Args().At(1)}
|
||||
} else {
|
||||
paths = c.paths()
|
||||
}
|
||||
for _, value := range paths {
|
||||
c.l.Info("go mod outdated:", value)
|
||||
if err := shell.New(ctx, c.l,
|
||||
"go", "list",
|
||||
"-u", "-m", "-json", "all",
|
||||
"|", "go-mod-outdated", "-update", "-direct",
|
||||
).
|
||||
Args(r.AdditionalArgs()...).
|
||||
Dir(value).
|
||||
Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *GoMod) completePaths(ctx context.Context, p *tree.Root, r *readline.Readline) (suggest []prompt.Suggest) {
|
||||
for _, value := range c.paths() {
|
||||
suggest = append(suggest, prompt.Suggest{Text: value})
|
||||
}
|
||||
return suggest
|
||||
}
|
||||
|
||||
func (c *GoMod) paths() []string {
|
||||
return c.cache.Get("paths", func() interface{} {
|
||||
var ret []string
|
||||
if err := fastwalk.Walk(&fastwalk.Config{
|
||||
Follow: false,
|
||||
}, ".", func(p string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.Name() == "go.mod" {
|
||||
ret = append(ret, path.Dir(p))
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
c.l.Debug("failed to walk files", err.Error())
|
||||
}
|
||||
return ret
|
||||
}).([]string)
|
||||
}
|
||||
63
example/.posh/go.mod
Normal file
63
example/.posh/go.mod
Normal file
@ -0,0 +1,63 @@
|
||||
module github.com/foomo/posh/example/posh
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/charlievieth/fastwalk v1.0.1
|
||||
github.com/foomo/fender v0.4.4
|
||||
github.com/foomo/posh v0.0.0-00010101000000-000000000000
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/spf13/viper v1.14.0
|
||||
)
|
||||
|
||||
require (
|
||||
atomicgo.dev/cursor v0.1.1 // indirect
|
||||
atomicgo.dev/keyboard v0.2.8 // indirect
|
||||
github.com/1Password/connect-sdk-go v1.5.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/c-bata/go-prompt v0.2.6 // indirect
|
||||
github.com/containerd/console v1.0.3 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-playground/locales v0.14.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.11.0 // indirect
|
||||
github.com/gofrs/flock v0.8.1 // indirect
|
||||
github.com/gookit/color v1.5.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/joho/godotenv v1.4.0 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/lithammer/fuzzysearch v1.1.5 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/mattn/go-tty v0.0.3 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||
github.com/pkg/term v1.1.0 // indirect
|
||||
github.com/pterm/pterm v0.12.51 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/spf13/afero v1.9.2 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
|
||||
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.3.0 // indirect
|
||||
golang.org/x/sys v0.2.0 // indirect
|
||||
golang.org/x/term v0.2.0 // indirect
|
||||
golang.org/x/text v0.4.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/c-bata/go-prompt v0.2.6 => github.com/franklinkim/go-prompt v0.2.7-0.20210427061716-a8f4995d7aa5
|
||||
github.com/foomo/posh => ../../
|
||||
)
|
||||
632
example/.posh/go.sum
Normal file
632
example/.posh/go.sum
Normal file
@ -0,0 +1,632 @@
|
||||
atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg=
|
||||
atomicgo.dev/cursor v0.1.1 h1:0t9sxQomCTRh5ug+hAMCs59x/UmC9QL6Ci5uosINKD4=
|
||||
atomicgo.dev/cursor v0.1.1/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU=
|
||||
atomicgo.dev/keyboard v0.2.8 h1:Di09BitwZgdTV1hPyX/b9Cqxi8HVuJQwWivnZUEqlj4=
|
||||
atomicgo.dev/keyboard v0.2.8/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
|
||||
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.44.3/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 v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/1Password/connect-sdk-go v1.5.0 h1:F0WJcLSzGg3iXEDY49/ULdszYKsQLGTzn+2cyYXqiyk=
|
||||
github.com/1Password/connect-sdk-go v1.5.0/go.mod h1:TdynFeyvaRoackENbJ8RfJokH+WAowAu1MLmUbdMq6s=
|
||||
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/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM=
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
|
||||
github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs=
|
||||
github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8=
|
||||
github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII=
|
||||
github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k=
|
||||
github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI=
|
||||
github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c=
|
||||
github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE=
|
||||
github.com/MarvinJWendt/testza v0.5.1 h1:a9Fqx6vQrHQ4CyiaLhktfTTelwGotmFWy8MNhyaohw8=
|
||||
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
|
||||
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||
github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/charlievieth/fastwalk v1.0.1 h1:jW01w8OCFdKS9JvAcnI+JHhWU/FuIEmNb24Ri9p7OVg=
|
||||
github.com/charlievieth/fastwalk v1.0.1/go.mod h1:dryXgMJyGHbMrAmmnF0/EJNBbZaihlwcNud5IuGyogU=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/foomo/fender v0.4.4 h1:zs5jQGAVIygn552beaFXow4gRCuCKRl4D4qGiED6WeQ=
|
||||
github.com/foomo/fender v0.4.4/go.mod h1:cUmK1Gg1wrue5ZzRdGj92Ong4jBcSbuuSbINqaBXZaE=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/franklinkim/go-prompt v0.2.7-0.20210427061716-a8f4995d7aa5 h1:kXNtle4AoQnngdm+gwt4ku6Llbzw3EFHgZYpL618JaI=
|
||||
github.com/franklinkim/go-prompt v0.2.7-0.20210427061716-a8f4995d7aa5/go.mod h1:+syUfnvYJUO5A+6QMQYXAyzkxHMNlj9dH2LIeQfBSjc=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw=
|
||||
github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/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/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
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/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
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.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
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/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
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/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
|
||||
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
|
||||
github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
|
||||
github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg=
|
||||
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 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
|
||||
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/karrick/godirwalk v1.17.0 h1:b4kY7nqDdioR/6qnbHQyDvmA17u5G1cZ6J+CZXwSWoI=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.2.0 h1:4ZexSFt8agMNzNisrsilL6RClWDC5YJnLHNIfTy4iuc=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
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/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c=
|
||||
github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q=
|
||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI=
|
||||
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
|
||||
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
|
||||
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pkg/term v1.1.0 h1:xIAAdCMh3QIAy+5FrE8Ad8XoDhEU4ufwbaSozViP9kk=
|
||||
github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw=
|
||||
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI=
|
||||
github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg=
|
||||
github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE=
|
||||
github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU=
|
||||
github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
|
||||
github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
|
||||
github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
|
||||
github.com/pterm/pterm v0.12.51 h1:iwhNG1FhQMgks+5kVyr/ClRk3WJCuL907nJN7RqmEpw=
|
||||
github.com/pterm/pterm v0.12.51/go.mod h1:79BLm4vos2z+eOoHnDG7ZWuYtLaSStyaspKjGmSoxc4=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
|
||||
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
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.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
|
||||
github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
|
||||
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
||||
github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
|
||||
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
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/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
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/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
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.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/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-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-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
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/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-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-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
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/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/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-20190206041539-40960b6deb8e/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-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-20190524140312-2c0ae7006135/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-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/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-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
|
||||
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
|
||||
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
|
||||
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/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
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/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
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/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
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=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
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.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
70
example/.posh/history
Normal file
70
example/.posh/history
Normal file
@ -0,0 +1,70 @@
|
||||
ls -loah
|
||||
ls -loa
|
||||
ls -lo
|
||||
ping
|
||||
demo
|
||||
help foo
|
||||
help exit | foo
|
||||
help ex
|
||||
help exit
|
||||
help exit foo
|
||||
help
|
||||
help esit
|
||||
help exit | bat
|
||||
help exit -- exit
|
||||
help exit -- --exit
|
||||
help exit
|
||||
gomod
|
||||
gomod download ./.posh/go.mod
|
||||
gomod download --foo -- bar
|
||||
gomod download --foo -- --bar
|
||||
gomod download
|
||||
gomod download --foo
|
||||
gomod download --foo xxx
|
||||
gomod download --foo="xxx"
|
||||
gomod download -foo barfoo="xxx"
|
||||
gomod download -foo xx
|
||||
gomod download --bar me
|
||||
gomod download -bar me
|
||||
gomod download -foo me
|
||||
gomod download --foo=me
|
||||
gomod download -foo=me
|
||||
gomod download -foo
|
||||
gomod download bar one -foo
|
||||
gomod download bar one -foo me
|
||||
gomod download bar one --foo me
|
||||
gomod download one two --foo bar
|
||||
gomod download one two --foo me --twice
|
||||
gomod download one two --foo me
|
||||
gomod download one two three
|
||||
gomod download one two two --foo --bar
|
||||
gomod download one two two --foo me --bar
|
||||
gomod download one two two -foo me -bar you
|
||||
gomod download one two two -foo=me -bar you
|
||||
gomod download one two two -foo=yes -bar you
|
||||
gomod download one two two -foo='yes' -bar you
|
||||
gomod download one two two -foo="yes" -bar you
|
||||
gomod download one two two -foo "yes" -bar you
|
||||
gomod download one two two --foo "yes" --bar you
|
||||
gomod download one two two --foo "yes" --bar -- --bar
|
||||
gomod download one two two --foo yes --bar -- --bar
|
||||
gomod download one two two --foo yes --bar -- foo --bar
|
||||
gomod download one two two --foo yes --bar -- -one
|
||||
gomod download one two two --foo yes --bar -- -on
|
||||
gomod download one two two --foo yes --bar -- -o
|
||||
gomod download one two two --foo yes --bar -- --
|
||||
gomod download one two two --foo yes --bar -- --one --two
|
||||
gomod download one two two --foo yes --bar no -- --one
|
||||
gomod download one two two --foo yes --bar no -- --one two
|
||||
gomod outdated ./.posh/go.mod
|
||||
gomod tidy ./.posh/go.mod
|
||||
gogenerate
|
||||
cache clear
|
||||
gomod tidy
|
||||
gomod tidy .posh
|
||||
op signin kevin.kim@bestbytes.com
|
||||
op signin
|
||||
ls
|
||||
ifconfig
|
||||
ls -la
|
||||
cache list
|
||||
131
example/.posh/plugin.go
Normal file
131
example/.posh/plugin.go
Normal file
@ -0,0 +1,131 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/foomo/fender/fend"
|
||||
command2 "github.com/foomo/posh/example/posh/command"
|
||||
"github.com/foomo/posh/integration/onepassword"
|
||||
"github.com/foomo/posh/pkg/cache"
|
||||
"github.com/foomo/posh/pkg/command"
|
||||
"github.com/foomo/posh/pkg/config"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/foomo/posh/pkg/ownbrew"
|
||||
"github.com/foomo/posh/pkg/plugin"
|
||||
"github.com/foomo/posh/pkg/prompt"
|
||||
"github.com/foomo/posh/pkg/prompt/history"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
"github.com/foomo/posh/pkg/validate"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type Plugin struct {
|
||||
l log.Logger
|
||||
c cache.Cache
|
||||
commands command.Commands
|
||||
}
|
||||
|
||||
func New(l log.Logger) (plugin.Plugin, error) {
|
||||
inst := &Plugin{
|
||||
l: l,
|
||||
c: cache.MemoryCache{},
|
||||
commands: command.Commands{},
|
||||
}
|
||||
|
||||
var (
|
||||
err error
|
||||
onePasswordCfg onepassword.Config
|
||||
onePasswordClient *onepassword.OnePassword
|
||||
)
|
||||
|
||||
// load configurations
|
||||
l.Must(viper.UnmarshalKey("onePassword", &onePasswordCfg))
|
||||
|
||||
// create dependency instances
|
||||
onePasswordClient, err = onepassword.New(l, inst.c, onepassword.WithTokenFilename(onePasswordCfg.TokenFilename))
|
||||
l.Must(err)
|
||||
|
||||
// add commands
|
||||
inst.commands.Add(
|
||||
command2.NewGoMod(l, inst.c),
|
||||
command2.NewGoGenerate(l, inst.c),
|
||||
onepassword.NewCommand(l, onePasswordCfg, onePasswordClient),
|
||||
command.NewCache(l, inst.c),
|
||||
command.NewExit(l),
|
||||
command.NewHelp(l, inst.commands),
|
||||
)
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
func (p *Plugin) Prompt(ctx context.Context, cfg config.Prompt) error {
|
||||
sh, err := prompt.New(p.l,
|
||||
prompt.WithTitle(cfg.Title),
|
||||
prompt.WithPrefix(cfg.Prefix),
|
||||
prompt.WithContext(ctx),
|
||||
prompt.WithCommands(p.commands),
|
||||
prompt.WithCheckers(
|
||||
func(ctx context.Context, l log.Logger) (name, note string, ok bool) {
|
||||
return "one", "", true
|
||||
},
|
||||
func(ctx context.Context, l log.Logger) (name, note string, ok bool) {
|
||||
return "two", "please install", false
|
||||
},
|
||||
),
|
||||
prompt.WithFileHistory(
|
||||
history.FileWithLimit(cfg.History.Limit),
|
||||
history.FileWithFilename(cfg.History.Filename),
|
||||
history.FileWithLockFilename(cfg.History.LockFilename),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return sh.Run()
|
||||
}
|
||||
|
||||
func (p *Plugin) Execute(ctx context.Context, args []string) error {
|
||||
r, err := readline.New(p.l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := r.Parse(strings.Join(args, " ")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c := p.commands.Get(r.Cmd()); c == nil {
|
||||
return fmt.Errorf("invalid [cmd] argument: %s", r.Cmd())
|
||||
} else if err := c.Execute(ctx, r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Plugin) Dependencies(ctx context.Context, cfg config.Dependencies) error {
|
||||
var fends []fend.Fend
|
||||
fends = append(fends, validate.DependenciesEnvs(p.l, cfg.Envs)...)
|
||||
fends = append(fends, validate.DependenciesScripts(ctx, p.l, cfg.Scripts)...)
|
||||
fends = append(fends, validate.DependenciesPackages(ctx, p.l, cfg.Packages)...)
|
||||
fends = append(fends,
|
||||
validate.GitUser(ctx, p.l, validate.GitUserName, validate.GitUserEmail(`(.*)@(bestbytes\.com)`)),
|
||||
)
|
||||
if fendErr, err := fend.First(fends...); err != nil {
|
||||
return err
|
||||
} else if fendErr != nil {
|
||||
return fendErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Plugin) Packages(ctx context.Context, cfg []config.Package) error {
|
||||
brew, err := ownbrew.New(p.l,
|
||||
ownbrew.WithPackages(cfg...),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return brew.Install(ctx)
|
||||
}
|
||||
13
example/.posh/scripts/ownbrew/gotsrpc.sh
Executable file
13
example/.posh/scripts/ownbrew/gotsrpc.sh
Executable file
@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
source .posh/scripts/ownbrew/include.sh
|
||||
|
||||
curl -sfL "https://github.com/foomo/gotsrpc/releases/download/v${version}/gotsrpc_${version}_${os}_${arch}.tar.gz" -o "${TEMP_DIR}/gotsrpc.tar.gz"
|
||||
curl -sfL "https://github.com/foomo/gotsrpc/releases/download/v${version}/gotsrpc_${version}_checksums.txt" -o "${TEMP_DIR}/gotsrpc.tar.gz.sha256"
|
||||
|
||||
echo "$(cat "${TEMP_DIR}/gotsrpc.tar.gz.sha256" | grep "gotsrpc_${version}_${os}_${arch}.tar.gz" | awk '{print $1;}') ${TEMP_DIR}/gotsrpc.tar.gz" | shasum -a 256 --check --quiet
|
||||
|
||||
tar -xzvf "${TEMP_DIR}/gotsrpc.tar.gz" -C "${TEMP_DIR}" gotsrpc
|
||||
mv "${TEMP_DIR}/gotsrpc" "${BIN_DIR}/gotsrpc-${version}-${os}-${arch}"
|
||||
chmod a+x "${BIN_DIR}/gotsrpc-${version}-${os}-${arch}"
|
||||
rm "${TEMP_DIR}/gotsrpc.tar.gz" "${TEMP_DIR}/gotsrpc.tar.gz.sha256"
|
||||
5
example/.posh/scripts/ownbrew/include.sh
Normal file
5
example/.posh/scripts/ownbrew/include.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
version="${version:-${1}}"
|
||||
os="${os:-${2}}"
|
||||
arch="${arch:-${3}}"
|
||||
42
example/Makefile
Normal file
42
example/Makefile
Normal file
@ -0,0 +1,42 @@
|
||||
.DEFAULT_GOAL:=help
|
||||
|
||||
## === Tasks ===
|
||||
|
||||
.PHONY: posh
|
||||
posh:
|
||||
@posh dependencies
|
||||
@posh prompt
|
||||
|
||||
## === Utils ===
|
||||
|
||||
## Show help text
|
||||
help:
|
||||
@awk '{ \
|
||||
if ($$0 ~ /^.PHONY: [a-zA-Z\-\_0-9]+$$/) { \
|
||||
helpCommand = substr($$0, index($$0, ":") + 2); \
|
||||
if (helpMessage) { \
|
||||
printf "\033[36m%-23s\033[0m %s\n", \
|
||||
helpCommand, helpMessage; \
|
||||
helpMessage = ""; \
|
||||
} \
|
||||
} else if ($$0 ~ /^[a-zA-Z\-\_0-9.]+:/) { \
|
||||
helpCommand = substr($$0, 0, index($$0, ":")); \
|
||||
if (helpMessage) { \
|
||||
printf "\033[36m%-23s\033[0m %s\n", \
|
||||
helpCommand, helpMessage"\n"; \
|
||||
helpMessage = ""; \
|
||||
} \
|
||||
} else if ($$0 ~ /^##/) { \
|
||||
if (helpMessage) { \
|
||||
helpMessage = helpMessage"\n "substr($$0, 3); \
|
||||
} else { \
|
||||
helpMessage = substr($$0, 3); \
|
||||
} \
|
||||
} else { \
|
||||
if (helpMessage) { \
|
||||
print "\n "helpMessage"\n" \
|
||||
} \
|
||||
helpMessage = ""; \
|
||||
} \
|
||||
}' \
|
||||
$(MAKEFILE_LIST)
|
||||
9
example/cmd/posh/main.go
Normal file
9
example/cmd/posh/main.go
Normal file
@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("hello")
|
||||
}
|
||||
68
go.mod
Normal file
68
go.mod
Normal file
@ -0,0 +1,68 @@
|
||||
module github.com/foomo/posh
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/1Password/connect-sdk-go v1.5.0
|
||||
github.com/Masterminds/semver/v3 v3.2.0
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/c-bata/go-prompt v0.2.6
|
||||
github.com/foomo/fender v0.4.4
|
||||
github.com/gofrs/flock v0.8.1
|
||||
github.com/joho/godotenv v1.4.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pterm/pterm v0.12.51
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/viper v1.14.0
|
||||
)
|
||||
|
||||
require (
|
||||
atomicgo.dev/cursor v0.1.1 // indirect
|
||||
atomicgo.dev/keyboard v0.2.8 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/containerd/console v1.0.3 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-playground/locales v0.14.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.11.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gookit/color v1.5.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/huandu/xstrings v1.3.3 // indirect
|
||||
github.com/imdario/mergo v0.3.11 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/lithammer/fuzzysearch v1.1.5 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/mattn/go-tty v0.0.3 // indirect
|
||||
github.com/mitchellh/copystructure v1.0.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||
github.com/pkg/term v1.1.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/spf13/afero v1.9.2 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
|
||||
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.3.0 // indirect
|
||||
golang.org/x/sys v0.2.0 // indirect
|
||||
golang.org/x/term v0.2.0 // indirect
|
||||
golang.org/x/text v0.4.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/c-bata/go-prompt v0.2.6 => github.com/franklinkim/go-prompt v0.2.7-0.20210427061716-a8f4995d7aa5
|
||||
661
go.sum
Normal file
661
go.sum
Normal file
@ -0,0 +1,661 @@
|
||||
atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg=
|
||||
atomicgo.dev/cursor v0.1.1 h1:0t9sxQomCTRh5ug+hAMCs59x/UmC9QL6Ci5uosINKD4=
|
||||
atomicgo.dev/cursor v0.1.1/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU=
|
||||
atomicgo.dev/keyboard v0.2.8 h1:Di09BitwZgdTV1hPyX/b9Cqxi8HVuJQwWivnZUEqlj4=
|
||||
atomicgo.dev/keyboard v0.2.8/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
|
||||
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.44.3/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 v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/1Password/connect-sdk-go v1.5.0 h1:F0WJcLSzGg3iXEDY49/ULdszYKsQLGTzn+2cyYXqiyk=
|
||||
github.com/1Password/connect-sdk-go v1.5.0/go.mod h1:TdynFeyvaRoackENbJ8RfJokH+WAowAu1MLmUbdMq6s=
|
||||
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/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM=
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
|
||||
github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs=
|
||||
github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8=
|
||||
github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII=
|
||||
github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k=
|
||||
github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI=
|
||||
github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c=
|
||||
github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE=
|
||||
github.com/MarvinJWendt/testza v0.5.1 h1:a9Fqx6vQrHQ4CyiaLhktfTTelwGotmFWy8MNhyaohw8=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
|
||||
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||
github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/foomo/fender v0.4.4 h1:zs5jQGAVIygn552beaFXow4gRCuCKRl4D4qGiED6WeQ=
|
||||
github.com/foomo/fender v0.4.4/go.mod h1:cUmK1Gg1wrue5ZzRdGj92Ong4jBcSbuuSbINqaBXZaE=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/franklinkim/go-prompt v0.2.7-0.20210427061716-a8f4995d7aa5 h1:kXNtle4AoQnngdm+gwt4ku6Llbzw3EFHgZYpL618JaI=
|
||||
github.com/franklinkim/go-prompt v0.2.7-0.20210427061716-a8f4995d7aa5/go.mod h1:+syUfnvYJUO5A+6QMQYXAyzkxHMNlj9dH2LIeQfBSjc=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw=
|
||||
github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/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/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
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/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
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.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
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/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
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/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
|
||||
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
|
||||
github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
|
||||
github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg=
|
||||
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 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
|
||||
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.2.0 h1:4ZexSFt8agMNzNisrsilL6RClWDC5YJnLHNIfTy4iuc=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
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/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c=
|
||||
github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q=
|
||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI=
|
||||
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
|
||||
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
|
||||
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
|
||||
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pkg/term v1.1.0 h1:xIAAdCMh3QIAy+5FrE8Ad8XoDhEU4ufwbaSozViP9kk=
|
||||
github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw=
|
||||
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI=
|
||||
github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg=
|
||||
github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE=
|
||||
github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU=
|
||||
github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
|
||||
github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
|
||||
github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
|
||||
github.com/pterm/pterm v0.12.51 h1:iwhNG1FhQMgks+5kVyr/ClRk3WJCuL907nJN7RqmEpw=
|
||||
github.com/pterm/pterm v0.12.51/go.mod h1:79BLm4vos2z+eOoHnDG7ZWuYtLaSStyaspKjGmSoxc4=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
|
||||
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
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.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
|
||||
github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
|
||||
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
||||
github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
|
||||
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
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/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
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/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
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.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
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-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-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
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/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-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-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
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/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/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-20190206041539-40960b6deb8e/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-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-20190524140312-2c0ae7006135/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-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/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-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
|
||||
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
|
||||
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
|
||||
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/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
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/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
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/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
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=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
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.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
130
integration/onepassword/command.go
Normal file
130
integration/onepassword/command.go
Normal file
@ -0,0 +1,130 @@
|
||||
package onepassword
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
argparse2 "github.com/foomo/posh/pkg/command/tree"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/foomo/posh/pkg/prompt"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
"github.com/foomo/posh/pkg/shell"
|
||||
)
|
||||
|
||||
type Command struct {
|
||||
l log.Logger
|
||||
cfg Config
|
||||
parser *argparse2.Root
|
||||
client *OnePassword
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func NewCommand(l log.Logger, cfg Config, client *OnePassword) *Command {
|
||||
inst := &Command{
|
||||
l: l,
|
||||
cfg: cfg,
|
||||
client: client,
|
||||
}
|
||||
|
||||
inst.parser = &argparse2.Root{
|
||||
Name: "op",
|
||||
Nodes: []*argparse2.Node{
|
||||
{
|
||||
Name: "get",
|
||||
Description: "retrieve item",
|
||||
Args: []*argparse2.Arg{
|
||||
{
|
||||
Name: "id",
|
||||
},
|
||||
},
|
||||
Execute: inst.get,
|
||||
},
|
||||
{
|
||||
Name: "signin",
|
||||
Description: "sign into your account",
|
||||
Execute: inst.signin,
|
||||
},
|
||||
{
|
||||
Name: "register",
|
||||
Description: "register an account",
|
||||
Args: []*argparse2.Arg{
|
||||
{
|
||||
Name: "email",
|
||||
},
|
||||
},
|
||||
Execute: inst.register,
|
||||
},
|
||||
},
|
||||
}
|
||||
return inst
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c *Command) Name() string {
|
||||
return c.parser.Name
|
||||
}
|
||||
|
||||
func (c *Command) Description() string {
|
||||
return "run go mod"
|
||||
}
|
||||
|
||||
func (c *Command) Complete(ctx context.Context, r *readline.Readline, d prompt.Document) (suggests []prompt.Suggest) {
|
||||
return c.parser.Complete(ctx, r)
|
||||
}
|
||||
|
||||
func (c *Command) Execute(ctx context.Context, r *readline.Readline) error {
|
||||
return c.parser.Execute(ctx, r)
|
||||
}
|
||||
|
||||
func (c *Command) Help() string {
|
||||
return `1Password session helper.
|
||||
|
||||
Usage:
|
||||
op [command]
|
||||
|
||||
Available commands:
|
||||
get [id] Retrieve an entry from your account
|
||||
signin Sign into your 1Password account for the session
|
||||
register [email] Add your 1Password account
|
||||
`
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c *Command) get(ctx context.Context, r *readline.Readline) error {
|
||||
return shell.New(ctx, c.l,
|
||||
"op",
|
||||
"--account", c.cfg.Account,
|
||||
"item", "get", r.Args().At(1),
|
||||
"--format", "json",
|
||||
).
|
||||
Args(r.AdditionalArgs()...).
|
||||
Run()
|
||||
}
|
||||
|
||||
func (c *Command) register(ctx context.Context, r *readline.Readline) error {
|
||||
return shell.New(ctx, c.l,
|
||||
"op", "account", "add",
|
||||
"--address", c.cfg.Account+".1password.eu",
|
||||
"--email", r.Args().At(1),
|
||||
).
|
||||
Args(r.AdditionalArgs()...).
|
||||
Wait()
|
||||
}
|
||||
|
||||
func (c *Command) signin(ctx context.Context, r *readline.Readline) error {
|
||||
if ok, _ := c.client.Session(c.cfg.Account); ok {
|
||||
c.l.Info("Already signed in")
|
||||
return nil
|
||||
} else if err := c.client.SignIn(ctx, c.cfg.Account); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
6
integration/onepassword/config.go
Normal file
6
integration/onepassword/config.go
Normal file
@ -0,0 +1,6 @@
|
||||
package onepassword
|
||||
|
||||
type Config struct {
|
||||
Account string `json:"account" yaml:"account"`
|
||||
TokenFilename string `json:"tokenFilename" yaml:"tokenFilename"`
|
||||
}
|
||||
7
integration/onepassword/errors.go
Normal file
7
integration/onepassword/errors.go
Normal file
@ -0,0 +1,7 @@
|
||||
package onepassword
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var ErrNotSignedIn = errors.New("you're not signed into your 1password account")
|
||||
364
integration/onepassword/onepassword.go
Normal file
364
integration/onepassword/onepassword.go
Normal file
@ -0,0 +1,364 @@
|
||||
package onepassword
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/1Password/connect-sdk-go/connect"
|
||||
"github.com/1Password/connect-sdk-go/onepassword"
|
||||
"github.com/foomo/posh/pkg/cache"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
OnePassword struct {
|
||||
l log.Logger
|
||||
cache cache.Namespace
|
||||
connect connect.Client
|
||||
uuidRegex *regexp.Regexp
|
||||
tokenFilename string
|
||||
watching map[string]bool
|
||||
last time.Time
|
||||
}
|
||||
Option func(*OnePassword) error
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Options
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func WithTokenFilename(v string) Option {
|
||||
return func(o *OnePassword) error {
|
||||
o.tokenFilename = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func New(l log.Logger, cache cache.Cache, opts ...Option) (*OnePassword, error) {
|
||||
inst := &OnePassword{
|
||||
l: l,
|
||||
cache: cache.Get("onePasswordClient"),
|
||||
uuidRegex: regexp.MustCompile(`^[a-z0-9]{26}$`),
|
||||
watching: map[string]bool{},
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if opt != nil {
|
||||
if err := opt(inst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if client, err := connect.NewClientFromEnvironment(); err != nil {
|
||||
l.Debug("not able to create connect client", err.Error())
|
||||
} else {
|
||||
inst.connect = client
|
||||
}
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (op *OnePassword) Session(account string) (bool, error) {
|
||||
var sessChanged bool
|
||||
sess := os.Getenv("OP_SESSION_" + account)
|
||||
|
||||
if op.tokenFilename != "" {
|
||||
if err := godotenv.Overload(op.tokenFilename); err != nil {
|
||||
op.l.Debug("could not load session from env file")
|
||||
sessChanged = true
|
||||
} else if value := os.Getenv("OP_SESSION_" + account); sess != value {
|
||||
sessChanged = true
|
||||
} else {
|
||||
op.l.Debug("INFO: loaded op session from file " + value)
|
||||
}
|
||||
}
|
||||
|
||||
if sessChanged || op.last.IsZero() || time.Since(op.last) > time.Minute*10 {
|
||||
out, err := exec.Command("op", "account", "--account", account, "get", "--format", "json").Output()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("%w: %s", err, string(out))
|
||||
}
|
||||
|
||||
var data struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(out, &data); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if data.Name == account {
|
||||
op.last = time.Now()
|
||||
op.watch(account)
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (op *OnePassword) SignIn(ctx context.Context, account string) error {
|
||||
if ok, _ := op.Session(account); ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
// create command
|
||||
cmd := exec.CommandContext(ctx,
|
||||
"op", "signin",
|
||||
"--account", account,
|
||||
"--raw",
|
||||
)
|
||||
|
||||
var stdoutBuf bytes.Buffer
|
||||
cmd.Stdout = &stdoutBuf
|
||||
cmd.Stdin = os.Stdin
|
||||
|
||||
// start the process and wait till it's finished
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
} else if err := cmd.Wait(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
token := strings.TrimSuffix(stdoutBuf.String(), "\n")
|
||||
if token == "" {
|
||||
return errors.New("failed to retrieve 1password token!")
|
||||
} else if err := os.Setenv(fmt.Sprintf("OP_SESSION_%s", account), token); err != nil {
|
||||
return err
|
||||
} else {
|
||||
op.l.Infof(`If you need op outside the shell, run:
|
||||
|
||||
$ export OP_SESSION_%s=%s
|
||||
`, account, token)
|
||||
}
|
||||
|
||||
if op.tokenFilename != "" {
|
||||
if err := os.MkdirAll(path.Dir(op.tokenFilename), os.ModePerm); err != nil {
|
||||
return err
|
||||
} else if err := os.WriteFile(op.tokenFilename, []byte(fmt.Sprintf("OP_SESSION_%s=%s\n", account, token)), 0600); err != nil {
|
||||
return err
|
||||
} else {
|
||||
op.l.Infof(`Session env has been stored for your convenience at:
|
||||
|
||||
%s
|
||||
`, op.tokenFilename)
|
||||
}
|
||||
}
|
||||
op.watch(account)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (op *OnePassword) Get(ctx context.Context, account, vaultUUID, itemUUID, field string) (string, error) {
|
||||
if op.connect != nil {
|
||||
if fields := op.connectGet(vaultUUID, itemUUID); len(fields) == 0 {
|
||||
return "", fmt.Errorf("could not find secret '%s' '%s'", vaultUUID, itemUUID)
|
||||
} else if value, ok := fields[field]; !ok {
|
||||
return "", fmt.Errorf("could not find field %s", field)
|
||||
} else {
|
||||
return strings.ReplaceAll(strings.TrimSpace(value), "\\n", "\n"), nil
|
||||
}
|
||||
} else {
|
||||
if ok, _ := op.Session(account); !ok {
|
||||
return "", ErrNotSignedIn
|
||||
} else if fields := op.clientGet(ctx, vaultUUID, itemUUID); len(fields) == 0 {
|
||||
return "", fmt.Errorf("could not find secret '%s' '%s'", vaultUUID, itemUUID)
|
||||
} else if value, ok := fields[field]; !ok {
|
||||
return "", fmt.Errorf("could not find field %s", field)
|
||||
} else {
|
||||
return strings.ReplaceAll(strings.TrimSpace(value), "\\n", "\n"), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (op *OnePassword) GetOnetimePassword(ctx context.Context, account, uuid string) (string, error) {
|
||||
if ok, _ := op.Session(account); !ok {
|
||||
return "", ErrNotSignedIn
|
||||
}
|
||||
|
||||
out, err := exec.CommandContext(ctx,
|
||||
"op", "item", "get", "--otp", uuid,
|
||||
).Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.ReplaceAll(strings.TrimSpace(string(out)), "\\n", "\n"), nil
|
||||
}
|
||||
|
||||
func (op *OnePassword) Render(ctx context.Context, source string) ([]byte, error) {
|
||||
tpl, err := template.New("1password").
|
||||
Delims("<% ", " %>").
|
||||
Option("missingkey=error").
|
||||
Funcs(
|
||||
template.FuncMap{
|
||||
"env": func(name string) (string, error) {
|
||||
value := os.Getenv(name)
|
||||
if value == "" {
|
||||
return "", fmt.Errorf("env variable %q was empty", name)
|
||||
}
|
||||
return value, nil
|
||||
},
|
||||
"op": func(account, vaultUUID, itemUUID, field string) (string, error) {
|
||||
return op.Get(ctx, account, vaultUUID, itemUUID, field)
|
||||
},
|
||||
"indent": func(spaces int, v string) string {
|
||||
pad := strings.Repeat(" ", spaces)
|
||||
return strings.ReplaceAll(v, "\n", "\n"+pad)
|
||||
},
|
||||
"quote": func(v string) string {
|
||||
return "'" + v + "'"
|
||||
},
|
||||
"replace": func(old, new, v string) string {
|
||||
return strings.ReplaceAll(v, old, new)
|
||||
},
|
||||
"base64": func(v string) string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(v))
|
||||
},
|
||||
},
|
||||
).
|
||||
Parse(source)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
if err := tpl.Execute(out, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return out.Bytes(), nil
|
||||
}
|
||||
|
||||
func (op *OnePassword) RenderFile(ctx context.Context, source string) ([]byte, error) {
|
||||
in, err := os.ReadFile(source)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := op.Render(ctx, string(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (op *OnePassword) RenderFileTo(ctx context.Context, source, target string) error {
|
||||
out, err := op.RenderFile(ctx, source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
value := fmt.Sprintf(
|
||||
"# Code generated by shell %s - DO NOT EDIT.\n%s",
|
||||
time.Now().Format("2006-01-02 15:04:05"),
|
||||
string(out),
|
||||
)
|
||||
return os.WriteFile(target, []byte(value), 0600)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (op *OnePassword) clientGet(ctx context.Context, vaultUUID string, itemUUID string) map[string]string {
|
||||
return op.cache.Get(strings.Join([]string{vaultUUID, itemUUID}, "#"), func() interface{} {
|
||||
ret := map[string]string{}
|
||||
var v struct {
|
||||
Vault struct {
|
||||
ID string `json:"id"`
|
||||
} `json:"vault"`
|
||||
Fields []struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"` // CONCEALED, STRING
|
||||
Label string `json:"label"`
|
||||
Value interface{} `json:"value"`
|
||||
} `json:"fields"`
|
||||
}
|
||||
if res, err := exec.CommandContext(ctx,
|
||||
"op", "item", "get", itemUUID, "--format", "json",
|
||||
).CombinedOutput(); err != nil {
|
||||
op.l.Error("failed to retrieve item", err.Error())
|
||||
return ret
|
||||
} else if err := json.Unmarshal(res, &v); err != nil {
|
||||
op.l.Error("failed to retrieve item", err.Error())
|
||||
return ret
|
||||
} else if v.Vault.ID != vaultUUID {
|
||||
op.l.Error("failed to retrieve item", "wrong vault UUID %s for item %s", vaultUUID, itemUUID)
|
||||
return ret
|
||||
} else {
|
||||
ret := map[string]string{}
|
||||
aliases := map[string]string{
|
||||
"notesPlain": "notes",
|
||||
}
|
||||
for _, field := range v.Fields {
|
||||
if alias, ok := aliases[field.Label]; ok {
|
||||
ret[alias] = fmt.Sprintf("%v", field.Value)
|
||||
} else {
|
||||
ret[field.Label] = fmt.Sprintf("%v", field.Value)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}).(map[string]string)
|
||||
}
|
||||
|
||||
func (op *OnePassword) connectGet(vaultUUID, itemUUID string) map[string]string {
|
||||
return op.cache.Get(strings.Join([]string{vaultUUID, itemUUID}, "#"), func() interface{} {
|
||||
ret := map[string]string{}
|
||||
var item *onepassword.Item
|
||||
if op.uuidRegex.Match([]byte(itemUUID)) {
|
||||
if v, err := op.connect.GetItem(itemUUID, vaultUUID); err != nil {
|
||||
op.l.Error("failed to retrieve item:", err.Error())
|
||||
return ret
|
||||
} else {
|
||||
item = v
|
||||
}
|
||||
} else {
|
||||
if v, err := op.connect.GetItemByTitle(itemUUID, vaultUUID); err != nil {
|
||||
op.l.Error("failed to retrieve item by title:", err.Error())
|
||||
return ret
|
||||
} else {
|
||||
item = v
|
||||
}
|
||||
}
|
||||
for _, f := range item.Fields {
|
||||
ret[f.Label] = f.Value
|
||||
}
|
||||
return ret
|
||||
}).(map[string]string)
|
||||
}
|
||||
|
||||
func (op *OnePassword) watch(account string) {
|
||||
if v, ok := op.watching[account]; !ok || !v {
|
||||
go func() {
|
||||
for {
|
||||
if ok, err := op.Session(account); err != nil {
|
||||
op.l.Warnf("\n1password session keep alive failed for '%s' (%s)", account, err.Error())
|
||||
op.watching[account] = false
|
||||
return
|
||||
} else if !ok {
|
||||
op.l.Warnf("\n1password session keep alive failed for '%s'", account)
|
||||
op.watching[account] = false
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Minute * 15)
|
||||
}
|
||||
}()
|
||||
op.watching[account] = true
|
||||
}
|
||||
}
|
||||
55
internal/cli/utils.go
Normal file
55
internal/cli/utils.go
Normal file
@ -0,0 +1,55 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type (
|
||||
Mod struct {
|
||||
Path, Dir, GoMod string
|
||||
}
|
||||
CurDir struct {
|
||||
Dir string
|
||||
}
|
||||
)
|
||||
|
||||
func GetModImportPath() string {
|
||||
mod, cd := parseModInfo()
|
||||
return path.Join(mod.Path, fileToURL(strings.TrimPrefix(cd.Dir, mod.Dir)))
|
||||
}
|
||||
|
||||
func parseModInfo() (Mod, CurDir) {
|
||||
var mod Mod
|
||||
var dir CurDir
|
||||
|
||||
m := modInfoJSON("-m")
|
||||
cobra.CheckErr(json.Unmarshal(m, &mod))
|
||||
|
||||
// Unsure why, but if no module is present Path is set to this string.
|
||||
if mod.Path == "command-line-arguments" {
|
||||
cobra.CheckErr("Please run `go mod init <MODNAME>` before `cobra-cli init`")
|
||||
}
|
||||
|
||||
e := modInfoJSON("-e")
|
||||
cobra.CheckErr(json.Unmarshal(e, &dir))
|
||||
|
||||
return mod, dir
|
||||
}
|
||||
|
||||
func fileToURL(in string) string {
|
||||
i := strings.Split(in, string(filepath.Separator))
|
||||
return path.Join(i...)
|
||||
}
|
||||
|
||||
func modInfoJSON(args ...string) []byte {
|
||||
cmdArgs := append([]string{"list", "-json"}, args...)
|
||||
out, err := exec.Command("go", cmdArgs...).Output()
|
||||
cobra.CheckErr(err)
|
||||
return out
|
||||
}
|
||||
17
internal/util/utils.go
Normal file
17
internal/util/utils.go
Normal file
@ -0,0 +1,17 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/posh/pkg/config"
|
||||
"github.com/foomo/posh/pkg/plugin"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func LoadPlugin(ctx context.Context, m *plugin.Manager) (plugin.Plugin, error) {
|
||||
var cfg config.Plugin
|
||||
if err := viper.UnmarshalKey("plugin", &cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m.BuildAndLoadPlugin(ctx, cfg.Source, cfg.Provider)
|
||||
}
|
||||
9
main.go
Normal file
9
main.go
Normal file
@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/foomo/posh/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
}
|
||||
7
pkg/cache/cache.go
vendored
Normal file
7
pkg/cache/cache.go
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package cache
|
||||
|
||||
type Cache interface {
|
||||
Get(namespace string) Namespace
|
||||
Clear(namespace string)
|
||||
List() map[string]Namespace
|
||||
}
|
||||
28
pkg/cache/memorycache.go
vendored
Normal file
28
pkg/cache/memorycache.go
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
package cache
|
||||
|
||||
type MemoryCache map[string]MemoryNamespace
|
||||
|
||||
func (c MemoryCache) Clear(namespace string) {
|
||||
if namespace == "" {
|
||||
for key := range c {
|
||||
delete(c, key)
|
||||
}
|
||||
} else if _, ok := c[namespace]; ok {
|
||||
delete(c, namespace)
|
||||
}
|
||||
}
|
||||
|
||||
func (c MemoryCache) Get(namespace string) Namespace {
|
||||
if _, ok := c[namespace]; !ok {
|
||||
c[namespace] = MemoryNamespace{}
|
||||
}
|
||||
return c[namespace]
|
||||
}
|
||||
|
||||
func (c MemoryCache) List() map[string]Namespace {
|
||||
ret := map[string]Namespace{}
|
||||
for s, namespace := range c {
|
||||
ret[s] = namespace
|
||||
}
|
||||
return ret
|
||||
}
|
||||
34
pkg/cache/memorynamespace.go
vendored
Normal file
34
pkg/cache/memorynamespace.go
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
package cache
|
||||
|
||||
import "github.com/c-bata/go-prompt"
|
||||
|
||||
type MemoryNamespace map[string]interface{}
|
||||
|
||||
func (c MemoryNamespace) Delete(key string) {
|
||||
delete(c, key)
|
||||
}
|
||||
|
||||
func (c MemoryNamespace) Get(key string, cb func() interface{}) interface{} {
|
||||
if _, ok := c[key]; !ok {
|
||||
if cb == nil {
|
||||
return nil
|
||||
}
|
||||
c[key] = cb()
|
||||
}
|
||||
return c[key]
|
||||
}
|
||||
|
||||
func (c MemoryNamespace) Keys() []string {
|
||||
keys := make([]string, 0, len(c))
|
||||
for k := range c {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func (c MemoryNamespace) GetSuggests(key string, cb func() interface{}) []prompt.Suggest {
|
||||
if v, ok := c.Get(key, cb).([]prompt.Suggest); ok {
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
12
pkg/cache/namespace.go
vendored
Normal file
12
pkg/cache/namespace.go
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"github.com/c-bata/go-prompt"
|
||||
)
|
||||
|
||||
type Namespace interface {
|
||||
Get(key string, cb func() interface{}) interface{}
|
||||
Keys() []string
|
||||
Delete(key string)
|
||||
GetSuggests(key string, cb func() interface{}) []prompt.Suggest
|
||||
}
|
||||
107
pkg/command/cache.go
Normal file
107
pkg/command/cache.go
Normal file
@ -0,0 +1,107 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/c-bata/go-prompt"
|
||||
"github.com/foomo/posh/pkg/cache"
|
||||
"github.com/foomo/posh/pkg/command/tree"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/pterm/pterm/putils"
|
||||
)
|
||||
|
||||
type Cache struct {
|
||||
l log.Logger
|
||||
tree *tree.Root
|
||||
cache cache.Cache
|
||||
}
|
||||
|
||||
// NewCache command
|
||||
func NewCache(l log.Logger, cache cache.Cache) *Cache {
|
||||
inst := &Cache{
|
||||
l: l,
|
||||
cache: cache,
|
||||
}
|
||||
inst.tree = &tree.Root{
|
||||
Name: "cache",
|
||||
Nodes: tree.Nodes{
|
||||
{
|
||||
Name: "clear",
|
||||
Description: "clear all caches",
|
||||
Execute: inst.clear,
|
||||
},
|
||||
{
|
||||
Name: "list",
|
||||
Description: "list all caches",
|
||||
Execute: inst.list,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return inst
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c *Cache) Name() string {
|
||||
return c.tree.Name
|
||||
}
|
||||
|
||||
func (c *Cache) Description() string {
|
||||
return "manage the internal cache"
|
||||
}
|
||||
|
||||
func (c *Cache) Complete(ctx context.Context, r *readline.Readline, d prompt.Document) (suggests []prompt.Suggest) {
|
||||
return c.tree.Complete(ctx, r)
|
||||
}
|
||||
|
||||
func (c *Cache) Execute(ctx context.Context, args *readline.Readline) error {
|
||||
return c.tree.Execute(ctx, args)
|
||||
}
|
||||
|
||||
func (c *Cache) Help() string {
|
||||
return `Manage the internal cache.
|
||||
|
||||
Usage:
|
||||
cache [command]
|
||||
|
||||
Available commands:
|
||||
list List all caches
|
||||
clear Clear all caches
|
||||
`
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c *Cache) clear(ctx context.Context, r *readline.Readline) error {
|
||||
c.l.Info("clearing cache")
|
||||
c.cache.Clear("")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cache) list(ctx context.Context, r *readline.Readline) error {
|
||||
// Create a fork of the default table, fill it with data and print it.
|
||||
// Data can also be generated and inserted later.
|
||||
tree := pterm.LeveledList{}
|
||||
for ns, value := range c.cache.List() {
|
||||
tree = append(tree, pterm.LeveledListItem{Level: 0, Text: ns})
|
||||
for _, k := range value.Keys() {
|
||||
tree = append(tree, pterm.LeveledListItem{Level: 1, Text: k})
|
||||
if c.l.Level() == log.LevelTrace {
|
||||
tree = append(tree, pterm.LeveledListItem{Level: 2, Text: fmt.Sprintf("%v", value.Get(k, nil))})
|
||||
}
|
||||
}
|
||||
}
|
||||
// Generate tree from LeveledList.
|
||||
root := putils.TreeFromLeveledList(tree)
|
||||
|
||||
// Render TreePrinter
|
||||
return pterm.DefaultTree.WithRoot(root).Render()
|
||||
}
|
||||
40
pkg/command/command.go
Normal file
40
pkg/command/command.go
Normal file
@ -0,0 +1,40 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/c-bata/go-prompt"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
)
|
||||
|
||||
type (
|
||||
Command interface {
|
||||
Name() string
|
||||
Description() string
|
||||
Execute(ctx context.Context, r *readline.Readline) error
|
||||
}
|
||||
Helper interface {
|
||||
Help() string
|
||||
}
|
||||
Validator interface {
|
||||
Validate(ctx context.Context, r *readline.Readline) error
|
||||
}
|
||||
Completer interface {
|
||||
Complete(ctx context.Context, r *readline.Readline, d prompt.Document) []prompt.Suggest
|
||||
}
|
||||
FlagCompleter interface {
|
||||
CompleteFlags(ctx context.Context, r *readline.Readline, d prompt.Document) []prompt.Suggest
|
||||
}
|
||||
ArgumentCompleter interface {
|
||||
CompleteArguments(ctx context.Context, r *readline.Readline, d prompt.Document) []prompt.Suggest
|
||||
}
|
||||
PassThroughArgsCompleter interface {
|
||||
CompletePassTroughArgs(ctx context.Context, r *readline.Readline, d prompt.Document) []prompt.Suggest
|
||||
}
|
||||
PassThroughFlagsCompleter interface {
|
||||
CompletePassTroughFlags(ctx context.Context, r *readline.Readline, d prompt.Document) []prompt.Suggest
|
||||
}
|
||||
AdditionalArgsCompleter interface {
|
||||
CompleteAdditionalArgs(ctx context.Context, r *readline.Readline, d prompt.Document) []prompt.Suggest
|
||||
}
|
||||
)
|
||||
54
pkg/command/commands.go
Normal file
54
pkg/command/commands.go
Normal file
@ -0,0 +1,54 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"plugin"
|
||||
"sort"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Commands map[string]Command
|
||||
|
||||
func (c Commands) Get(name string) Command {
|
||||
if value, ok := c[name]; ok {
|
||||
return value
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c Commands) List() []Command {
|
||||
ret := make([]Command, 0, len(c))
|
||||
for _, command := range c {
|
||||
ret = append(ret, command)
|
||||
}
|
||||
sort.Slice(ret, func(i, j int) bool {
|
||||
return ret[i].Name() < ret[j].Name()
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c Commands) Has(name string) bool {
|
||||
return c.Get(name) != nil
|
||||
}
|
||||
|
||||
func (c Commands) Add(commands ...Command) {
|
||||
for _, command := range commands {
|
||||
c[command.Name()] = command
|
||||
}
|
||||
}
|
||||
|
||||
func (c Commands) Load(paths ...string) error {
|
||||
for _, path := range paths {
|
||||
if plg, err := plugin.Open(path); err != nil {
|
||||
return errors.Wrapf(err, "failed to load plugin (%s)", path)
|
||||
} else if sym, err := plg.Lookup("Commands"); err != nil {
|
||||
return errors.Wrapf(err, "failed to lookup Commands from plugin (%s)", path)
|
||||
} else if cmds, ok := sym.([]Command); !ok {
|
||||
return errors.Wrapf(err, "failed to lookup Commands type from plugin (%s)", path)
|
||||
} else {
|
||||
c.Add(cmds...)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
51
pkg/command/exit.go
Normal file
51
pkg/command/exit.go
Normal file
@ -0,0 +1,51 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
)
|
||||
|
||||
type Exit struct {
|
||||
l log.Logger
|
||||
name string
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func NewExit(l log.Logger) *Exit {
|
||||
return &Exit{
|
||||
l: l,
|
||||
name: "exit",
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c *Exit) Name() string {
|
||||
return c.name
|
||||
}
|
||||
|
||||
func (c *Exit) Description() string {
|
||||
return "exit shell"
|
||||
}
|
||||
|
||||
func (c *Exit) Execute(ctx context.Context, args *readline.Readline) error {
|
||||
c.l.Print("Bye.")
|
||||
os.Exit(0)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Exit) Help() string {
|
||||
return `Exit the Project Oriented Shell.
|
||||
|
||||
Usage:
|
||||
exit
|
||||
`
|
||||
}
|
||||
122
pkg/command/help.go
Normal file
122
pkg/command/help.go
Normal file
@ -0,0 +1,122 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/c-bata/go-prompt"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
Help struct {
|
||||
l log.Logger
|
||||
name string
|
||||
commands Commands
|
||||
}
|
||||
|
||||
HelpOption func(*Help)
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func NewHelp(l log.Logger, commands Commands) *Help {
|
||||
return &Help{
|
||||
l: l,
|
||||
name: "help",
|
||||
commands: commands,
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c *Help) Name() string {
|
||||
return c.name
|
||||
}
|
||||
|
||||
func (c *Help) Description() string {
|
||||
return "print help"
|
||||
}
|
||||
|
||||
func (c *Help) Complete(ctx context.Context, r *readline.Readline, d prompt.Document) (suggests []prompt.Suggest) {
|
||||
switch {
|
||||
case r.Args().LenLte(1):
|
||||
for _, value := range c.list() {
|
||||
suggests = append(suggests, prompt.Suggest{Text: value.Name(), Description: value.Description()})
|
||||
}
|
||||
}
|
||||
return suggests
|
||||
}
|
||||
|
||||
func (c *Help) Validate(ctx context.Context, r *readline.Readline) error {
|
||||
switch {
|
||||
case r.Args().LenIs(0):
|
||||
// all good
|
||||
case r.Args().LenIs(1):
|
||||
for _, command := range c.list() {
|
||||
if r.Args().At(0) == command.Name() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.Errorf("invalid [command] argument: %s", r.Args().At(0))
|
||||
case r.Args().LenGte(2):
|
||||
return errors.New("too many arguments")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Help) Execute(ctx context.Context, r *readline.Readline) error {
|
||||
switch r.Args().Len() {
|
||||
case 0:
|
||||
ret := `Help about all available commands.
|
||||
|
||||
Usage:
|
||||
help [command]
|
||||
|
||||
Available Commands:
|
||||
`
|
||||
for _, value := range c.list() {
|
||||
ret += c.format(value.Name(), value.Description())
|
||||
}
|
||||
c.l.Print(ret)
|
||||
case 1:
|
||||
if helper, ok := c.commands.Get(r.Args().At(0)).(Helper); ok {
|
||||
c.l.Print(helper.Help())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c *Help) list() []Command {
|
||||
var ret []Command
|
||||
for _, value := range c.commands.List() {
|
||||
if _, ok := value.(Helper); ok {
|
||||
ret = append(ret, value)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// print formatted output
|
||||
func (c *Help) format(name, description string) string {
|
||||
offset := int(math.Max(0, float64(20-len(name))))
|
||||
suffix := strings.Repeat(" ", offset)
|
||||
prefix := ""
|
||||
if offset == 0 {
|
||||
suffix = "\n"
|
||||
prefix = strings.Repeat(" ", 20)
|
||||
}
|
||||
return " " + name + suffix + prefix + description + "\n"
|
||||
}
|
||||
15
pkg/command/tree/arg.go
Normal file
15
pkg/command/tree/arg.go
Normal file
@ -0,0 +1,15 @@
|
||||
package tree
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/c-bata/go-prompt"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
)
|
||||
|
||||
type Arg struct {
|
||||
Name string
|
||||
Repeat bool
|
||||
Optional bool
|
||||
Suggest func(ctx context.Context, parser *Root, args *readline.Readline) (suggest []prompt.Suggest)
|
||||
}
|
||||
11
pkg/command/tree/args.go
Normal file
11
pkg/command/tree/args.go
Normal file
@ -0,0 +1,11 @@
|
||||
package tree
|
||||
|
||||
type Args []*Arg
|
||||
|
||||
func (a Args) Last() *Arg {
|
||||
if len(a) > 0 {
|
||||
return a[len(a)-1]
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
7
pkg/command/tree/flag.go
Normal file
7
pkg/command/tree/flag.go
Normal file
@ -0,0 +1,7 @@
|
||||
package tree
|
||||
|
||||
type Flag struct {
|
||||
Name string
|
||||
Required bool
|
||||
Value interface{}
|
||||
}
|
||||
93
pkg/command/tree/node.go
Normal file
93
pkg/command/tree/node.go
Normal file
@ -0,0 +1,93 @@
|
||||
package tree
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/c-bata/go-prompt"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Node struct {
|
||||
Name string
|
||||
Names func() []string
|
||||
Args Args
|
||||
Flags func(fs *readline.FlagSet)
|
||||
PassThroughArgs Args
|
||||
PassThroughFlags func(fs *readline.FlagSet)
|
||||
Description string
|
||||
Commands []*Node
|
||||
Execute func(ctx context.Context, args *readline.Readline) error
|
||||
//Suggest func(ctx context.Context, parser *Parser, args *prompt.Args) (suggest []prompt.Suggest)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c *Node) setFlags(r *readline.Readline, parse bool) error {
|
||||
if c.Flags != nil {
|
||||
r.SetFlags(readline.NewFlagSet(c.Flags))
|
||||
if parse {
|
||||
if err := r.ParseFlags(); err != nil {
|
||||
return errors.Wrap(err, "failed to parse flags")
|
||||
}
|
||||
}
|
||||
}
|
||||
if c.PassThroughFlags != nil {
|
||||
r.SetParsePassThroughFlags(readline.NewFlagSet(c.PassThroughFlags))
|
||||
if parse {
|
||||
if err := r.ParsePassThroughFlags(); err != nil {
|
||||
return errors.Wrap(err, "failed to parse pass through flags")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Node) completeArguments(ctx context.Context, p *Root, r *readline.Readline, i int) (suggest []prompt.Suggest) {
|
||||
localArgs := r.Args()[i:]
|
||||
if len(c.Commands) > 0 && len(localArgs) <= 1 {
|
||||
for _, command := range c.Commands {
|
||||
suggest = append(suggest, prompt.Suggest{Text: command.Name, Description: command.Description})
|
||||
}
|
||||
} else if len(c.Args) >= len(localArgs) {
|
||||
if fn := c.Args[len(localArgs)-1].Suggest; fn != nil {
|
||||
suggest = fn(ctx, p, r)
|
||||
}
|
||||
} else if lastArg := c.Args.Last(); lastArg != nil && lastArg.Repeat {
|
||||
if fn := lastArg.Suggest; fn != nil {
|
||||
suggest = fn(ctx, p, r)
|
||||
}
|
||||
}
|
||||
return suggest
|
||||
}
|
||||
|
||||
func (c *Node) completeFlags(r *readline.Readline) (suggest []prompt.Suggest) {
|
||||
for _, f := range r.AllFlags() {
|
||||
suggest = append(suggest, prompt.Suggest{Text: "--" + f.Name, Description: f.Usage})
|
||||
}
|
||||
return suggest
|
||||
}
|
||||
|
||||
func (c *Node) completePassThroughFlags(r *readline.Readline) (suggest []prompt.Suggest) {
|
||||
for _, f := range r.AllPassThroughFlags() {
|
||||
suggest = append(suggest, prompt.Suggest{Text: "--" + f.Name, Description: f.Usage})
|
||||
}
|
||||
return suggest
|
||||
}
|
||||
|
||||
func (c *Node) execute(ctx context.Context, r *readline.Readline, i int) error {
|
||||
localArgs := r.Args()[i:]
|
||||
if len(c.Commands) > 0 && len(localArgs) == 0 {
|
||||
return errors.New("missing [command] argument")
|
||||
} else if len(c.Args) > 0 {
|
||||
for j, arg := range c.Args {
|
||||
if !arg.Optional && len(localArgs) <= j+1 {
|
||||
return errors.New("missing [" + arg.Name + "] argument")
|
||||
}
|
||||
}
|
||||
}
|
||||
return c.Execute(ctx, r)
|
||||
}
|
||||
3
pkg/command/tree/nodes.go
Normal file
3
pkg/command/tree/nodes.go
Normal file
@ -0,0 +1,3 @@
|
||||
package tree
|
||||
|
||||
type Nodes []*Node
|
||||
108
pkg/command/tree/root.go
Normal file
108
pkg/command/tree/root.go
Normal file
@ -0,0 +1,108 @@
|
||||
package tree
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/c-bata/go-prompt"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Root struct {
|
||||
Name string
|
||||
Nodes []*Node
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (p *Root) Execute(ctx context.Context, r *readline.Readline) error {
|
||||
if r.Args().LenIs(0) {
|
||||
return errors.New("missing [command] argument")
|
||||
} else if cmd, i := p.find(p.Nodes, r, 0); cmd == nil {
|
||||
return errors.New("invalid [command] argument")
|
||||
} else if err := cmd.setFlags(r, true); err != nil {
|
||||
return err
|
||||
} else if err := cmd.execute(ctx, r, i); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Root) Complete(ctx context.Context, r *readline.Readline) (suggests []prompt.Suggest) {
|
||||
switch r.Mode() {
|
||||
case readline.ModeArgs:
|
||||
if r.Args().LenLte(1) {
|
||||
for _, command := range p.Nodes {
|
||||
suggests = append(suggests, prompt.Suggest{Text: command.Name, Description: command.Description})
|
||||
}
|
||||
} else if cmd, i := p.find(p.Nodes, r, 0); cmd == nil {
|
||||
return nil
|
||||
} else if err := cmd.setFlags(r, false); err != nil {
|
||||
return nil
|
||||
} else {
|
||||
suggests = cmd.completeArguments(ctx, p, r, i+1)
|
||||
}
|
||||
sort.Slice(suggests, func(i, j int) bool {
|
||||
return suggests[i].Text < suggests[j].Text
|
||||
})
|
||||
case readline.ModeFlags:
|
||||
if cmd, _ := p.find(p.Nodes, r, 0); cmd == nil {
|
||||
return nil
|
||||
} else if err := cmd.setFlags(r, false); err != nil {
|
||||
return nil
|
||||
} else {
|
||||
suggests = cmd.completeFlags(r)
|
||||
}
|
||||
sort.Slice(suggests, func(i, j int) bool {
|
||||
return suggests[i].Text < suggests[j].Text
|
||||
})
|
||||
case readline.ModePassThroughArgs:
|
||||
// TODO
|
||||
case readline.ModePassThroughFlags:
|
||||
if cmd, _ := p.find(p.Nodes, r, 0); cmd == nil {
|
||||
return nil
|
||||
} else if err := cmd.setFlags(r, false); err != nil {
|
||||
return nil
|
||||
} else {
|
||||
suggests = cmd.completePassThroughFlags(r)
|
||||
}
|
||||
sort.Slice(suggests, func(i, j int) bool {
|
||||
return suggests[i].Text < suggests[j].Text
|
||||
})
|
||||
}
|
||||
return suggests
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (p *Root) find(cmds []*Node, r *readline.Readline, i int) (*Node, int) {
|
||||
if r.Args().LenLt(i + 1) {
|
||||
return nil, i
|
||||
}
|
||||
arg := r.Args().At(i)
|
||||
for _, cmd := range cmds {
|
||||
if cmd.Name == arg {
|
||||
if subCmd, j := p.find(cmd.Commands, r, i+1); subCmd != nil {
|
||||
return subCmd, j
|
||||
}
|
||||
return cmd, i
|
||||
}
|
||||
if cmd.Names != nil {
|
||||
for _, name := range cmd.Names() {
|
||||
if name == arg {
|
||||
if subCmd, j := p.find(cmd.Commands, r, i+1); subCmd != nil {
|
||||
return subCmd, j
|
||||
}
|
||||
}
|
||||
return cmd, i
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, i
|
||||
}
|
||||
40
pkg/config/dependencies.go
Normal file
40
pkg/config/dependencies.go
Normal file
@ -0,0 +1,40 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type (
|
||||
Dependencies struct {
|
||||
Envs []DependenciesEnv `json:"envs" yaml:"envs"`
|
||||
Scripts []DependenciesScript `json:"script" yaml:"script"`
|
||||
Packages []DependenciesPackage `json:"packages" yaml:"packages"`
|
||||
}
|
||||
DependenciesEnv struct {
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Help string `json:"help" yaml:"help"`
|
||||
}
|
||||
DependenciesScript struct {
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Command string `json:"command" yaml:"command"`
|
||||
Help string `json:"help" yaml:"help"`
|
||||
}
|
||||
DependenciesPackage struct {
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Version string `json:"version" yaml:"version"`
|
||||
Command string `json:"command" yaml:"command"`
|
||||
Help string `json:"help" yaml:"help"`
|
||||
}
|
||||
)
|
||||
|
||||
func (c DependenciesEnv) String() string {
|
||||
return fmt.Sprintf("Name: %s", c.Name)
|
||||
}
|
||||
|
||||
func (c DependenciesScript) String() string {
|
||||
return fmt.Sprintf("Name: %s, Command: %s", c.Name, c.Command)
|
||||
}
|
||||
|
||||
func (c DependenciesPackage) String() string {
|
||||
return fmt.Sprintf("Name: %s, Version: %s Command: %s", c.Name, c.Version, c.Command)
|
||||
}
|
||||
15
pkg/config/package.go
Normal file
15
pkg/config/package.go
Normal file
@ -0,0 +1,15 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Package struct {
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Version string `json:"version" yaml:"version"`
|
||||
Command string `json:"command" yaml:"command"`
|
||||
}
|
||||
|
||||
func (c Package) String() string {
|
||||
return fmt.Sprintf("Name: %s, Version: %s Command: %s", c.Name, c.Version, c.Command)
|
||||
}
|
||||
15
pkg/config/plugin.go
Normal file
15
pkg/config/plugin.go
Normal file
@ -0,0 +1,15 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Plugin struct {
|
||||
Source string `json:"source" yaml:"source"`
|
||||
Target string `json:"target" yaml:"target"`
|
||||
Provider string `json:"provider" yaml:"provider"`
|
||||
}
|
||||
|
||||
func (c Plugin) String() string {
|
||||
return fmt.Sprintf("Filename: %s, Provider: %s", c.Source, c.Provider)
|
||||
}
|
||||
14
pkg/config/prompt.go
Normal file
14
pkg/config/prompt.go
Normal file
@ -0,0 +1,14 @@
|
||||
package config
|
||||
|
||||
type (
|
||||
Prompt struct {
|
||||
Title string `json:"title" yaml:"title"`
|
||||
Prefix string `json:"prefix" yaml:"prefix"`
|
||||
History PromptHistory `json:"history" yaml:"history"`
|
||||
}
|
||||
PromptHistory struct {
|
||||
Limit int `json:"limit" yaml:"limit"`
|
||||
Filename string `json:"filename" yaml:"filename"`
|
||||
LockFilename string `json:"lockFilename" yaml:"lockFilename"`
|
||||
}
|
||||
)
|
||||
120
pkg/log/fmt.go
Normal file
120
pkg/log/fmt.go
Normal file
@ -0,0 +1,120 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type (
|
||||
Fmt struct {
|
||||
level Level
|
||||
}
|
||||
FmtOption func(*Fmt)
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Options
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func FmtWithLevel(v Level) FmtOption {
|
||||
return func(o *Fmt) {
|
||||
o.level = v
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func NewFmt(opts ...FmtOption) *Fmt {
|
||||
inst := &Fmt{
|
||||
level: LevelError,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if opt != nil {
|
||||
opt(inst)
|
||||
}
|
||||
}
|
||||
return inst
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (l *Fmt) Level() Level {
|
||||
return l.level
|
||||
}
|
||||
|
||||
func (l *Fmt) Print(a ...interface{}) {
|
||||
fmt.Println(append([]interface{}{"Info:"}, a...)...)
|
||||
}
|
||||
|
||||
func (l *Fmt) Printf(format string, a ...interface{}) {
|
||||
fmt.Printf(format+"\n", a...)
|
||||
}
|
||||
|
||||
func (l *Fmt) Debug(a ...interface{}) {
|
||||
if l.level <= LevelDebug {
|
||||
fmt.Println(append([]interface{}{"Debug:"}, a...)...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Fmt) Debugf(format string, a ...interface{}) {
|
||||
if l.level <= LevelDebug {
|
||||
fmt.Printf("Debug: "+format+"\n", a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Fmt) Info(a ...interface{}) {
|
||||
if l.level <= LevelInfo {
|
||||
fmt.Println(append([]interface{}{"Info:"}, a...)...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Fmt) Infof(format string, a ...interface{}) {
|
||||
if l.level <= LevelInfo {
|
||||
fmt.Printf("Info: "+format+"\n", a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Fmt) Warn(a ...interface{}) {
|
||||
if l.level <= LevelWarn {
|
||||
fmt.Println(append([]interface{}{"Warn:"}, a...)...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Fmt) Warnf(format string, a ...interface{}) {
|
||||
if l.level <= LevelWarn {
|
||||
fmt.Printf("Warn: "+format+"\n", a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Fmt) Error(a ...interface{}) {
|
||||
if l.level <= LevelError {
|
||||
fmt.Println(append([]interface{}{"Error:"}, a...)...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Fmt) Errorf(format string, a ...interface{}) {
|
||||
if l.level <= LevelError {
|
||||
fmt.Printf("Error: "+format+"\n", a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Fmt) Fatal(a ...interface{}) {
|
||||
fmt.Println(append([]interface{}{"Fatal:"}, a...)...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (l *Fmt) Fatalf(format string, args ...interface{}) {
|
||||
fmt.Printf("Fatal: "+format+"\n", args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (l *Fmt) Must(err error) {
|
||||
if err != nil {
|
||||
l.Error(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
28
pkg/log/level.go
Normal file
28
pkg/log/level.go
Normal file
@ -0,0 +1,28 @@
|
||||
package log
|
||||
|
||||
type Level int
|
||||
|
||||
const (
|
||||
LevelTrace Level = iota
|
||||
LevelDebug
|
||||
LevelInfo
|
||||
LevelWarn
|
||||
LevelError
|
||||
)
|
||||
|
||||
func GetLevel(v string) Level {
|
||||
switch v {
|
||||
case "trace":
|
||||
return LevelTrace
|
||||
case "debug":
|
||||
return LevelDebug
|
||||
case "info":
|
||||
return LevelInfo
|
||||
case "warn":
|
||||
return LevelWarn
|
||||
case "error":
|
||||
return LevelError
|
||||
default:
|
||||
return LevelInfo
|
||||
}
|
||||
}
|
||||
18
pkg/log/logger.go
Normal file
18
pkg/log/logger.go
Normal file
@ -0,0 +1,18 @@
|
||||
package log
|
||||
|
||||
type Logger interface {
|
||||
Level() Level
|
||||
Print(a ...interface{})
|
||||
Printf(format string, a ...interface{})
|
||||
Debug(a ...interface{})
|
||||
Debugf(format string, a ...interface{})
|
||||
Info(a ...interface{})
|
||||
Infof(format string, a ...interface{})
|
||||
Warn(a ...interface{})
|
||||
Warnf(format string, a ...interface{})
|
||||
Error(a ...interface{})
|
||||
Errorf(format string, a ...interface{})
|
||||
Fatal(a ...interface{})
|
||||
Fatalf(format string, a ...interface{})
|
||||
Must(err error)
|
||||
}
|
||||
140
pkg/log/pterm.go
Normal file
140
pkg/log/pterm.go
Normal file
@ -0,0 +1,140 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/pterm/pterm"
|
||||
)
|
||||
|
||||
type (
|
||||
PTerm struct {
|
||||
level Level
|
||||
}
|
||||
PTermOption func(*PTerm) error
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Options
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func PTermWithDisableColor(v bool) PTermOption {
|
||||
return func(o *PTerm) error {
|
||||
if v {
|
||||
pterm.DisableColor()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func PTermWithLevel(v Level) PTermOption {
|
||||
return func(o *PTerm) error {
|
||||
o.level = v
|
||||
switch {
|
||||
case v <= LevelTrace:
|
||||
pterm.Debug.ShowLineNumber = true
|
||||
fallthrough
|
||||
case v <= LevelDebug:
|
||||
pterm.EnableDebugMessages()
|
||||
fallthrough
|
||||
default:
|
||||
pterm.Debug.LineNumberOffset = 1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func NewPTerm(opts ...PTermOption) (*PTerm, error) {
|
||||
inst := &PTerm{
|
||||
level: LevelError,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if opt != nil {
|
||||
if err := opt(inst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (l *PTerm) Level() Level {
|
||||
return l.level
|
||||
}
|
||||
|
||||
func (l *PTerm) Print(a ...interface{}) {
|
||||
pterm.Println(a...)
|
||||
}
|
||||
|
||||
func (l *PTerm) Printf(format string, a ...interface{}) {
|
||||
pterm.Printfln(format, a...)
|
||||
}
|
||||
func (l *PTerm) Debug(a ...interface{}) {
|
||||
if l.level <= LevelDebug {
|
||||
pterm.Debug.Println(a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PTerm) Debugf(format string, a ...interface{}) {
|
||||
if l.level <= LevelDebug {
|
||||
pterm.Debug.Printfln(format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PTerm) Info(a ...interface{}) {
|
||||
if l.level <= LevelInfo {
|
||||
pterm.Info.Println(a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PTerm) Infof(format string, a ...interface{}) {
|
||||
if l.level <= LevelInfo {
|
||||
pterm.Info.Printfln(format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PTerm) Warn(a ...interface{}) {
|
||||
if l.level <= LevelWarn {
|
||||
pterm.Warning.Println(a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PTerm) Warnf(format string, a ...interface{}) {
|
||||
if l.level <= LevelWarn {
|
||||
pterm.Warning.Printfln(format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PTerm) Error(a ...interface{}) {
|
||||
if l.level <= LevelError {
|
||||
pterm.Error.Println(a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PTerm) Errorf(format string, a ...interface{}) {
|
||||
if l.level <= LevelError {
|
||||
pterm.Error.Printfln(format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PTerm) Fatal(a ...interface{}) {
|
||||
pterm.Fatal.Println(a...)
|
||||
}
|
||||
|
||||
func (l *PTerm) Fatalf(format string, args ...interface{}) {
|
||||
pterm.Fatal.Printfln(format, args...)
|
||||
}
|
||||
|
||||
func (l *PTerm) Must(err error) {
|
||||
if err != nil {
|
||||
l.Error(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
189
pkg/ownbrew/ownbrew.go
Normal file
189
pkg/ownbrew/ownbrew.go
Normal file
@ -0,0 +1,189 @@
|
||||
package ownbrew
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/foomo/posh/pkg/config"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
Ownbrew struct {
|
||||
l log.Logger
|
||||
binDir string
|
||||
tempDir string
|
||||
caskDir string
|
||||
cellarDir string
|
||||
packages []config.Package
|
||||
}
|
||||
Option func(*Ownbrew) error
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Options
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func WithPackages(v ...config.Package) Option {
|
||||
return func(o *Ownbrew) error {
|
||||
o.packages = append(o.packages, v...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithBinDir(v string) Option {
|
||||
return func(o *Ownbrew) error {
|
||||
o.binDir = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithTempDir(v string) Option {
|
||||
return func(o *Ownbrew) error {
|
||||
o.tempDir = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithCaskDir(v string) Option {
|
||||
return func(o *Ownbrew) error {
|
||||
o.caskDir = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithCellarDir(v string) Option {
|
||||
return func(o *Ownbrew) error {
|
||||
o.cellarDir = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func New(l log.Logger, opts ...Option) (*Ownbrew, error) {
|
||||
inst := &Ownbrew{
|
||||
l: l,
|
||||
binDir: "bin",
|
||||
tempDir: ".posh/tmp",
|
||||
caskDir: ".posh/scripts/ownbrew",
|
||||
cellarDir: ".posh/bin",
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if opt != nil {
|
||||
if err := opt(inst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, dir := range []string{inst.binDir, inst.tempDir, inst.caskDir, inst.cellarDir} {
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (o *Ownbrew) Install(ctx context.Context) error {
|
||||
o.l.Debug("installing packages", runtime.GOOS, runtime.GOARCH)
|
||||
|
||||
for _, pkg := range o.packages {
|
||||
if pkg.Command == "" {
|
||||
pkg.Command = filepath.Join(o.caskDir, pkg.Name+".sh")
|
||||
}
|
||||
o.l.Debug("installing:", pkg.String())
|
||||
|
||||
cellarFilename := filepath.Join(o.cellarDir, fmt.Sprintf("%s-%s-%s-%s", pkg.Name, pkg.Version, runtime.GOOS, runtime.GOARCH))
|
||||
exists, err := o.cellarExists(cellarFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
if err := o.casksExists(pkg.Command); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, "sh",
|
||||
pkg.Command,
|
||||
pkg.Version,
|
||||
runtime.GOOS,
|
||||
runtime.GOARCH,
|
||||
)
|
||||
|
||||
cmd.Env = append(
|
||||
os.Environ(),
|
||||
"BIN_DIR="+o.cellarDir,
|
||||
"TEMP_DIR="+o.tempDir,
|
||||
)
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
o.l.Debug(string(output))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to install package: %s", pkg.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// create symlink
|
||||
if err := o.symlink(cellarFilename, filepath.Join(o.binDir, pkg.Name)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (o *Ownbrew) symlink(source, target string) error {
|
||||
if err := os.Remove(target); os.IsNotExist(err) {
|
||||
// continue
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
prefix, err := filepath.Rel(filepath.Base(target), "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prefix = strings.TrimSuffix(prefix, ".")
|
||||
|
||||
o.l.Debug("symlink:", prefix+source, target)
|
||||
return os.Symlink(prefix+source, target)
|
||||
}
|
||||
|
||||
func (o *Ownbrew) casksExists(filename string) error {
|
||||
if stat, err := os.Stat(filename); err != nil {
|
||||
return errors.Wrap(err, "failed to stat cask")
|
||||
} else if stat.IsDir() {
|
||||
return fmt.Errorf("not an executeable: %s", filename)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Ownbrew) cellarExists(filename string) (bool, error) {
|
||||
if _, err := os.Stat(filename); errors.Is(err, os.ErrNotExist) {
|
||||
o.l.Debug("install:", filename)
|
||||
return false, nil
|
||||
} else if err != nil {
|
||||
return false, errors.Wrap(err, "failed to stat bin")
|
||||
} else {
|
||||
o.l.Debug("exists:", filename)
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
101
pkg/plugin/manager.go
Normal file
101
pkg/plugin/manager.go
Normal file
@ -0,0 +1,101 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"plugin"
|
||||
"strings"
|
||||
|
||||
"github.com/foomo/posh/pkg/config"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
Plugin interface {
|
||||
Prompt(ctx context.Context, cfg config.Prompt) error
|
||||
Execute(ctx context.Context, args []string) error
|
||||
Packages(ctx context.Context, cfg []config.Package) error
|
||||
Dependencies(ctx context.Context, cfg config.Dependencies) error
|
||||
}
|
||||
Provider func(l log.Logger) (Plugin, error)
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
l log.Logger
|
||||
plugins map[string]*plugin.Plugin
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func NewManager(l log.Logger) (*Manager, error) {
|
||||
inst := &Manager{
|
||||
l: l,
|
||||
plugins: map[string]*plugin.Plugin{},
|
||||
}
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (m *Manager) BuildAndLoadPlugin(ctx context.Context, filename, provider string) (Plugin, error) {
|
||||
if err := m.Build(ctx, filename); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m.LoadPlugin(filename, provider)
|
||||
}
|
||||
|
||||
func (m *Manager) Build(ctx context.Context, filename string) error {
|
||||
m.l.Debug("building:", filename)
|
||||
|
||||
dir := filepath.Dir(filename)
|
||||
base := path.Base(filename)
|
||||
cmd := exec.CommandContext(ctx, "go", "build",
|
||||
"-buildmode=plugin",
|
||||
"-o", strings.ReplaceAll(base, ".go", ".so"),
|
||||
base,
|
||||
)
|
||||
cmd.Dir = dir
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
return errors.Wrap(err, string(output))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) LoadPlugin(filename, provider string) (Plugin, error) {
|
||||
m.l.Debug("loading plugin:", filename, provider)
|
||||
filename = strings.ReplaceAll(filename, ".go", ".so")
|
||||
if plg, err := m.Load(filename); err != nil {
|
||||
return nil, err
|
||||
} else if sym, err := plg.Lookup(provider); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to lookup provider (%s)", provider)
|
||||
} else if fn, ok := sym.(func(l log.Logger) (Plugin, error)); !ok {
|
||||
return nil, fmt.Errorf("invalid provider type (%T) ", sym)
|
||||
} else if inst, err := fn(m.l); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create plugin instance")
|
||||
} else if inst == nil {
|
||||
return nil, errors.New("plugin can not be nil")
|
||||
} else {
|
||||
return inst, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) Load(filename string) (*plugin.Plugin, error) {
|
||||
if value, ok := m.plugins[filename]; ok {
|
||||
return value, nil
|
||||
}
|
||||
m.l.Debug("loading:", filename)
|
||||
if plg, err := plugin.Open(filename); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to load plugin (%s)", filename)
|
||||
} else {
|
||||
m.plugins[filename] = plg
|
||||
return plg, nil
|
||||
}
|
||||
}
|
||||
18
pkg/prompt/aliases.go
Normal file
18
pkg/prompt/aliases.go
Normal file
@ -0,0 +1,18 @@
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"github.com/c-bata/go-prompt"
|
||||
)
|
||||
|
||||
type (
|
||||
Filter = prompt.Filter
|
||||
Suggest = prompt.Suggest
|
||||
Document = prompt.Document
|
||||
)
|
||||
|
||||
var (
|
||||
FilterFuzzy = prompt.FilterFuzzy
|
||||
FilterContains = prompt.FilterContains
|
||||
FilterHasPrefix = prompt.FilterHasPrefix
|
||||
FilterHasSuffix = prompt.FilterHasSuffix
|
||||
)
|
||||
9
pkg/prompt/check/check.go
Normal file
9
pkg/prompt/check/check.go
Normal file
@ -0,0 +1,9 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
)
|
||||
|
||||
type Check func(ctx context.Context, l log.Logger, checkers []Checker) error
|
||||
9
pkg/prompt/check/checker.go
Normal file
9
pkg/prompt/check/checker.go
Normal file
@ -0,0 +1,9 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
)
|
||||
|
||||
type Checker func(ctx context.Context, l log.Logger) (name, note string, ok bool)
|
||||
23
pkg/prompt/check/defaultcheck.go
Normal file
23
pkg/prompt/check/defaultcheck.go
Normal file
@ -0,0 +1,23 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/pterm/pterm"
|
||||
)
|
||||
|
||||
func DefaultCheck(ctx context.Context, l log.Logger, checkers []Checker) error {
|
||||
var data pterm.TableData
|
||||
for _, checker := range checkers {
|
||||
name, note, ok := checker(ctx, l)
|
||||
data = append(data, []string{name, StatusFromBool(ok).String(), pterm.FgGray.Sprint(note)})
|
||||
}
|
||||
table := pterm.DefaultTable
|
||||
table.Separator = " "
|
||||
if err := table.WithData(data).Render(); err != nil {
|
||||
return err
|
||||
}
|
||||
pterm.Println()
|
||||
return nil
|
||||
}
|
||||
20
pkg/prompt/check/status.go
Normal file
20
pkg/prompt/check/status.go
Normal file
@ -0,0 +1,20 @@
|
||||
package check
|
||||
|
||||
type Status string
|
||||
|
||||
const (
|
||||
StatusSuccess = "✅"
|
||||
StatusFailure = "❌"
|
||||
)
|
||||
|
||||
func (s Status) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func StatusFromBool(v bool) Status {
|
||||
if v {
|
||||
return StatusSuccess
|
||||
} else {
|
||||
return StatusFailure
|
||||
}
|
||||
}
|
||||
3
pkg/prompt/flair/defaultflair.go
Normal file
3
pkg/prompt/flair/defaultflair.go
Normal file
@ -0,0 +1,3 @@
|
||||
package flair
|
||||
|
||||
type Flair func(title string) error
|
||||
21
pkg/prompt/flair/flair.go
Normal file
21
pkg/prompt/flair/flair.go
Normal file
@ -0,0 +1,21 @@
|
||||
package flair
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/pterm/pterm/putils"
|
||||
)
|
||||
|
||||
func DefaultFlair(title string) error {
|
||||
pterm.FgGray.Println()
|
||||
if err := pterm.DefaultBigText.WithLetters(
|
||||
putils.LettersFromStringWithStyle(strings.ToUpper(title), pterm.NewStyle(pterm.FgCyan)),
|
||||
putils.LettersFromStringWithStyle("$H", pterm.NewStyle(pterm.FgGreen))).
|
||||
Render(); err != nil {
|
||||
return err
|
||||
}
|
||||
pterm.FgGray.Println("Use `exit` or `Ctrl-D` to exit this program.")
|
||||
pterm.Println()
|
||||
return nil
|
||||
}
|
||||
157
pkg/prompt/history/file.go
Normal file
157
pkg/prompt/history/file.go
Normal file
@ -0,0 +1,157 @@
|
||||
package history
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/gofrs/flock"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
File struct {
|
||||
l log.Logger
|
||||
mu sync.RWMutex
|
||||
lock *flock.Flock
|
||||
limit int
|
||||
filename string
|
||||
lockFilename string
|
||||
}
|
||||
FileOption func(*File) error
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func NewFile(l log.Logger, opts ...FileOption) (*File, error) {
|
||||
inst := &File{
|
||||
l: l,
|
||||
limit: 100,
|
||||
filename: ".posh/history",
|
||||
lockFilename: ".posh/history.lock",
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if opt != nil {
|
||||
if err := opt(inst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
inst.lock = flock.New(inst.lockFilename)
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Options
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func FileWithLimit(v int) FileOption {
|
||||
return func(h *File) error {
|
||||
h.limit = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func FileWithFilename(v string) FileOption {
|
||||
return func(h *File) error {
|
||||
h.filename = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func FileWithLockFilename(v string) FileOption {
|
||||
return func(h *File) error {
|
||||
h.lockFilename = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (h *File) Load(ctx context.Context) ([]string, error) {
|
||||
return h.read(ctx)
|
||||
}
|
||||
|
||||
func (h *File) Persist(ctx context.Context, record string) {
|
||||
go func(ctx context.Context, record string) {
|
||||
if lines, err := h.read(ctx); err != nil {
|
||||
h.l.Warnf("failed to read history file (%s): %s", h.filename, err.Error())
|
||||
return
|
||||
} else if err := h.write(ctx, h.truncate(h.unique(append(lines, record)))); err != nil {
|
||||
h.l.Warnf("failed to write history file (%s): %s", h.filename, err.Error())
|
||||
return
|
||||
}
|
||||
}(ctx, record)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (h *File) read(ctx context.Context) ([]string, error) {
|
||||
h.mu.RLock()
|
||||
defer h.mu.RUnlock()
|
||||
if _, err := h.lock.TryRLockContext(ctx, 100*time.Millisecond); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err := h.lock.Unlock(); err != nil {
|
||||
h.l.Warnf("failed to unlock on history file (%s): %s", h.filename, err.Error())
|
||||
}
|
||||
}()
|
||||
b, err := os.ReadFile(h.filename)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var lines []string
|
||||
for _, line := range strings.Split(string(b), "\n") {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
return lines, nil
|
||||
}
|
||||
|
||||
func (h *File) write(ctx context.Context, lines []string) error {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
if _, err := h.lock.TryLockContext(ctx, 100*time.Millisecond); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := h.lock.Unlock(); err != nil {
|
||||
h.l.Warnf("failed to unlock on history file (%s): %s", h.filename, err.Error())
|
||||
}
|
||||
}()
|
||||
return os.WriteFile(h.filename, []byte(strings.Join(lines, "\n")), 0644)
|
||||
}
|
||||
|
||||
func (h *File) unique(lines []string) []string {
|
||||
var list []string
|
||||
var revList []string
|
||||
keys := make(map[string]bool)
|
||||
for i := len(lines) - 1; i >= 0; i-- {
|
||||
if _, ok := keys[lines[i]]; !ok {
|
||||
revList = append(revList, lines[i])
|
||||
keys[lines[i]] = true
|
||||
}
|
||||
}
|
||||
for i := len(revList) - 1; i >= 0; i-- {
|
||||
list = append(list, revList[i])
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func (h *File) truncate(lines []string) []string {
|
||||
if len(lines) > h.limit {
|
||||
lines = lines[len(lines)-h.limit:]
|
||||
}
|
||||
return lines
|
||||
}
|
||||
10
pkg/prompt/history/history.go
Normal file
10
pkg/prompt/history/history.go
Normal file
@ -0,0 +1,10 @@
|
||||
package history
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type History interface {
|
||||
Load(ctx context.Context) ([]string, error)
|
||||
Persist(ctx context.Context, record string)
|
||||
}
|
||||
32
pkg/prompt/history/noop.go
Normal file
32
pkg/prompt/history/noop.go
Normal file
@ -0,0 +1,32 @@
|
||||
package history
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
)
|
||||
|
||||
type Noop struct {
|
||||
l log.Logger
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func NewNoop(l log.Logger) *Noop {
|
||||
return &Noop{
|
||||
l: l,
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (h *Noop) Load(ctx context.Context) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (h *Noop) Persist(ctx context.Context, record string) {
|
||||
}
|
||||
318
pkg/prompt/prompt.go
Normal file
318
pkg/prompt/prompt.go
Normal file
@ -0,0 +1,318 @@
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
|
||||
"github.com/c-bata/go-prompt"
|
||||
"github.com/c-bata/go-prompt/completer"
|
||||
"github.com/foomo/posh/pkg/command"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/foomo/posh/pkg/prompt/check"
|
||||
"github.com/foomo/posh/pkg/prompt/flair"
|
||||
"github.com/foomo/posh/pkg/prompt/history"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
"github.com/foomo/posh/pkg/shell"
|
||||
)
|
||||
|
||||
type (
|
||||
Prompt struct {
|
||||
l log.Logger
|
||||
ctx context.Context
|
||||
title string
|
||||
flair flair.Flair
|
||||
prefix string
|
||||
check check.Check
|
||||
checkers []check.Checker
|
||||
filter Filter
|
||||
readline *readline.Readline
|
||||
history history.History
|
||||
commands command.Commands
|
||||
// inputRegex - split cmd into args
|
||||
promptOptions []prompt.Option
|
||||
}
|
||||
Option func(*Prompt) error
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Options
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func WithTitle(v string) Option {
|
||||
return func(o *Prompt) error {
|
||||
o.title = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithFlair(v flair.Flair) Option {
|
||||
return func(o *Prompt) error {
|
||||
o.flair = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithPrefix(v string) Option {
|
||||
return func(o *Prompt) error {
|
||||
o.prefix = v + " "
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithCheck(v check.Check) Option {
|
||||
return func(o *Prompt) error {
|
||||
o.check = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithCheckers(v ...check.Checker) Option {
|
||||
return func(o *Prompt) error {
|
||||
o.checkers = append(o.checkers, v...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithContext(v context.Context) Option {
|
||||
return func(o *Prompt) error {
|
||||
o.ctx = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithHistory(v history.History) Option {
|
||||
return func(o *Prompt) error {
|
||||
o.history = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithFileHistory(v ...history.FileOption) Option {
|
||||
return func(o *Prompt) error {
|
||||
if value, err := history.NewFile(o.l, v...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
o.history = value
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithCommands(v command.Commands) Option {
|
||||
return func(p *Prompt) error {
|
||||
p.commands = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithFilter(v Filter) Option {
|
||||
return func(o *Prompt) error {
|
||||
o.filter = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func New(l log.Logger, opts ...Option) (*Prompt, error) {
|
||||
inst := &Prompt{
|
||||
l: l,
|
||||
ctx: context.Background(),
|
||||
title: "posh",
|
||||
prefix: "> ",
|
||||
flair: flair.DefaultFlair,
|
||||
filter: FilterFuzzy,
|
||||
check: check.DefaultCheck,
|
||||
history: history.NewNoop(l),
|
||||
commands: command.Commands{},
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if opt != nil {
|
||||
if err := opt(inst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, err := readline.New(l); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
inst.readline = value
|
||||
}
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Getter
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (s *Prompt) Commands() command.Commands {
|
||||
return s.commands
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (s *Prompt) Run() error {
|
||||
histories, err := s.history.Load(s.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := prompt.New(
|
||||
s.execute,
|
||||
s.complete,
|
||||
prompt.OptionTitle(s.title),
|
||||
prompt.OptionPrefix(s.prefix),
|
||||
prompt.OptionPrefixTextColor(prompt.Cyan),
|
||||
prompt.OptionInputTextColor(prompt.DefaultColor),
|
||||
prompt.OptionCompletionWordSeparator(completer.FilePathCompletionSeparator),
|
||||
prompt.OptionHistoryIgnoreDuplicates(),
|
||||
prompt.OptionHistory(histories),
|
||||
// macos alt+left fix
|
||||
prompt.OptionAddASCIICodeBind(prompt.ASCIICodeBind{
|
||||
ASCIICode: []byte{0x1b, 0x62},
|
||||
Fn: prompt.GoLeftWord,
|
||||
}),
|
||||
// macos alt+right fix
|
||||
prompt.OptionAddASCIICodeBind(prompt.ASCIICodeBind{
|
||||
ASCIICode: []byte{0x1b, 0x66},
|
||||
Fn: prompt.GoRightWord,
|
||||
}),
|
||||
)
|
||||
|
||||
if err := s.flair(s.title); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.check(s.ctx, s.l, s.checkers); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Run()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (s *Prompt) execute(input string) {
|
||||
input = strings.TrimSpace(input)
|
||||
if input == "" {
|
||||
return
|
||||
}
|
||||
|
||||
s.history.Persist(s.ctx, input)
|
||||
|
||||
if err := s.readline.Parse(input); err != nil {
|
||||
s.l.Error("failed to parse line:", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
ctx := s.context()
|
||||
if cmd := s.Commands().Get(s.readline.Cmd()); cmd != nil {
|
||||
s.l.Debugf(`executing command:
|
||||
|
||||
> %s
|
||||
|
||||
%s
|
||||
`, input, s.readline.String())
|
||||
if value, ok := cmd.(command.Validator); ok {
|
||||
if err := value.Validate(ctx, s.readline); err != nil {
|
||||
s.l.Error(err.Error())
|
||||
}
|
||||
}
|
||||
if err := cmd.Execute(ctx, s.readline); err != nil {
|
||||
s.l.Error(err.Error())
|
||||
}
|
||||
} else if err := shell.New(ctx, s.l, input).Run(); err != nil {
|
||||
s.l.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Prompt) complete(d prompt.Document) []prompt.Suggest {
|
||||
input := d.TextBeforeCursor()
|
||||
if input == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := s.readline.Parse(input); err != nil {
|
||||
s.l.Debug("failed to parse line:", err.Error())
|
||||
return nil
|
||||
}
|
||||
word := d.GetWordBeforeCursor()
|
||||
|
||||
// return root completion
|
||||
if s.readline.IsModeDefault() && s.readline.Args().LenIs(0) {
|
||||
var suggests []prompt.Suggest
|
||||
for _, inst := range s.Commands().List() {
|
||||
suggests = append(suggests, prompt.Suggest{Text: inst.Name(), Description: inst.Description()})
|
||||
}
|
||||
return s.filter(suggests, word, true)
|
||||
}
|
||||
|
||||
// retrieve command instance
|
||||
cmd := s.commands.Get(s.readline.Cmd())
|
||||
if cmd == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx := s.context()
|
||||
|
||||
switch s.readline.Mode() {
|
||||
case readline.ModeArgs:
|
||||
if value, ok := cmd.(command.ArgumentCompleter); ok {
|
||||
return s.filter(value.CompleteArguments(ctx, s.readline, d), word, true)
|
||||
} else if value, ok := cmd.(command.Completer); ok {
|
||||
return s.filter(value.Complete(ctx, s.readline, d), word, true)
|
||||
}
|
||||
case readline.ModeFlags:
|
||||
if value, ok := cmd.(command.FlagCompleter); ok {
|
||||
return s.filter(value.CompleteFlags(ctx, s.readline, d), word, true)
|
||||
} else if value, ok := cmd.(command.Completer); ok {
|
||||
return s.filter(value.Complete(ctx, s.readline, d), word, true)
|
||||
}
|
||||
case readline.ModePassThroughArgs:
|
||||
if value, ok := cmd.(command.PassThroughArgsCompleter); ok {
|
||||
return s.filter(value.CompletePassTroughArgs(ctx, s.readline, d), word, true)
|
||||
} else if value, ok := cmd.(command.Completer); ok {
|
||||
return s.filter(value.Complete(ctx, s.readline, d), word, true)
|
||||
}
|
||||
case readline.ModePassThroughFlags:
|
||||
if value, ok := cmd.(command.PassThroughFlagsCompleter); ok {
|
||||
return s.filter(value.CompletePassTroughFlags(ctx, s.readline, d), word, true)
|
||||
} else if value, ok := cmd.(command.Completer); ok {
|
||||
return s.filter(value.Complete(ctx, s.readline, d), word, true)
|
||||
}
|
||||
case readline.ModeAdditionalArgs:
|
||||
if value, ok := cmd.(command.AdditionalArgsCompleter); ok {
|
||||
return s.filter(value.CompleteAdditionalArgs(ctx, s.readline, d), word, true)
|
||||
} else if value, ok := cmd.(command.Completer); ok {
|
||||
return s.filter(value.Complete(ctx, s.readline, d), word, true)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// context returns and watches over a new context
|
||||
func (s *Prompt) context() context.Context {
|
||||
ctx, cancel := context.WithCancel(s.ctx)
|
||||
go func(ctx context.Context, cancel context.CancelFunc) {
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, os.Interrupt)
|
||||
select {
|
||||
case <-sigChan:
|
||||
cancel()
|
||||
return
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}(ctx, cancel)
|
||||
return ctx
|
||||
}
|
||||
34
pkg/readline/arg.go
Normal file
34
pkg/readline/arg.go
Normal file
@ -0,0 +1,34 @@
|
||||
package readline
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Arg string
|
||||
|
||||
func (a Arg) String() string {
|
||||
return string(a)
|
||||
}
|
||||
|
||||
func (a Arg) IsPipe() bool {
|
||||
return a == "|"
|
||||
}
|
||||
|
||||
func (a Arg) IsPass() bool {
|
||||
return a == "--"
|
||||
}
|
||||
|
||||
func (a Arg) IsFlag() bool {
|
||||
return strings.HasPrefix(a.String(), "-") && len(a) > 1
|
||||
}
|
||||
|
||||
func (a Arg) IsRedirect() bool {
|
||||
return a == ">" || a == ">>" ||
|
||||
a == "2>" || a == "2>>" ||
|
||||
a == "&>" || a == "&>>" ||
|
||||
a == "2>&1"
|
||||
}
|
||||
|
||||
func (a Arg) IsAdditional() bool {
|
||||
return a.IsPipe() || a.IsRedirect()
|
||||
}
|
||||
76
pkg/readline/args.go
Normal file
76
pkg/readline/args.go
Normal file
@ -0,0 +1,76 @@
|
||||
package readline
|
||||
|
||||
type Args []string
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func NewArgs(args []string) Args {
|
||||
ret := make(Args, len(args))
|
||||
for i, arg := range args {
|
||||
ret[i] = arg
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (a Args) At(v int) string {
|
||||
if a.HasIndex(v) {
|
||||
return a[v]
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (a Args) Empty() bool {
|
||||
return a == nil || a.LenIs(0)
|
||||
}
|
||||
|
||||
func (a Args) Has(v string) bool {
|
||||
for _, arg := range a {
|
||||
if arg == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a Args) HasIndex(v int) bool {
|
||||
return a.LenGte(v + 1)
|
||||
}
|
||||
|
||||
func (a Args) Len() int {
|
||||
return len(a)
|
||||
}
|
||||
|
||||
func (a Args) LenIs(v int) bool {
|
||||
return a.Len() == v
|
||||
}
|
||||
|
||||
func (a Args) LenGt(v int) bool {
|
||||
return a.Len() > v
|
||||
}
|
||||
|
||||
func (a Args) LenGte(v int) bool {
|
||||
return a.Len() >= v
|
||||
}
|
||||
|
||||
func (a Args) LenLt(v int) bool {
|
||||
return a.Len() < v
|
||||
}
|
||||
|
||||
func (a Args) LenLte(v int) bool {
|
||||
return a.Len() <= v
|
||||
}
|
||||
|
||||
func (a Args) Last() string {
|
||||
if !a.Empty() {
|
||||
return a[a.Len()-1]
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
11
pkg/readline/mode.go
Normal file
11
pkg/readline/mode.go
Normal file
@ -0,0 +1,11 @@
|
||||
package readline
|
||||
|
||||
type Mode string
|
||||
|
||||
const (
|
||||
ModeArgs Mode = ""
|
||||
ModeFlags Mode = "flags"
|
||||
ModePassThroughArgs Mode = "passThrough"
|
||||
ModePassThroughFlags Mode = "passThroughFlags"
|
||||
ModeAdditionalArgs Mode = "additional"
|
||||
)
|
||||
330
pkg/readline/readline.go
Normal file
330
pkg/readline/readline.go
Normal file
@ -0,0 +1,330 @@
|
||||
package readline
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
)
|
||||
|
||||
type (
|
||||
Readline struct {
|
||||
l log.Logger
|
||||
mu sync.RWMutex
|
||||
cmd string
|
||||
mode Mode
|
||||
args Args
|
||||
flags Args
|
||||
flagSet *FlagSet
|
||||
passThroughArgs Args
|
||||
passThroughFlags Args
|
||||
passThroughFlagSet *FlagSet
|
||||
additionalArgs Args
|
||||
// regex - split cmd into args (https://regex101.com/r/EgiOzv/1)
|
||||
regex *regexp.Regexp
|
||||
}
|
||||
Option func(*Readline) error
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Options
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func WithRegex(v *regexp.Regexp) Option {
|
||||
return func(o *Readline) error {
|
||||
o.regex = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func New(l log.Logger, opts ...Option) (*Readline, error) {
|
||||
inst := &Readline{
|
||||
l: l,
|
||||
regex: regexp.MustCompile(`[^\s"']+|"([^"]*)"|'([^']*)'|(\s$)`),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if opt != nil {
|
||||
if err := opt(inst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Getter
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (a *Readline) Mode() Mode {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return a.mode
|
||||
}
|
||||
|
||||
func (a *Readline) Cmd() string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return a.cmd
|
||||
}
|
||||
|
||||
func (a *Readline) Args() Args {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return a.args
|
||||
}
|
||||
|
||||
func (a *Readline) Flags() Args {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return a.flags
|
||||
}
|
||||
|
||||
func (a *Readline) FlagSet() *FlagSet {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return a.flagSet
|
||||
}
|
||||
|
||||
func (a *Readline) PassThroughArgs() Args {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return a.passThroughArgs
|
||||
}
|
||||
|
||||
func (a *Readline) PassThroughFlags() Args {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return a.passThroughFlags
|
||||
}
|
||||
|
||||
func (a *Readline) PassThroughFlagSet() *FlagSet {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return a.passThroughFlagSet
|
||||
}
|
||||
|
||||
func (a *Readline) AdditionalArgs() Args {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return a.additionalArgs
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (a *Readline) Parse(input string) error {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
a.reset()
|
||||
parts := a.regex.FindAllString(input, -1)
|
||||
|
||||
if len(parts) == 0 {
|
||||
return nil
|
||||
} else {
|
||||
a.cmd, parts = parts[0], parts[1:]
|
||||
}
|
||||
|
||||
last := len(parts) - 1
|
||||
for i, part := range parts {
|
||||
if a.mode == ModeArgs && Arg(part).IsFlag() {
|
||||
a.mode = ModeFlags
|
||||
}
|
||||
if i != last && (a.mode == ModeArgs || a.mode == ModeFlags) && Arg(part).IsPass() {
|
||||
a.mode = ModePassThroughArgs
|
||||
}
|
||||
if a.mode == ModePassThroughArgs && Arg(part).IsFlag() {
|
||||
a.mode = ModePassThroughFlags
|
||||
}
|
||||
if Arg(part).IsAdditional() && i < len(parts)-1 {
|
||||
a.mode = ModeAdditionalArgs
|
||||
}
|
||||
|
||||
switch a.mode {
|
||||
case ModeArgs:
|
||||
a.args = append(a.args, part)
|
||||
case ModeFlags:
|
||||
a.flags = append(a.flags, part)
|
||||
case ModePassThroughArgs:
|
||||
a.passThroughArgs = append(a.passThroughArgs, part)
|
||||
case ModePassThroughFlags:
|
||||
a.passThroughFlags = append(a.passThroughFlags, part)
|
||||
case ModeAdditionalArgs:
|
||||
a.additionalArgs = append(a.additionalArgs, part)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Readline) SetFlags(fs *FlagSet) {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
a.flagSet = fs
|
||||
}
|
||||
|
||||
func (a *Readline) ParseFlags() error {
|
||||
if fs := a.FlagSet(); fs == nil {
|
||||
return nil
|
||||
} else if err := fs.Parse(a.flags); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Readline) SetParsePassThroughFlags(fs *FlagSet) {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
a.passThroughFlagSet = fs
|
||||
}
|
||||
|
||||
func (a *Readline) ParsePassThroughFlags() error {
|
||||
if fs := a.PassThroughFlagSet(); fs == nil {
|
||||
return nil
|
||||
} else if err := fs.Parse(a.passThroughFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Readline) String() string {
|
||||
return fmt.Sprintf(`
|
||||
Cmd: %s
|
||||
Mode %s
|
||||
Args: %s
|
||||
Flags: %s
|
||||
PassThroughArgs: %s
|
||||
PassThroughFlags: %s
|
||||
AdditionalArgs %s
|
||||
`, a.Cmd(), a.Mode(), a.Args(), a.Flags(), a.PassThroughArgs(), a.PassThroughFlags(), a.AdditionalArgs())
|
||||
}
|
||||
|
||||
func (a *Readline) IsModeDefault() bool {
|
||||
return a.Mode() == ModeArgs
|
||||
}
|
||||
|
||||
func (a *Readline) IsModePassThrough() bool {
|
||||
return a.Mode() == ModePassThroughArgs
|
||||
}
|
||||
|
||||
func (a *Readline) IsModeAdditional() bool {
|
||||
return a.Mode() == ModeAdditionalArgs
|
||||
}
|
||||
|
||||
func (a *Readline) AllFlags() []*flag.Flag {
|
||||
var ret []*flag.Flag
|
||||
if fs := a.FlagSet(); fs != nil {
|
||||
fs.VisitAll(func(f *flag.Flag) {
|
||||
ret = append(ret, f)
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (a *Readline) VisitedFlags() []*flag.Flag {
|
||||
var ret []*flag.Flag
|
||||
if fs := a.FlagSet(); fs != nil {
|
||||
fs.Visit(func(f *flag.Flag) {
|
||||
ret = append(ret, f)
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (a *Readline) AllPassThroughFlags() []*flag.Flag {
|
||||
var ret []*flag.Flag
|
||||
if fs := a.PassThroughFlagSet(); fs != nil {
|
||||
fs.VisitAll(func(f *flag.Flag) {
|
||||
ret = append(ret, f)
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (a *Readline) reset() {
|
||||
a.mode = ModeArgs
|
||||
a.cmd = ""
|
||||
a.args = nil
|
||||
a.flags = nil
|
||||
a.flagSet = nil
|
||||
a.passThroughArgs = nil
|
||||
a.passThroughFlags = nil
|
||||
a.passThroughFlagSet = nil
|
||||
a.additionalArgs = nil
|
||||
}
|
||||
|
||||
type FlagSet struct {
|
||||
*flag.FlagSet
|
||||
}
|
||||
|
||||
func NewFlagSet(handler func(set *FlagSet)) *FlagSet {
|
||||
inst := &FlagSet{
|
||||
FlagSet: flag.NewFlagSet("readline", flag.ContinueOnError),
|
||||
}
|
||||
if handler != nil {
|
||||
handler(inst)
|
||||
}
|
||||
return inst
|
||||
}
|
||||
|
||||
func (a *FlagSet) GetString(name string) string {
|
||||
if f := a.FlagSet.Lookup(name); f == nil {
|
||||
return ""
|
||||
} else if !a.flagIsSet(name) {
|
||||
return f.DefValue
|
||||
} else {
|
||||
return f.Value.String()
|
||||
}
|
||||
}
|
||||
func (a *FlagSet) GetInt64(name string) int64 {
|
||||
if value := a.GetString(name); value == "" {
|
||||
return 0
|
||||
} else if v, err := strconv.ParseInt(value, 10, 64); err != nil {
|
||||
return 0
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (a *FlagSet) GetFloat64(name string) float64 {
|
||||
if value := a.GetString(name); value == "" {
|
||||
return 0
|
||||
} else if v, err := strconv.ParseFloat(value, 64); err != nil {
|
||||
return 0
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (a *FlagSet) GetBool(name string) bool {
|
||||
if value := a.GetString(name); value == "" {
|
||||
return false
|
||||
} else if v, err := strconv.ParseBool(value); err != nil {
|
||||
return false
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
func (a *FlagSet) flagIsSet(name string) bool {
|
||||
found := false
|
||||
if fs := a.FlagSet; fs != nil {
|
||||
fs.Visit(func(f *flag.Flag) {
|
||||
if f.Name == name {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
}
|
||||
return found
|
||||
}
|
||||
139
pkg/scaffold/scaffold.go
Normal file
139
pkg/scaffold/scaffold.go
Normal file
@ -0,0 +1,139 @@
|
||||
package scaffold
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/Masterminds/sprig/v3"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
Scaffold struct {
|
||||
l log.Logger
|
||||
dry bool
|
||||
force bool
|
||||
}
|
||||
Option func(*Scaffold) error
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Options
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func WithDry(v bool) Option {
|
||||
return func(o *Scaffold) error {
|
||||
o.dry = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithForce(v bool) Option {
|
||||
return func(o *Scaffold) error {
|
||||
o.force = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithLogger(v log.Logger) Option {
|
||||
return func(o *Scaffold) error {
|
||||
o.l = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func New(opts ...Option) (*Scaffold, error) {
|
||||
inst := &Scaffold{
|
||||
l: log.NewFmt(),
|
||||
dry: false,
|
||||
force: false,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if opt != nil {
|
||||
if err := opt(inst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
func (s *Scaffold) Render(source fs.FS, target string, vars any) error {
|
||||
// validate target
|
||||
if stat, err := os.Stat(target); errors.Is(err, os.ErrNotExist) {
|
||||
s.l.Print("scaffold:", target)
|
||||
if err := os.MkdirAll(target, os.ModePerm); err != nil {
|
||||
return errors.Wrapf(err, "failed to create target folder (%s)", target)
|
||||
}
|
||||
} else if err != nil {
|
||||
return errors.Wrapf(err, "failed to stat target folder (%s)", target)
|
||||
} else if !stat.IsDir() {
|
||||
return fmt.Errorf("target not a directory (%s)", target)
|
||||
}
|
||||
|
||||
// iterate source
|
||||
if err := fs.WalkDir(source, ".", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to walk fs dir")
|
||||
}
|
||||
|
||||
filename := filepath.Join(target, strings.ReplaceAll(path, "$", ""))
|
||||
|
||||
if path == "." {
|
||||
return nil
|
||||
} else if d.IsDir() {
|
||||
s.l.Print("scaffold:", filename)
|
||||
return os.MkdirAll(filename, os.ModePerm)
|
||||
} else {
|
||||
tpl, err := template.New(d.Name()).Funcs(sprig.FuncMap()).ParseFS(source, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if stat, err := os.Stat(filename); errors.Is(err, fs.ErrNotExist) {
|
||||
// all good
|
||||
} else if err != nil {
|
||||
return errors.Wrapf(err, "failed to stat target (%s)", filename)
|
||||
} else if stat.IsDir() {
|
||||
return fmt.Errorf("target file is an existing directory (%s)", filename)
|
||||
} else if !s.force {
|
||||
return fmt.Errorf("target file already exists (%s)", filename)
|
||||
}
|
||||
|
||||
var out io.Writer
|
||||
if s.dry {
|
||||
out = os.Stdout
|
||||
} else {
|
||||
s.l.Print("scaffold:", filename)
|
||||
if file, err := os.Create(filename); err != nil {
|
||||
return errors.Wrapf(err, "failed to create target file (%s)", filename)
|
||||
} else {
|
||||
out = file
|
||||
defer func() {
|
||||
_ = file.Close()
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
if err := tpl.Execute(out, vars); err != nil {
|
||||
return errors.Wrapf(err, "failed to render target file (%s)", filename)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}); err != nil {
|
||||
return errors.Wrapf(err, "failed to render scaffold to %s", target)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
134
pkg/shell/shell.go
Normal file
134
pkg/shell/shell.go
Normal file
@ -0,0 +1,134 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
)
|
||||
|
||||
// Shell struct
|
||||
type Shell struct {
|
||||
l log.Logger
|
||||
cmd *exec.Cmd
|
||||
quiet bool
|
||||
args []string
|
||||
Stdin io.Reader
|
||||
Stdout io.Writer
|
||||
Stderr io.Writer
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func New(ctx context.Context, l log.Logger, inputs ...interface{}) *Shell {
|
||||
var args []string
|
||||
for _, input := range inputs {
|
||||
if value, ok := input.(string); ok {
|
||||
args = append(args, value)
|
||||
} else if value, ok := input.([]string); ok {
|
||||
args = append(args, value...)
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("%v", args))
|
||||
}
|
||||
}
|
||||
cmd := exec.CommandContext(ctx, "/bin/sh", "-c")
|
||||
cmd.Env = os.Environ()
|
||||
return &Shell{
|
||||
l: l,
|
||||
cmd: cmd,
|
||||
args: args,
|
||||
Stdin: os.Stdin,
|
||||
Stdout: os.Stdout,
|
||||
Stderr: os.Stderr,
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (s *Shell) Args(args ...string) *Shell {
|
||||
s.args = append(s.args, args...)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Shell) Env(env []string) *Shell {
|
||||
s.cmd.Env = append(s.cmd.Env, env...)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Shell) Dir(dir string) *Shell {
|
||||
s.cmd.Dir = dir
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Shell) Quiet() *Shell {
|
||||
s.quiet = true
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Shell) Run() error {
|
||||
args := s.args
|
||||
s.cmd.Args = append(s.cmd.Args, strings.Join(args, " "))
|
||||
s.cmd.Stdin = s.Stdin
|
||||
if !s.quiet {
|
||||
s.cmd.Stdout = s.Stdout
|
||||
s.cmd.Stderr = s.Stderr
|
||||
}
|
||||
s.debug()
|
||||
return s.cmd.Run()
|
||||
}
|
||||
|
||||
func (s *Shell) Output() ([]byte, error) {
|
||||
args := s.args
|
||||
s.cmd.Args = append(s.cmd.Args, strings.Join(args, " "))
|
||||
if !s.quiet {
|
||||
s.cmd.Stdin = s.Stdin
|
||||
s.cmd.Stderr = s.Stderr
|
||||
}
|
||||
s.debug()
|
||||
return s.cmd.Output()
|
||||
}
|
||||
|
||||
// Wait ...
|
||||
func (s *Shell) Wait() error {
|
||||
args := s.args
|
||||
s.cmd.Args = append(s.cmd.Args, strings.Join(args, " "))
|
||||
s.cmd.Stdin = s.Stdin
|
||||
if !s.quiet {
|
||||
s.cmd.Stdout = s.Stdout
|
||||
s.cmd.Stderr = s.Stderr
|
||||
}
|
||||
s.debug()
|
||||
// start the process and wait till it's finished
|
||||
if err := s.cmd.Start(); err != nil {
|
||||
return err
|
||||
} else if err := s.cmd.Wait(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (s *Shell) debug() {
|
||||
s.l.Debugf(`"Executing:
|
||||
$ %s
|
||||
|
||||
Directory: %s
|
||||
|
||||
%s
|
||||
`,
|
||||
s.cmd.String(),
|
||||
s.cmd.Dir,
|
||||
strings.Join(s.cmd.Environ(), "\n"),
|
||||
)
|
||||
}
|
||||
41
pkg/validate/dependenciesenv.go
Normal file
41
pkg/validate/dependenciesenv.go
Normal file
@ -0,0 +1,41 @@
|
||||
package validate
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/foomo/fender/fend"
|
||||
"github.com/foomo/fender/rule"
|
||||
"github.com/foomo/posh/pkg/config"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
)
|
||||
|
||||
type DependenciesEnvRule func(l log.Logger, v config.DependenciesEnv) rule.Rule
|
||||
|
||||
func DependenciesEnvs(l log.Logger, v []config.DependenciesEnv) []fend.Fend {
|
||||
ret := make([]fend.Fend, len(v))
|
||||
for i, vv := range v {
|
||||
ret[i] = DependenciesEnv(l, vv, DependenciesEnvExists)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func DependenciesEnv(l log.Logger, v config.DependenciesEnv, rules ...DependenciesEnvRule) fend.Fend {
|
||||
return func() []rule.Rule {
|
||||
ret := make([]rule.Rule, len(rules))
|
||||
for i, r := range rules {
|
||||
ret[i] = r(l, v)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
func DependenciesEnvExists(l log.Logger, v config.DependenciesEnv) rule.Rule {
|
||||
return func() (*rule.Error, error) {
|
||||
l.Debug("validate env exists:", v.String())
|
||||
if value := os.Getenv(v.Name); value == "" {
|
||||
return nil, errors.New(v.Help)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
70
pkg/validate/dependenciespackage.go
Normal file
70
pkg/validate/dependenciespackage.go
Normal file
@ -0,0 +1,70 @@
|
||||
package validate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/foomo/fender/fend"
|
||||
"github.com/foomo/fender/rule"
|
||||
"github.com/foomo/posh/pkg/config"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type DependenciesPackageRule func(ctx context.Context, l log.Logger, v config.DependenciesPackage) rule.Rule
|
||||
|
||||
func DependenciesPackages(ctx context.Context, l log.Logger, v []config.DependenciesPackage) []fend.Fend {
|
||||
ret := make([]fend.Fend, len(v))
|
||||
for i, vv := range v {
|
||||
ret[i] = DependenciesPackage(ctx, l, vv, DependenciesPackageExists, DependenciesPackageVersion)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func DependenciesPackage(ctx context.Context, l log.Logger, v config.DependenciesPackage, rules ...DependenciesPackageRule) fend.Fend {
|
||||
return func() []rule.Rule {
|
||||
ret := make([]rule.Rule, len(rules))
|
||||
for i, r := range rules {
|
||||
ret[i] = r(ctx, l, v)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
func DependenciesPackageExists(ctx context.Context, l log.Logger, v config.DependenciesPackage) rule.Rule {
|
||||
return func() (*rule.Error, error) {
|
||||
l.Debug("validate package exists:", v.String())
|
||||
if output, err := exec.LookPath(v.Name); err != nil {
|
||||
l.Debug(err.Error(), output)
|
||||
return nil, fmt.Errorf(v.Help, v.Version)
|
||||
} else if output == "" {
|
||||
l.Debugf("missing executable %s", v.Name)
|
||||
return nil, fmt.Errorf(v.Help, v.Version)
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func DependenciesPackageVersion(ctx context.Context, l log.Logger, v config.DependenciesPackage) rule.Rule {
|
||||
return func() (*rule.Error, error) {
|
||||
l.Debug("validate package version:", v.String())
|
||||
if output, err := exec.CommandContext(ctx, "sh", "-c", v.Command).CombinedOutput(); err != nil {
|
||||
return nil, err
|
||||
} else if actual := strings.TrimPrefix(strings.TrimSpace(string(output)), "v"); actual == "" {
|
||||
return nil, fmt.Errorf("failed to retrieve version: %s", string(output))
|
||||
} else if c, err := semver.NewConstraint(v.Version); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to create version constraint: %s", v.Version)
|
||||
} else if version, err := semver.NewVersion(actual); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to create version")
|
||||
} else if !c.Check(version) {
|
||||
l.Debug("wrong package version:", actual)
|
||||
return nil, fmt.Errorf(v.Help, v.Version)
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
43
pkg/validate/dependenciesscript.go
Normal file
43
pkg/validate/dependenciesscript.go
Normal file
@ -0,0 +1,43 @@
|
||||
package validate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
|
||||
"github.com/foomo/fender/fend"
|
||||
"github.com/foomo/fender/rule"
|
||||
"github.com/foomo/posh/pkg/config"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type DependenciesScriptRule func(ctx context.Context, l log.Logger, v config.DependenciesScript) rule.Rule
|
||||
|
||||
func DependenciesScripts(ctx context.Context, l log.Logger, v []config.DependenciesScript) []fend.Fend {
|
||||
ret := make([]fend.Fend, len(v))
|
||||
for i, vv := range v {
|
||||
ret[i] = DependenciesScript(ctx, l, vv, DependenciesScriptStatus)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func DependenciesScript(ctx context.Context, l log.Logger, v config.DependenciesScript, rules ...DependenciesScriptRule) fend.Fend {
|
||||
return func() []rule.Rule {
|
||||
ret := make([]rule.Rule, len(rules))
|
||||
for i, r := range rules {
|
||||
ret[i] = r(ctx, l, v)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
func DependenciesScriptStatus(ctx context.Context, l log.Logger, v config.DependenciesScript) rule.Rule {
|
||||
return func() (*rule.Error, error) {
|
||||
l.Debug("validate script status:", v.String())
|
||||
if output, err := exec.CommandContext(ctx, "sh", "-c", v.Command).CombinedOutput(); err != nil {
|
||||
l.Debug(string(output))
|
||||
return nil, errors.Wrap(err, v.Help)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
64
pkg/validate/git.go
Normal file
64
pkg/validate/git.go
Normal file
@ -0,0 +1,64 @@
|
||||
package validate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/foomo/fender/fend"
|
||||
"github.com/foomo/fender/rule"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type GitRule func(ctx context.Context, l log.Logger) rule.Rule
|
||||
|
||||
func GitUser(ctx context.Context, l log.Logger, rules ...GitRule) fend.Fend {
|
||||
return func() []rule.Rule {
|
||||
ret := make([]rule.Rule, len(rules))
|
||||
for i, r := range rules {
|
||||
ret[i] = r(ctx, l)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
func GitUserName(ctx context.Context, l log.Logger) rule.Rule {
|
||||
return func() (*rule.Error, error) {
|
||||
l.Debug("validate git user.name")
|
||||
if output, err := exec.CommandContext(ctx, "git", "config", "user.name").CombinedOutput(); err != nil {
|
||||
return nil, errors.Wrap(err, string(output))
|
||||
} else if parts := strings.Split(trim(string(output)), " "); len(parts) < 2 {
|
||||
return nil, errors.New(`
|
||||
Please configure a human readable git name e.g. "Max Mustermann" instead of "` + parts[0] + `".
|
||||
|
||||
$ git config user.name "Max Mustermann"
|
||||
`)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GitUserEmail(pattern string) GitRule {
|
||||
reg := regexp.MustCompile(pattern)
|
||||
return func(ctx context.Context, l log.Logger) rule.Rule {
|
||||
return func() (*rule.Error, error) {
|
||||
l.Debug("validate git user.email")
|
||||
if output, err := exec.CommandContext(ctx, "git", "config", "user.email").CombinedOutput(); err != nil {
|
||||
return nil, errors.Wrap(err, string(output))
|
||||
} else if output := trim(string(output)); !reg.MatchString(output) {
|
||||
return nil, errors.New(`
|
||||
Please configure your github email to match the pattern "` + pattern + ` instead of "` + string(output) + `".
|
||||
|
||||
$ git config user.email "max.muster@dev.null"
|
||||
`)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func trim(s string) string {
|
||||
return strings.TrimSuffix(strings.TrimSpace(s), "\n")
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user