mirror of
https://github.com/jimeh/evm.git
synced 2026-02-18 23:16:39 +00:00
refactor: extract core logic to a plain Go package
This commit is contained in:
@@ -1,35 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
|
||||||
|
|
||||||
func configCommand() (*cobra.Command, error) {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "config",
|
|
||||||
Short: "Show evm environment/setup details.",
|
|
||||||
Aliases: []string{"env", "info"},
|
|
||||||
ValidArgs: []string{},
|
|
||||||
RunE: configRunE,
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Flags().StringP("format", "f", "", "output format (yaml or json)")
|
|
||||||
err := viper.BindPFlag("info.format", cmd.Flags().Lookup("format"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func configRunE(cmd *cobra.Command, _ []string) error {
|
|
||||||
conf, err := getConfig()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
format := viper.GetString("info.format")
|
|
||||||
|
|
||||||
return render(cmd.OutOrStdout(), format, conf)
|
|
||||||
}
|
|
||||||
135
command_exec.go
135
command_exec.go
@@ -1,135 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func execCommand() (*cobra.Command, error) {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "exec <binary> [args]...",
|
|
||||||
Short: "Execute named binary from current " +
|
|
||||||
"Emacs version",
|
|
||||||
Args: cobra.MinimumNArgs(1),
|
|
||||||
SilenceUsage: true,
|
|
||||||
DisableFlagParsing: true,
|
|
||||||
DisableFlagsInUseLine: true,
|
|
||||||
Hidden: true,
|
|
||||||
ValidArgsFunction: execValidArgs,
|
|
||||||
RunE: execRunE,
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func execRunE(cmd *cobra.Command, args []string) error {
|
|
||||||
conf, err := getConfig()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
version, err := newEmacsVersion(conf, conf.Current.Version)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if bin, ok := version.BinPath(args[0]); ok {
|
|
||||||
select {
|
|
||||||
case <-cmd.Context().Done():
|
|
||||||
return cmd.Context().Err()
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
execArgs := append([]string{bin}, args[1:]...)
|
|
||||||
execEnv := os.Environ()
|
|
||||||
for i := 0; i < len(execEnv); i++ {
|
|
||||||
if strings.HasPrefix(execEnv[i], "PATH=") {
|
|
||||||
execEnv[i] = "PATH=" + version.Bin + ":" + execEnv[i][5:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return syscall.Exec(bin, execArgs, execEnv)
|
|
||||||
}
|
|
||||||
|
|
||||||
versions, err := newEmacsVersions(conf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var availableIn []string
|
|
||||||
for _, ev := range versions {
|
|
||||||
if _, ok := ev.BinPath(args[0]); ok {
|
|
||||||
availableIn = append(availableIn, ev.Version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
err = execOtherVersionsTemplate.Execute(&buf, &execOtherVersionsData{
|
|
||||||
Name: args[0],
|
|
||||||
Current: conf.Current.Version,
|
|
||||||
AvailableIn: availableIn,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors.New(buf.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func execValidArgs(
|
|
||||||
_ *cobra.Command,
|
|
||||||
args []string,
|
|
||||||
toComplete string,
|
|
||||||
) ([]string, cobra.ShellCompDirective) {
|
|
||||||
var r []string
|
|
||||||
|
|
||||||
if len(args) > 0 {
|
|
||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
||||||
}
|
|
||||||
|
|
||||||
conf, err := getConfig()
|
|
||||||
if err != nil {
|
|
||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
||||||
}
|
|
||||||
|
|
||||||
version, err := newEmacsVersion(conf, conf.Current.Version)
|
|
||||||
if err != nil {
|
|
||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, bin := range version.Binaries {
|
|
||||||
if toComplete == "" || strings.HasPrefix(bin, toComplete) {
|
|
||||||
r = append(r, bin)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r, cobra.ShellCompDirectiveNoFileComp
|
|
||||||
}
|
|
||||||
|
|
||||||
type execOtherVersionsData struct {
|
|
||||||
Name string
|
|
||||||
Current string
|
|
||||||
AvailableIn []string
|
|
||||||
}
|
|
||||||
|
|
||||||
var execOtherVersionsTemplate = template.Must(template.New("other").Parse(
|
|
||||||
`{{ if gt (len .AvailableIn) 0 -}}
|
|
||||||
Current Emacs version ({{.Current}}) does not have a "{{.Name}}" executable.
|
|
||||||
|
|
||||||
"{{.Name}}" is available in the following Emacs versions:
|
|
||||||
{{- range .AvailableIn }}
|
|
||||||
- {{ . }}
|
|
||||||
{{- end -}}
|
|
||||||
{{ else -}}
|
|
||||||
"{{.Name}}" executable is not available in any installed Emacs version.
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
Change version with: evm use <version>
|
|
||||||
List all installed versions with: evm list`,
|
|
||||||
))
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
|
||||||
|
|
||||||
func listCommand() (*cobra.Command, error) {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "list",
|
|
||||||
Short: "List all Emacs versions found in " +
|
|
||||||
"`$EVM_ROOT/versions/*'",
|
|
||||||
Aliases: []string{"ls", "versions"},
|
|
||||||
Args: cobra.ExactArgs(0),
|
|
||||||
ValidArgsFunction: listValidArgs,
|
|
||||||
RunE: listRunE,
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Flags().StringP("format", "f", "", "output format (yaml or json)")
|
|
||||||
err := viper.BindPFlag("list.format", cmd.Flags().Lookup("format"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func listRunE(cmd *cobra.Command, _ []string) error {
|
|
||||||
conf, err := getConfig()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
format := viper.GetString("list.format")
|
|
||||||
|
|
||||||
versions, err := newEmacsVersions(conf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
results := &listResults{
|
|
||||||
Current: conf.Current.Version,
|
|
||||||
Versions: versions,
|
|
||||||
}
|
|
||||||
|
|
||||||
return render(cmd.OutOrStdout(), format, results)
|
|
||||||
}
|
|
||||||
|
|
||||||
func listValidArgs(
|
|
||||||
_ *cobra.Command,
|
|
||||||
args []string,
|
|
||||||
toComplete string,
|
|
||||||
) ([]string, cobra.ShellCompDirective) {
|
|
||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
||||||
}
|
|
||||||
|
|
||||||
type listResults struct {
|
|
||||||
Current string `yaml:"current" json:"current"`
|
|
||||||
Versions emacsVersions `yaml:"versions" json:"versions"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lr *listResults) WriteTo(w io.Writer) (int64, error) {
|
|
||||||
var b []byte
|
|
||||||
|
|
||||||
for _, ver := range lr.Versions {
|
|
||||||
if lr.Current == ver.Version {
|
|
||||||
b = append(b, []byte("* ")...)
|
|
||||||
} else {
|
|
||||||
b = append(b, []byte(" ")...)
|
|
||||||
}
|
|
||||||
|
|
||||||
b = append(b, []byte(ver.Version)...)
|
|
||||||
b = append(b, byte('\n'))
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err := w.Write(b)
|
|
||||||
|
|
||||||
return int64(n), err
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
|
||||||
|
|
||||||
func rootCommand() (*cobra.Command, error) {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "evm",
|
|
||||||
Short: "A simple and opinionated Emacs Version Manager and build tool.",
|
|
||||||
}
|
|
||||||
|
|
||||||
mode := os.Getenv("EVM_MODE")
|
|
||||||
if mode != "system" {
|
|
||||||
mode = "user"
|
|
||||||
}
|
|
||||||
|
|
||||||
viper.SetDefault("mode", mode)
|
|
||||||
|
|
||||||
rootDir := filepath.Join(string(os.PathSeparator), "opt", "evm")
|
|
||||||
if mode == "user" {
|
|
||||||
rootDir = filepath.Join("$HOME", ".evm")
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.PersistentFlags().String("root", rootDir, "Root directory")
|
|
||||||
viper.SetDefault("path.root", rootDir)
|
|
||||||
err := viper.BindPFlag(
|
|
||||||
"path.root", cmd.PersistentFlags().Lookup("root"),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = viper.BindEnv("path.root", "EVM_ROOT")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
viper.SetDefault("path.shims", filepath.Join("$EVM_ROOT", "shims"))
|
|
||||||
viper.SetDefault("path.sources", filepath.Join("$EVM_ROOT", "sources"))
|
|
||||||
viper.SetDefault("path.versions", filepath.Join("$EVM_ROOT", "versions"))
|
|
||||||
|
|
||||||
infoCmd, err := configCommand()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
listCmd, err := listCommand()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
useCmd, err := useCommand()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
execCmd, err := execCommand()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.AddCommand(
|
|
||||||
infoCmd,
|
|
||||||
listCmd,
|
|
||||||
useCmd,
|
|
||||||
execCmd,
|
|
||||||
)
|
|
||||||
|
|
||||||
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
|
||||||
viper.SetEnvPrefix("evm")
|
|
||||||
viper.AutomaticEnv()
|
|
||||||
|
|
||||||
return cmd, nil
|
|
||||||
}
|
|
||||||
118
command_use.go
118
command_use.go
@@ -1,118 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func useCommand() (*cobra.Command, error) {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "use <version>",
|
|
||||||
Short: "Activate specified version.",
|
|
||||||
Aliases: []string{"activate", "switch"},
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
ValidArgsFunction: useValidArgs,
|
|
||||||
RunE: useRunE,
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func useRunE(_ *cobra.Command, args []string) error {
|
|
||||||
conf, err := getConfig()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
version, err := newEmacsVersion(conf, args[0])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var shim bytes.Buffer
|
|
||||||
err = useShimTemplate.Execute(&shim, conf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = os.MkdirAll(conf.Path.Shims, 0o755)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, bin := range version.Binaries {
|
|
||||||
shimFile := filepath.Join(conf.Path.Shims, bin)
|
|
||||||
err = os.WriteFile(shimFile, shim.Bytes(), 0o755)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var f fs.FileInfo
|
|
||||||
f, err = os.Stat(shimFile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.Mode().Perm() != 0o755 {
|
|
||||||
err = os.Chmod(shimFile, 0o755)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentFile := filepath.Join(conf.Path.Root, currentFileName)
|
|
||||||
err = os.WriteFile(currentFile, []byte(version.Version), 0o644)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func useValidArgs(
|
|
||||||
_ *cobra.Command,
|
|
||||||
args []string,
|
|
||||||
toComplete string,
|
|
||||||
) ([]string, cobra.ShellCompDirective) {
|
|
||||||
var r []string
|
|
||||||
|
|
||||||
if len(args) > 0 {
|
|
||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
||||||
}
|
|
||||||
|
|
||||||
conf, err := getConfig()
|
|
||||||
if err != nil {
|
|
||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
||||||
}
|
|
||||||
|
|
||||||
versions, err := newEmacsVersions(conf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ver := range versions {
|
|
||||||
if toComplete == "" ||
|
|
||||||
strings.HasPrefix(ver.Version, toComplete) {
|
|
||||||
r = append(r, ver.Version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r, cobra.ShellCompDirectiveNoFileComp
|
|
||||||
}
|
|
||||||
|
|
||||||
var useShimTemplate = template.Must(template.New("other").Parse(
|
|
||||||
`#!/usr/bin/env bash
|
|
||||||
set -e
|
|
||||||
[ -n "$EVM_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
program="${0##*/}"
|
|
||||||
export EVM_ROOT="{{.Path.Root}}"
|
|
||||||
exec "{{.Path.Binary}}" exec "$program" "$@"
|
|
||||||
`))
|
|
||||||
39
commands/commands.go
Normal file
39
commands/commands.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import "github.com/spf13/cobra"
|
||||||
|
|
||||||
|
type runEFunc func(cmd *cobra.Command, _ []string) error
|
||||||
|
|
||||||
|
type validArgsFunc func(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
args []string,
|
||||||
|
toComplete string,
|
||||||
|
) ([]string, cobra.ShellCompDirective)
|
||||||
|
|
||||||
|
func noValidArgs(
|
||||||
|
_ *cobra.Command,
|
||||||
|
_ []string,
|
||||||
|
_ string,
|
||||||
|
) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
func flagString(cmd *cobra.Command, name string) string {
|
||||||
|
var r string
|
||||||
|
|
||||||
|
if f := cmd.Flag(name); f != nil {
|
||||||
|
r = f.Value.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringsContains(haystack []string, needle string) bool {
|
||||||
|
for _, s := range haystack {
|
||||||
|
if s == needle {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
28
commands/config.go
Normal file
28
commands/config.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jimeh/evm/manager"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewConfig(mgr *manager.Manager) (*cobra.Command, error) {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "config",
|
||||||
|
Short: "Show evm environment/setup details",
|
||||||
|
Aliases: []string{"env", "info"},
|
||||||
|
ValidArgs: []string{},
|
||||||
|
RunE: configRunE(mgr),
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flags().StringP("format", "f", "", "output format (yaml or json)")
|
||||||
|
|
||||||
|
return cmd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func configRunE(mgr *manager.Manager) runEFunc {
|
||||||
|
return func(cmd *cobra.Command, _ []string) error {
|
||||||
|
format := flagString(cmd, "format")
|
||||||
|
|
||||||
|
return render(cmd.OutOrStdout(), format, mgr.Config)
|
||||||
|
}
|
||||||
|
}
|
||||||
48
commands/evm.go
Normal file
48
commands/evm.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jimeh/evm/manager"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewEvm(mgr *manager.Manager) (*cobra.Command, error) {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "evm",
|
||||||
|
Short: "A simple and opinionated Emacs Version Manager and build tool",
|
||||||
|
}
|
||||||
|
|
||||||
|
configCmd, err := NewConfig(mgr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
listCmd, err := NewList(mgr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
useCmd, err := NewUse(mgr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rehashCmd, err := NewRehash(mgr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
execCmd, err := NewExec(mgr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.AddCommand(
|
||||||
|
configCmd,
|
||||||
|
listCmd,
|
||||||
|
useCmd,
|
||||||
|
rehashCmd,
|
||||||
|
execCmd,
|
||||||
|
)
|
||||||
|
|
||||||
|
return cmd, nil
|
||||||
|
}
|
||||||
131
commands/exec.go
Normal file
131
commands/exec.go
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"html/template"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jimeh/evm/manager"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewExec(mgr *manager.Manager) (*cobra.Command, error) {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "exec <binary> [args]...",
|
||||||
|
Short: "Execute named binary from current " +
|
||||||
|
"Emacs version",
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
SilenceUsage: true,
|
||||||
|
DisableFlagParsing: true,
|
||||||
|
DisableFlagsInUseLine: true,
|
||||||
|
Hidden: true,
|
||||||
|
ValidArgsFunction: execValidArgs(mgr),
|
||||||
|
RunE: execRunE(mgr),
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func execRunE(mgr *manager.Manager) runEFunc {
|
||||||
|
return func(cmd *cobra.Command, args []string) error {
|
||||||
|
ctx := cmd.Context()
|
||||||
|
|
||||||
|
program := args[0]
|
||||||
|
args = args[1:]
|
||||||
|
|
||||||
|
err := mgr.Exec(ctx, program, args)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, manager.ErrBinNotFound) {
|
||||||
|
var versions []*manager.Version
|
||||||
|
versions, err = mgr.FindBin(ctx, program)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return newExecOtherVersionsError(&execOtherVersionsData{
|
||||||
|
Name: program,
|
||||||
|
Current: mgr.CurrentVersion(),
|
||||||
|
AvailableIn: versions,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.Is(err, manager.ErrNoCurrentVersion) {
|
||||||
|
return newExecNoCurrentVersionError()
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func execValidArgs(mgr *manager.Manager) validArgsFunc {
|
||||||
|
return func(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
args []string,
|
||||||
|
toComplete string,
|
||||||
|
) ([]string, cobra.ShellCompDirective) {
|
||||||
|
var r []string
|
||||||
|
|
||||||
|
if len(args) > 0 {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
version, err := mgr.Get(cmd.Context(), mgr.CurrentVersion())
|
||||||
|
if err != nil {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, bin := range version.Binaries {
|
||||||
|
base := filepath.Base(bin)
|
||||||
|
if toComplete == "" || strings.HasPrefix(base, toComplete) {
|
||||||
|
r = append(r, base)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newExecNoCurrentVersionError() error {
|
||||||
|
return errors.New(`No current Emacs version is set.
|
||||||
|
|
||||||
|
List all installed versions with: evm list
|
||||||
|
Change version with: evm use <version>`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type execOtherVersionsData struct {
|
||||||
|
Name string
|
||||||
|
Current string
|
||||||
|
AvailableIn []*manager.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
func newExecOtherVersionsError(data *execOtherVersionsData) error {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err := execOtherVersionsTemplate.Execute(&buf, data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New(buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
var execOtherVersionsTemplate = template.Must(template.New("other").Parse(
|
||||||
|
`{{ if gt (len .AvailableIn) 0 -}}
|
||||||
|
Executable "{{.Name}}" is not available in the current Emacs version ({{.Current}}).
|
||||||
|
|
||||||
|
"{{.Name}}" is available in the following Emacs versions:
|
||||||
|
{{- range .AvailableIn }}
|
||||||
|
- {{ .Version }}
|
||||||
|
{{- end -}}
|
||||||
|
{{ else -}}
|
||||||
|
Executable "{{.Name}}" is not available in any installed Emacs version.
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
Change version with: evm use <version>
|
||||||
|
List all installed versions with: evm list`,
|
||||||
|
))
|
||||||
72
commands/list.go
Normal file
72
commands/list.go
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/jimeh/evm/manager"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewList(mgr *manager.Manager) (*cobra.Command, error) {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "list",
|
||||||
|
Short: "List all Emacs versions found in " +
|
||||||
|
"`$EVM_ROOT/versions/*'",
|
||||||
|
Aliases: []string{"ls", "versions"},
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
ValidArgsFunction: noValidArgs,
|
||||||
|
RunE: listRunE(mgr),
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flags().StringP("format", "f", "", "output format (yaml or json)")
|
||||||
|
|
||||||
|
return cmd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func listRunE(mgr *manager.Manager) runEFunc {
|
||||||
|
return func(cmd *cobra.Command, _ []string) error {
|
||||||
|
format := flagString(cmd, "format")
|
||||||
|
|
||||||
|
versions, err := mgr.List(cmd.Context())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
output := &listOutput{
|
||||||
|
Current: mgr.CurrentVersion(),
|
||||||
|
SetBy: mgr.CurrentSetBy(),
|
||||||
|
Versions: versions,
|
||||||
|
}
|
||||||
|
|
||||||
|
return render(cmd.OutOrStdout(), format, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type listOutput struct {
|
||||||
|
Current string `yaml:"current" json:"current"`
|
||||||
|
SetBy string `yaml:"current_set_by,omitempty" json:"current_set_by,omitempty"`
|
||||||
|
Versions []*manager.Version `yaml:"versions" json:"versions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lr *listOutput) WriteTo(w io.Writer) (int64, error) {
|
||||||
|
var b []byte
|
||||||
|
|
||||||
|
for _, ver := range lr.Versions {
|
||||||
|
if lr.Current == ver.Version {
|
||||||
|
b = append(b, []byte("* ")...)
|
||||||
|
} else {
|
||||||
|
b = append(b, []byte(" ")...)
|
||||||
|
}
|
||||||
|
|
||||||
|
b = append(b, []byte(ver.Version)...)
|
||||||
|
if lr.Current == ver.Version && lr.SetBy != "" {
|
||||||
|
b = append(b, []byte(" (set by "+lr.SetBy+")")...)
|
||||||
|
}
|
||||||
|
|
||||||
|
b = append(b, byte('\n'))
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := w.Write(b)
|
||||||
|
|
||||||
|
return int64(n), err
|
||||||
|
}
|
||||||
58
commands/rehash.go
Normal file
58
commands/rehash.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jimeh/evm/manager"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewRehash(mgr *manager.Manager) (*cobra.Command, error) {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "rehash [<version>...]",
|
||||||
|
Short: "Update shims for all or specific versions",
|
||||||
|
Aliases: []string{"reshim"},
|
||||||
|
ValidArgsFunction: rehashValidArgs(mgr),
|
||||||
|
RunE: rehashRunE(mgr),
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func rehashRunE(mgr *manager.Manager) runEFunc {
|
||||||
|
return func(cmd *cobra.Command, args []string) error {
|
||||||
|
ctx := cmd.Context()
|
||||||
|
|
||||||
|
if len(args) > 0 {
|
||||||
|
return mgr.RehashVersions(ctx, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mgr.RehashAll(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rehashValidArgs(mgr *manager.Manager) validArgsFunc {
|
||||||
|
return func(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
args []string,
|
||||||
|
toComplete string,
|
||||||
|
) ([]string, cobra.ShellCompDirective) {
|
||||||
|
versions, err := mgr.List(cmd.Context())
|
||||||
|
if err != nil {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
var r []string
|
||||||
|
for _, ver := range versions {
|
||||||
|
if stringsContains(args, ver.Version) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if toComplete == "" || strings.HasPrefix(ver.Version, toComplete) {
|
||||||
|
r = append(r, ver.Version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding"
|
"encoding"
|
||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func render(w io.Writer, format string, v interface{}) error {
|
func render(w io.Writer, format string, v interface{}) error {
|
||||||
if format == "yaml" {
|
if format == "yaml" || format == "yml" {
|
||||||
return renderYAML(w, v)
|
return renderYAML(w, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
53
commands/use.go
Normal file
53
commands/use.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jimeh/evm/manager"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewUse(mgr *manager.Manager) (*cobra.Command, error) {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "use <version>",
|
||||||
|
Short: "Switch to a specific version",
|
||||||
|
Aliases: []string{"activate", "switch"},
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
ValidArgsFunction: useValidArgs(mgr),
|
||||||
|
RunE: useRunE(mgr),
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func useRunE(mgr *manager.Manager) runEFunc {
|
||||||
|
return func(cmd *cobra.Command, args []string) error {
|
||||||
|
return mgr.Use(cmd.Context(), args[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func useValidArgs(mgr *manager.Manager) validArgsFunc {
|
||||||
|
return func(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
args []string,
|
||||||
|
toComplete string,
|
||||||
|
) ([]string, cobra.ShellCompDirective) {
|
||||||
|
if len(args) > 0 {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
versions, err := mgr.List(cmd.Context())
|
||||||
|
if err != nil {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
var r []string
|
||||||
|
for _, ver := range versions {
|
||||||
|
if toComplete == "" || strings.HasPrefix(ver.Version, toComplete) {
|
||||||
|
r = append(r, ver.Version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
}
|
||||||
152
config.go
152
config.go
@@ -1,152 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
|
||||||
|
|
||||||
const currentFileName = "current"
|
|
||||||
|
|
||||||
var (
|
|
||||||
configUnmashaled bool
|
|
||||||
cachedConfig = &config{}
|
|
||||||
)
|
|
||||||
|
|
||||||
type config struct {
|
|
||||||
Mode string `yaml:"mode" json:"mode"`
|
|
||||||
Current currentConfig `yaml:"current" json:"current"`
|
|
||||||
Path pathsConfig `yaml:"path" json:"path"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type currentConfig struct {
|
|
||||||
Version string `yaml:"version" json:"version"`
|
|
||||||
SetBy string `yaml:"set_by" json:"set_by"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type pathsConfig struct {
|
|
||||||
Binary string `yaml:"binary" json:"binary"`
|
|
||||||
Root string `yaml:"root" json:"root"`
|
|
||||||
Shims string `yaml:"shims" json:"shims"`
|
|
||||||
Sources string `yaml:"sources" json:"sources"`
|
|
||||||
Versions string `yaml:"versions" json:"versions"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func getConfig() (*config, error) {
|
|
||||||
if configUnmashaled {
|
|
||||||
cc, err := getCurrentVersion(cachedConfig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cachedConfig.Current = *cc
|
|
||||||
|
|
||||||
return cachedConfig, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
conf := &config{}
|
|
||||||
err := viper.Unmarshal(conf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if conf.Mode != "user" && conf.Mode != "system" {
|
|
||||||
return nil, errors.New(`When set EVM_MODE must be "user" or "system"`)
|
|
||||||
}
|
|
||||||
|
|
||||||
conf.Path.Binary, err = os.Executable()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var homePrefix string
|
|
||||||
switch {
|
|
||||||
case strings.HasPrefix(conf.Path.Root, "$HOME") ||
|
|
||||||
strings.HasPrefix(conf.Path.Root, "$home"):
|
|
||||||
homePrefix = conf.Path.Root[0:5]
|
|
||||||
case strings.HasPrefix(conf.Path.Root, "~"):
|
|
||||||
homePrefix = conf.Path.Root[0:1]
|
|
||||||
}
|
|
||||||
|
|
||||||
if homePrefix != "" {
|
|
||||||
var home string
|
|
||||||
home, err = os.UserHomeDir()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
conf.Path.Root = filepath.Join(
|
|
||||||
home, strings.TrimPrefix(conf.Path.Root, homePrefix))
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasPrefix(conf.Path.Shims, "$EVM_ROOT") {
|
|
||||||
conf.Path.Shims = filepath.Join(
|
|
||||||
conf.Path.Root, conf.Path.Shims[9:],
|
|
||||||
)
|
|
||||||
} else if !path.IsAbs(conf.Path.Shims) {
|
|
||||||
conf.Path.Shims = filepath.Join(
|
|
||||||
conf.Path.Root, conf.Path.Shims,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasPrefix(conf.Path.Sources, "$EVM_ROOT") {
|
|
||||||
conf.Path.Sources = filepath.Join(
|
|
||||||
conf.Path.Root, conf.Path.Sources[9:],
|
|
||||||
)
|
|
||||||
} else if !path.IsAbs(conf.Path.Sources) {
|
|
||||||
conf.Path.Sources = filepath.Join(
|
|
||||||
conf.Path.Root, conf.Path.Sources,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasPrefix(conf.Path.Versions, "$EVM_ROOT") {
|
|
||||||
conf.Path.Versions = filepath.Join(
|
|
||||||
conf.Path.Root, conf.Path.Versions[9:],
|
|
||||||
)
|
|
||||||
} else if !path.IsAbs(conf.Path.Versions) {
|
|
||||||
conf.Path.Versions = filepath.Join(
|
|
||||||
conf.Path.Root, conf.Path.Versions,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
cc, err := getCurrentVersion(conf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
conf.Current = *cc
|
|
||||||
cachedConfig = conf
|
|
||||||
|
|
||||||
return cachedConfig, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCurrentVersion(conf *config) (*currentConfig, error) {
|
|
||||||
cc := ¤tConfig{}
|
|
||||||
|
|
||||||
if v := os.Getenv("EVM_VERSION"); v != "" {
|
|
||||||
cc.Version = strings.TrimSpace(v)
|
|
||||||
cc.SetBy = "EVM_VERSION environment variable"
|
|
||||||
|
|
||||||
return cc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
currentFile := filepath.Join(conf.Path.Root, currentFileName)
|
|
||||||
b, err := os.ReadFile(currentFile)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
|
||||||
return cc, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(b) > 0 {
|
|
||||||
cc.Version = strings.TrimSpace(string(b))
|
|
||||||
cc.SetBy = currentFile
|
|
||||||
}
|
|
||||||
|
|
||||||
return cc, nil
|
|
||||||
}
|
|
||||||
15
go.mod
15
go.mod
@@ -3,25 +3,12 @@ module github.com/jimeh/evm
|
|||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/sethvargo/go-envconfig v0.5.0
|
||||||
github.com/spf13/cobra v1.3.0
|
github.com/spf13/cobra v1.3.0
|
||||||
github.com/spf13/viper v1.10.1
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
github.com/magiconair/properties v1.8.6 // indirect
|
|
||||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
|
||||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
|
||||||
github.com/spf13/afero v1.8.1 // indirect
|
|
||||||
github.com/spf13/cast v1.4.1 // indirect
|
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/subosito/gotenv v1.2.0 // indirect
|
|
||||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 // indirect
|
|
||||||
golang.org/x/text v0.3.7 // indirect
|
|
||||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
|||||||
45
go.sum
45
go.sum
@@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
|||||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
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.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.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.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
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.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||||
@@ -16,7 +15,6 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY
|
|||||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
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.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.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
|
||||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||||
@@ -47,7 +45,6 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
|||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
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.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.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=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/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/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
@@ -92,7 +89,6 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
|||||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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/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.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.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
@@ -108,7 +104,6 @@ github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E
|
|||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
|
||||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
@@ -167,6 +162,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.3/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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
@@ -182,7 +178,6 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
|
|||||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/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-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-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
|
||||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
@@ -194,10 +189,8 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
|
|||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||||
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
||||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
|
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
|
||||||
github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
|
|
||||||
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
|
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
|
||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||||
@@ -219,7 +212,6 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
|
|||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
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/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
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/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||||
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
|
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
|
||||||
@@ -253,8 +245,6 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
|
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
|
||||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
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.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
@@ -275,7 +265,6 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
|
|||||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
|
|
||||||
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
@@ -285,14 +274,10 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
|
|||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
|
|
||||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
|
||||||
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||||
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||||
@@ -313,26 +298,21 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
|||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
|
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
|
||||||
github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM=
|
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
|
github.com/sethvargo/go-envconfig v0.5.0 h1:puRfYHj1HUe03MSPVBW8zc2BtRyn/KySgZcICXOzpVg=
|
||||||
|
github.com/sethvargo/go-envconfig v0.5.0/go.mod h1:00S1FAhRUuTNJazWBWcJGvEHOM+NO6DhoRMAOX7FY5o=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
|
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
|
||||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||||
github.com/spf13/afero v1.8.1 h1:izYHOT71f9iZ7iq37Uqjael60/vYC6vMtzedudZ0zEk=
|
|
||||||
github.com/spf13/afero v1.8.1/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
|
|
||||||
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
|
|
||||||
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0=
|
github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0=
|
||||||
github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
|
github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
|
||||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
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 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
|
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
|
||||||
github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk=
|
|
||||||
github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
@@ -340,9 +320,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
|||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
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.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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
@@ -373,9 +351,7 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
|
|||||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/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-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-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/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-20190306152737-a1d7652674e8/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-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@@ -446,7 +422,6 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/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-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/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-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-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||||
@@ -526,7 +501,6 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/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-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -534,7 +508,6 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@@ -549,9 +522,6 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 h1:BXxu8t6QN0G1uff4bzZzSkpsax8+ALqTGUtz08QrV00=
|
|
||||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/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-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -561,7 +531,6 @@ 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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
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-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@@ -614,7 +583,6 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f
|
|||||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/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-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/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.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
@@ -657,7 +625,6 @@ google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdr
|
|||||||
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
|
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
|
||||||
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
|
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
|
||||||
google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
|
google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
|
||||||
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
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.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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
@@ -700,9 +667,7 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D
|
|||||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/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-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-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-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
@@ -757,7 +722,6 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
|
|||||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
@@ -779,15 +743,12 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR
|
|||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
|
|
||||||
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/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.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-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||||
|
|||||||
18
main.go
18
main.go
@@ -6,13 +6,20 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/jimeh/evm/commands"
|
||||||
|
"github.com/jimeh/evm/manager"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd, err := rootCommand()
|
mgr, err := manager.New(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
|
fatal(err)
|
||||||
os.Exit(1)
|
}
|
||||||
|
|
||||||
|
cmd, err := commands.NewEvm(mgr)
|
||||||
|
if err != nil {
|
||||||
|
fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := signal.NotifyContext(
|
ctx, cancel := signal.NotifyContext(
|
||||||
@@ -26,3 +33,8 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fatal(err error) {
|
||||||
|
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|||||||
276
manager/config.go
Normal file
276
manager/config.go
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
package manager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sethvargo/go-envconfig"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrConfig = fmt.Errorf("%w", Err)
|
||||||
|
|
||||||
|
type Mode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
User Mode = "user"
|
||||||
|
System Mode = "system"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConfigFile struct {
|
||||||
|
Paths ConfigFilePaths `yaml:"paths" json:"paths"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConfigFilePaths struct {
|
||||||
|
Shims string `yaml:"shims" json:"shims" env:"EVM_SHIMS,overwrite"`
|
||||||
|
Sources string `yaml:"sources" json:"sources" env:"EVM_SOURCES,overwrite"`
|
||||||
|
Versions string `yaml:"versions" json:"versions" env:"EVM_VERSIONS,overwrite"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Mode Mode `yaml:"mode" json:"mode"`
|
||||||
|
Current CurrentConfig `yaml:"current" json:"current"`
|
||||||
|
Paths PathsConfig `yaml:"paths" json:"paths"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CurrentConfig struct {
|
||||||
|
Version string `yaml:"version" json:"version"`
|
||||||
|
SetBy string `yaml:"set_by,omitempty" json:"set_by,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathsConfig struct {
|
||||||
|
Binary string `yaml:"binary" json:"binary"`
|
||||||
|
Root string `yaml:"root" json:"root"`
|
||||||
|
Shims string `yaml:"shims" json:"shims"`
|
||||||
|
Sources string `yaml:"sources" json:"sources"`
|
||||||
|
Versions string `yaml:"versions" json:"versions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfig() (*Config, error) {
|
||||||
|
mode := Mode(os.Getenv("EVM_MODE"))
|
||||||
|
if mode != System {
|
||||||
|
mode = User
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultRoot := filepath.Join(string(os.PathSeparator), "opt", "evm")
|
||||||
|
if mode == User {
|
||||||
|
defaultRoot = filepath.Join("$HOME", ".evm")
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := os.Getenv("EVM_ROOT"); v != "" {
|
||||||
|
defaultRoot = v
|
||||||
|
}
|
||||||
|
|
||||||
|
conf := &Config{
|
||||||
|
Mode: mode,
|
||||||
|
Paths: PathsConfig{
|
||||||
|
Root: defaultRoot,
|
||||||
|
Shims: "$EVM_ROOT/shims",
|
||||||
|
Sources: "$EVM_ROOT/sources",
|
||||||
|
Versions: "$EVM_ROOT/versions",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
conf.Paths.Root, err = conf.normalizePath(conf.Paths.Root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = conf.load()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
conf.Paths.Shims, err = conf.normalizePath(conf.Paths.Shims)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conf.Paths.Sources, err = conf.normalizePath(conf.Paths.Sources)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conf.Paths.Versions, err = conf.normalizePath(conf.Paths.Versions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
conf.Paths.Binary, err = os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = conf.PopulateCurrent()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentFileName = "current"
|
||||||
|
|
||||||
|
func (conf *Config) PopulateCurrent() error {
|
||||||
|
if v := os.Getenv("EVM_VERSION"); v != "" {
|
||||||
|
conf.Current.Version = strings.TrimSpace(v)
|
||||||
|
conf.Current.SetBy = "EVM_VERSION environment variable"
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
currentFile := filepath.Join(conf.Paths.Root, currentFileName)
|
||||||
|
b, err := os.ReadFile(currentFile)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b) > 0 {
|
||||||
|
conf.Current.Version = strings.TrimSpace(string(b))
|
||||||
|
conf.Current.SetBy = currentFile
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var configFileNames = []string{
|
||||||
|
"config.yaml",
|
||||||
|
"config.yml",
|
||||||
|
"config.json",
|
||||||
|
"evm.yaml",
|
||||||
|
"evm.yml",
|
||||||
|
"evm.json",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) load() error {
|
||||||
|
var path string
|
||||||
|
for _, name := range configFileNames {
|
||||||
|
f := filepath.Join(c.Paths.Root, name)
|
||||||
|
|
||||||
|
_, err := os.Stat(f)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
path = f
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
cf := &ConfigFile{}
|
||||||
|
if path != "" {
|
||||||
|
var err error
|
||||||
|
cf, err = c.loadConfigFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := envconfig.Process(context.Background(), cf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if cf.Paths.Shims != "" {
|
||||||
|
c.Paths.Shims = cf.Paths.Shims
|
||||||
|
}
|
||||||
|
if cf.Paths.Sources != "" {
|
||||||
|
c.Paths.Sources = cf.Paths.Sources
|
||||||
|
}
|
||||||
|
if cf.Paths.Versions != "" {
|
||||||
|
c.Paths.Versions = cf.Paths.Versions
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) loadConfigFile(path string) (*ConfigFile, error) {
|
||||||
|
if path == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cf := &ConfigFile{}
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer(content)
|
||||||
|
switch filepath.Ext(path) {
|
||||||
|
case ".yaml", ".yml":
|
||||||
|
dec := yaml.NewDecoder(buf)
|
||||||
|
dec.KnownFields(true)
|
||||||
|
err = dec.Decode(cf)
|
||||||
|
case ".json":
|
||||||
|
dec := json.NewDecoder(buf)
|
||||||
|
dec.DisallowUnknownFields()
|
||||||
|
err = dec.Decode(cf)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
`%w"%s" does not have a ".yaml", ".yml", `+
|
||||||
|
`or ".json" file extension`,
|
||||||
|
ErrConfig, path,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if err != nil && !errors.Is(err, io.EOF) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) normalizePath(path string) (string, error) {
|
||||||
|
path = strings.TrimSpace(path)
|
||||||
|
|
||||||
|
var homePrefix string
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(path, "$HOME") ||
|
||||||
|
strings.HasPrefix(path, "$home"):
|
||||||
|
homePrefix = path[0:5]
|
||||||
|
case strings.HasPrefix(path, "~"):
|
||||||
|
homePrefix = path[0:1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if homePrefix != "" {
|
||||||
|
if c.Mode == System {
|
||||||
|
return "", fmt.Errorf(
|
||||||
|
`%wEVM_MODE is set to "%s" which prohibits `+
|
||||||
|
`using "$HOME" or "~" in EVM_ROOT`,
|
||||||
|
ErrConfig, string(System),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var home string
|
||||||
|
home, err := os.UserHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
path = filepath.Join(
|
||||||
|
home, strings.TrimPrefix(path, homePrefix))
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Paths.Root == "" {
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(path, "$EVM_ROOT") {
|
||||||
|
path = filepath.Join(c.Paths.Root, path[9:])
|
||||||
|
} else if !filepath.IsAbs(path) {
|
||||||
|
path = filepath.Join(c.Paths.Root, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
286
manager/manager.go
Normal file
286
manager/manager.go
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
package manager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Err = errors.New("")
|
||||||
|
ErrVersion = fmt.Errorf("%w", Err)
|
||||||
|
ErrNoCurrentVersion = fmt.Errorf("%w", ErrVersion)
|
||||||
|
ErrVersionNotFound = fmt.Errorf("%w", ErrVersion)
|
||||||
|
ErrBinNotFound = fmt.Errorf("%w", ErrVersion)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Manager struct {
|
||||||
|
Config *Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(config *Config) (*Manager, error) {
|
||||||
|
if config == nil {
|
||||||
|
var err error
|
||||||
|
config, err = NewConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Manager{Config: config}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) CurrentVersion() string {
|
||||||
|
return m.Config.Current.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) CurrentSetBy() string {
|
||||||
|
return m.Config.Current.SetBy
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) List(ctx context.Context) ([]*Version, error) {
|
||||||
|
return newVersions(ctx, m.Config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Get(ctx context.Context, version string) (*Version, error) {
|
||||||
|
return newVersion(ctx, m.Config, version)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Use(ctx context.Context, version string) error {
|
||||||
|
ver, err := m.Get(ctx, version)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
currentFile := filepath.Join(m.Config.Paths.Root, currentFileName)
|
||||||
|
err = os.WriteFile(currentFile, []byte(ver.Version), 0o644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.rehashVersions(ctx, false, []*Version{ver})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) RehashAll(ctx context.Context) error {
|
||||||
|
versions, err := m.List(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.rehashVersions(ctx, true, versions)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) RehashVersions(
|
||||||
|
ctx context.Context,
|
||||||
|
versions []string,
|
||||||
|
) error {
|
||||||
|
var vers []*Version
|
||||||
|
for _, s := range versions {
|
||||||
|
v, err := m.Get(ctx, s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
vers = append(vers, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.rehashVersions(ctx, false, vers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) rehashVersions(
|
||||||
|
ctx context.Context,
|
||||||
|
tidy bool,
|
||||||
|
versions []*Version,
|
||||||
|
) error {
|
||||||
|
|
||||||
|
programs := map[string]bool{}
|
||||||
|
for _, ver := range versions {
|
||||||
|
for _, bin := range ver.Binaries {
|
||||||
|
base := filepath.Base(bin)
|
||||||
|
programs[base] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shims, err := m.ListShims(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
shimMap := map[string]bool{}
|
||||||
|
for _, s := range shims {
|
||||||
|
base := filepath.Base(s)
|
||||||
|
shimMap[base] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
shim, err := m.shim()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.MkdirAll(m.Config.Paths.Shims, 0o755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for name := range programs {
|
||||||
|
shimFile := filepath.Join(m.Config.Paths.Shims, name)
|
||||||
|
err = os.WriteFile(shimFile, shim, 0o755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var f fs.FileInfo
|
||||||
|
f, err = os.Stat(shimFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.Mode().Perm() != 0o755 {
|
||||||
|
err = os.Chmod(shimFile, 0o755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(shimMap, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tidy {
|
||||||
|
for name := range shimMap {
|
||||||
|
shimFile := filepath.Join(m.Config.Paths.Shims, name)
|
||||||
|
err := os.Remove(shimFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var shimTemplate = template.Must(template.New("other").Parse(
|
||||||
|
`#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
[ -n "$EVM_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
program="${0##*/}"
|
||||||
|
export EVM_ROOT="{{.Paths.Root}}"
|
||||||
|
exec "{{.Paths.Binary}}" exec "$program" "$@"
|
||||||
|
`))
|
||||||
|
|
||||||
|
func (m *Manager) shim() ([]byte, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err := shimTemplate.Execute(&buf, m.Config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) ListShims(ctx context.Context) ([]string, error) {
|
||||||
|
entries, err := os.ReadDir(m.Config.Paths.Shims)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := []string{}
|
||||||
|
|
||||||
|
for _, entry := range entries {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return nil, ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
shimPath := filepath.Join(m.Config.Paths.Shims, entry.Name())
|
||||||
|
f, err := os.Stat(shimPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.Mode().IsRegular() {
|
||||||
|
r = append(r, shimPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Exec(
|
||||||
|
ctx context.Context,
|
||||||
|
program string,
|
||||||
|
args []string,
|
||||||
|
) error {
|
||||||
|
current := m.CurrentVersion()
|
||||||
|
if current == "" {
|
||||||
|
return ErrNoCurrentVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.ExecVersion(ctx, current, program, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) ExecVersion(
|
||||||
|
ctx context.Context,
|
||||||
|
version string,
|
||||||
|
program string,
|
||||||
|
args []string,
|
||||||
|
) error {
|
||||||
|
ver, err := m.Get(ctx, version)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
bin, err := ver.FindBin(program)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
execArgs := append([]string{bin}, args...)
|
||||||
|
execEnv := os.Environ()
|
||||||
|
|
||||||
|
// Prepend selected version's bin directory to PATH.
|
||||||
|
for i := 0; i < len(execEnv); i++ {
|
||||||
|
if strings.HasPrefix(execEnv[i], "PATH=") {
|
||||||
|
execEnv[i] = "PATH=" + ver.BinDir + ":" + execEnv[i][5:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return syscall.Exec(bin, execArgs, execEnv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) FindBin(
|
||||||
|
ctx context.Context,
|
||||||
|
name string,
|
||||||
|
) ([]*Version, error) {
|
||||||
|
versions, err := m.List(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var availableIn []*Version
|
||||||
|
for _, ver := range versions {
|
||||||
|
if _, err := ver.FindBin(name); err == nil {
|
||||||
|
availableIn = append(availableIn, ver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return availableIn, nil
|
||||||
|
}
|
||||||
114
manager/version.go
Normal file
114
manager/version.go
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
package manager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Version struct {
|
||||||
|
Version string `yaml:"version" json:"version"`
|
||||||
|
Current bool `yaml:"current" json:"current"`
|
||||||
|
Path string `yaml:"path" json:"path"`
|
||||||
|
BinDir string `yaml:"bin_dir" json:"bin_dir"`
|
||||||
|
Binaries []string `yaml:"binaries" json:"binaries"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ver *Version) FindBin(name string) (string, error) {
|
||||||
|
for _, b := range ver.Binaries {
|
||||||
|
if filepath.Base(b) == name {
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf(
|
||||||
|
`%wExecutable "%s" not found in Emacs version %s`,
|
||||||
|
ErrBinNotFound, name, ver.Version,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newVersion(
|
||||||
|
ctx context.Context,
|
||||||
|
conf *Config,
|
||||||
|
version string,
|
||||||
|
) (*Version, error) {
|
||||||
|
if version == "" {
|
||||||
|
return nil, fmt.Errorf("%wversion cannot be empty", ErrVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
path := filepath.Join(conf.Paths.Versions, version)
|
||||||
|
|
||||||
|
_, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"%wVersion %s is not available in %s",
|
||||||
|
ErrVersionNotFound, version, conf.Paths.Versions,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ver := &Version{
|
||||||
|
Version: version,
|
||||||
|
Path: path,
|
||||||
|
BinDir: filepath.Join(path, "bin"),
|
||||||
|
Current: version == conf.Current.Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
entries, err := os.ReadDir(ver.BinDir)
|
||||||
|
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range entries {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return nil, ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
binPath := filepath.Join(ver.BinDir, entry.Name())
|
||||||
|
|
||||||
|
f, err := os.Stat(binPath)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure f is Regular file and executable.
|
||||||
|
if f.Mode().IsRegular() && f.Mode().Perm()&0111 == 0111 {
|
||||||
|
ver.Binaries = append(ver.Binaries, binPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ver, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newVersions(ctx context.Context, conf *Config) ([]*Version, error) {
|
||||||
|
results := []*Version{}
|
||||||
|
|
||||||
|
entries, err := os.ReadDir(conf.Paths.Versions)
|
||||||
|
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range entries {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return nil, ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !entry.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ver, err := newVersion(ctx, conf, entry.Name())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
results = append(results, ver)
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
101
versions.go
101
versions.go
@@ -1,101 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
type emacsVersions []*emacsVersion
|
|
||||||
|
|
||||||
func newEmacsVersions(conf *config) (emacsVersions, error) {
|
|
||||||
results := emacsVersions{}
|
|
||||||
|
|
||||||
entries, err := os.ReadDir(conf.Path.Versions)
|
|
||||||
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, entry := range entries {
|
|
||||||
if !entry.IsDir() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
vi, err := newEmacsVersion(conf, entry.Name())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
results = append(results, vi)
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type emacsVersion struct {
|
|
||||||
Version string `yaml:"version" json:"version"`
|
|
||||||
Current bool `yaml:"current" json:"current"`
|
|
||||||
Path string `yaml:"path" json:"path"`
|
|
||||||
Bin string `yaml:"bin" json:"bin"`
|
|
||||||
Binaries []string `yaml:"binaries" json:"binaries"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ev *emacsVersion) BinPath(name string) (string, bool) {
|
|
||||||
for _, b := range ev.Binaries {
|
|
||||||
if filepath.Base(b) == name {
|
|
||||||
return filepath.Join(ev.Bin, b), true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
|
|
||||||
func newEmacsVersion(conf *config, version string) (*emacsVersion, error) {
|
|
||||||
path := filepath.Join(conf.Path.Versions, version)
|
|
||||||
|
|
||||||
_, err := os.Stat(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf(
|
|
||||||
"Version %s is not available in %s",
|
|
||||||
version, conf.Path.Versions,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
ev := &emacsVersion{
|
|
||||||
Version: version,
|
|
||||||
Path: path,
|
|
||||||
Bin: filepath.Join(path, "bin"),
|
|
||||||
Current: version == conf.Current.Version,
|
|
||||||
}
|
|
||||||
|
|
||||||
entries, err := os.ReadDir(ev.Bin)
|
|
||||||
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, entry := range entries {
|
|
||||||
binPath := filepath.Join(ev.Bin, entry.Name())
|
|
||||||
|
|
||||||
f, err := os.Stat(binPath)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
relPath, err := filepath.Rel(ev.Bin, binPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regular and executable file.
|
|
||||||
if f.Mode().IsRegular() && f.Mode().Perm()&0111 == 0111 {
|
|
||||||
ev.Binaries = append(ev.Binaries, relPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ev, nil
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user