From f3f7d661f702a15979b5b97e6e1dbf13b7adc307 Mon Sep 17 00:00:00 2001 From: Michael Rykov Date: Thu, 7 Oct 2021 13:32:26 +0800 Subject: [PATCH] =?UTF-8?q?Added=20=E2=80=9Cgit:config=E2=80=9D=20commands?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/client.go | 1 + api/git_config.go | 43 +++++++++++++ cli/git.go | 1 + cli/git_config.go | 130 ++++++++++++++++++++++++++++++++++++++ cli/git_config_test.go | 140 +++++++++++++++++++++++++++++++++++++++++ go.mod | 10 +-- go.sum | 27 +++++--- 7 files changed, 337 insertions(+), 15 deletions(-) create mode 100644 api/git_config.go create mode 100644 cli/git_config.go create mode 100644 cli/git_config_test.go diff --git a/api/client.go b/api/client.go index e534c42..cadac6f 100644 --- a/api/client.go +++ b/api/client.go @@ -97,6 +97,7 @@ func (c *Client) prepareJSONBody(req *request, data interface{}) error { return err } + req.ContentLength = int64(len(body)) req.Header.Set("Content-Type", "application/json") req.Body = ioutil.NopCloser(bytes.NewReader(body)) return nil diff --git a/api/git_config.go b/api/git_config.go new file mode 100644 index 0000000..5ad83d0 --- /dev/null +++ b/api/git_config.go @@ -0,0 +1,43 @@ +package api + +import ( + "context" + "net/url" +) + +// Packages returns the details of the package listing +func (c *Client) GitConfig(cc context.Context, repo string) ([]GitConfigPair, error) { + path := "/git/repos/{acct}/" + url.PathEscape(repo) + "/config-vars" + req := c.newRequest(cc, "GET", path, false) + + resp := gitConfigJSON{} + if err := req.doJSON(&resp); err != nil { + return nil, err + } + + out := make([]GitConfigPair, 0, len(resp.ConfigVars)) + for k, v := range resp.ConfigVars { + out = append(out, GitConfigPair{k, v}) + } + + return out, nil +} + +// Git Config request/response +type gitConfigJSON struct { + ConfigVars map[string]string `json:"config_vars"` +} + +// Repo represents Git Config KV pair +type GitConfigPair struct { + Key string + Value string +} + +// GitConfigSet updates Git Config with passed-in map of new variables +func (c *Client) GitConfigSet(cc context.Context, repo string, vars map[string]string) error { + path := "/git/repos/{acct}/" + url.PathEscape(repo) + "/config-vars" + req := c.newRequest(cc, "PATCH", path, false) + c.prepareJSONBody(req, &gitConfigJSON{vars}) + return req.doJSON(nil) +} diff --git a/cli/git.go b/cli/git.go index 3b1b368..b0db690 100644 --- a/cli/git.go +++ b/cli/git.go @@ -15,6 +15,7 @@ func NewCmdGitRoot() *cobra.Command { Short: "Git repository commands", } + gitCmd.AddCommand(NewCmdGitConfig()) gitCmd.AddCommand(NewCmdGitRebuild()) gitCmd.AddCommand(NewCmdGitRename()) gitCmd.AddCommand(NewCmdGitReset()) diff --git a/cli/git_config.go b/cli/git_config.go new file mode 100644 index 0000000..eb1dc47 --- /dev/null +++ b/cli/git_config.go @@ -0,0 +1,130 @@ +package cli + +import ( + "github.com/gemfury/cli/api" + "github.com/gemfury/cli/internal/ctx" + "github.com/spf13/cobra" + "sort" + "strings" + "text/tabwriter" + + "fmt" +) + +// NewCmdGitConfig is the root for Git Config +func NewCmdGitConfig() *cobra.Command { + gitConfigCmd := &cobra.Command{ + Use: "config", + Short: "Configure Git build", + RunE: func(cmd *cobra.Command, args []string) error { + return filteredGitConfig(cmd, args, false) + }, + } + + gitConfigCmd.AddCommand(NewCmdGitConfigSet()) + gitConfigCmd.AddCommand(NewCmdGitConfigGet()) + + return gitConfigCmd +} + +// NewCmdGitConfigGet updates one or more configuration keys +func NewCmdGitConfigGet() *cobra.Command { + gitConfigGetCmd := &cobra.Command{ + Use: "get KEY", + Short: "Get Git build environment key", + RunE: func(cmd *cobra.Command, args []string) error { + return filteredGitConfig(cmd, args, true) + }, + } + + return gitConfigGetCmd +} + +// Filtered/unfiltered retrieval of Git Config for commands above +func filteredGitConfig(cmd *cobra.Command, args []string, filter bool) error { + if filter && len(args) < 2 { + return fmt.Errorf("Please specify a repository and a key") + } else if !filter && len(args) != 1 { + return fmt.Errorf("Command requires only a repository") + } + + cc := cmd.Context() + term := ctx.Terminal(cc) + c, err := newAPIClient(cc) + if err != nil { + return err + } + + config, err := c.GitConfig(cc, args[0]) + if err != nil { + return err + } + + filteredConfig := config + if keys := args[1:]; filter && len(keys) > 0 { + filteredConfig = make([]api.GitConfigPair, 0, len(keys)) + for _, c := range config { + for _, k := range keys { + if c.Key == k { + filteredConfig = append(filteredConfig, c) + break + } + } + } + } + + if len(filteredConfig) > 0 { + sort.Slice(filteredConfig, func(i, j int) bool { + return filteredConfig[i].Key < filteredConfig[j].Key + }) + } + + term.Printf("\n*** GIT CONFIG ***\n\n") + w := tabwriter.NewWriter(term.IOOut(), 0, 0, 2, ' ', 0) + + for _, c := range filteredConfig { + fmt.Fprintf(w, "%s:\t%s\n", c.Key, c.Value) + } + + w.Flush() + return nil +} + +// NewCmdGitConfigSet updates one or more configuration keys +func NewCmdGitConfigSet() *cobra.Command { + gitConfigSetCmd := &cobra.Command{ + Use: "set KEY=VAL", + Short: "Set Git build environment key", + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) < 2 { + return fmt.Errorf("Please specify a repository and a KEY=VALUE") + } + + cc := cmd.Context() + term := ctx.Terminal(cc) + c, err := newAPIClient(cc) + if err != nil { + return err + } + + vars := map[string]string{} + for _, pairStr := range args[1:] { + pair := strings.SplitN(pairStr, "=", 2) + if len(pair) != 2 { + return fmt.Errorf("Argument has no value: %s", pairStr) + } + vars[pair[0]] = pair[1] + } + + err = c.GitConfigSet(cc, args[0], vars) + if err != nil { + return err + } + + term.Printf("Updated %s repository config\n", args[0]) + return nil + }, + } + + return gitConfigSetCmd +} diff --git a/cli/git_config_test.go b/cli/git_config_test.go new file mode 100644 index 0000000..888c2d4 --- /dev/null +++ b/cli/git_config_test.go @@ -0,0 +1,140 @@ +package cli_test + +import ( + "github.com/gemfury/cli/cli" + "github.com/gemfury/cli/internal/ctx" + "github.com/gemfury/cli/internal/testutil" + "github.com/gemfury/cli/pkg/terminal" + "strings" + "testing" +) + +const ( + gitConfigResponse = `{ "config_vars": { + "KEY1": "VALUE1", + "KEY2": "VALUE2" + }} +` +) + +// ==== GIT CONFIG ==== + +func TestGitConfigCommandSuccess(t *testing.T) { + auth := terminal.TestAuther("user", "abc123", nil) + term := terminal.NewForTest() + + // Fire up test server + path := "/git/repos/me/repo-name/config-vars" + server := testutil.APIServer(t, "GET", path, gitConfigResponse, 200) + defer server.Close() + + cc := cli.TestContext(term, auth) + flags := ctx.GlobalFlags(cc) + flags.Endpoint = server.URL + + err := runCommandNoErr(cc, []string{"git", "config", "repo-name"}) + if err != nil { + t.Fatal(err) + } + + exp := "KEY1: VALUE1 KEY2: VALUE2" + if outStr := compactString(term.OutBytes()); !strings.HasSuffix(outStr, exp) { + t.Errorf("Expected output to include %q, got %q", exp, outStr) + } +} + +func TestGitConfigCommandUnauthorized(t *testing.T) { + path := "/git/repos/me/repo-name/config-vars" + server := testutil.APIServer(t, "GET", path, "{}", 200) + testCommandLoginPreCheck(t, []string{"git", "config", "repo-name"}, server) + server.Close() +} + +func TestGitConfigCommandForbidden(t *testing.T) { + path := "/git/repos/me/repo-name/config-vars" + server := testutil.APIServer(t, "GET", path, "", 403) + testCommandForbiddenResponse(t, []string{"git", "config", "repo-name"}, server) + server.Close() +} + +// ==== GIT CONFIG GET ==== + +func TestGitConfigGetCommandSuccess(t *testing.T) { + auth := terminal.TestAuther("user", "abc123", nil) + term := terminal.NewForTest() + + // Fire up test server + path := "/git/repos/me/repo-name/config-vars" + server := testutil.APIServer(t, "GET", path, gitConfigResponse, 200) + defer server.Close() + + cc := cli.TestContext(term, auth) + flags := ctx.GlobalFlags(cc) + flags.Endpoint = server.URL + + err := runCommandNoErr(cc, []string{"git", "config", "get", "repo-name", "KEY2"}) + if err != nil { + t.Fatal(err) + } + + exp := "KEY2: VALUE2" + if outStr := compactString(term.OutBytes()); !strings.HasSuffix(outStr, exp) { + t.Errorf("Expected output to include %q, got %q", exp, outStr) + } else if strings.Contains(outStr, "KEY1") { + t.Errorf("Expected output to be filtered, got %q", outStr) + } +} + +func TestGitConfigGetCommandUnauthorized(t *testing.T) { + path := "/git/repos/me/repo-name/config-vars" + server := testutil.APIServer(t, "GET", path, "{}", 200) + testCommandLoginPreCheck(t, []string{"git", "config", "get", "repo-name", "KEY2"}, server) + server.Close() +} + +func TestGitConfigGetCommandForbidden(t *testing.T) { + path := "/git/repos/me/repo-name/config-vars" + server := testutil.APIServer(t, "GET", path, "", 403) + testCommandForbiddenResponse(t, []string{"git", "config", "get", "repo-name", "KEY2"}, server) + server.Close() +} + +// ==== GIT CONFIG SET ==== + +func TestGitConfigSetCommandSuccess(t *testing.T) { + auth := terminal.TestAuther("user", "abc123", nil) + term := terminal.NewForTest() + + // Fire up test server + path := "/git/repos/me/repo-name/config-vars" + server := testutil.APIServer(t, "PATCH", path, gitConfigResponse, 200) + defer server.Close() + + cc := cli.TestContext(term, auth) + flags := ctx.GlobalFlags(cc) + flags.Endpoint = server.URL + + err := runCommandNoErr(cc, []string{"git", "config", "set", "repo-name", "KEY2=VALUE2"}) + if err != nil { + t.Fatal(err) + } + + exp := "Updated repo-name repository config" + if outStr := compactString(term.OutBytes()); outStr != exp { + t.Errorf("Expected output to include %q, got %q", exp, outStr) + } +} + +func TestGitConfigSetCommandUnauthorized(t *testing.T) { + path := "/git/repos/me/repo-name/config-vars" + server := testutil.APIServer(t, "PATCH", path, "{}", 200) + testCommandLoginPreCheck(t, []string{"git", "config", "set", "repo-name", "KEY2=VALUE2"}, server) + server.Close() +} + +func TestGitConfigSetCommandForbidden(t *testing.T) { + path := "/git/repos/me/repo-name/config-vars" + server := testutil.APIServer(t, "PATCH", path, "", 403) + testCommandForbiddenResponse(t, []string{"git", "config", "set", "repo-name", "KEY2=VALUE2"}, server) + server.Close() +} diff --git a/go.mod b/go.mod index 8122e05..53bbe6c 100644 --- a/go.mod +++ b/go.mod @@ -17,14 +17,14 @@ require ( require ( github.com/VividCortex/ewma v1.2.0 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect - github.com/fatih/color v1.12.0 // indirect + github.com/fatih/color v1.13.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/juju/ansiterm v0.0.0-20210706145210-9283cdf370b5 // indirect + github.com/juju/ansiterm v0.0.0-20210929141451-8b71cc96ebdc // indirect github.com/lunixbochs/vtclean v1.0.0 // indirect - github.com/mattn/go-colorable v0.1.8 // indirect - github.com/mattn/go-isatty v0.0.13 // indirect + github.com/mattn/go-colorable v0.1.11 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect github.com/rivo/uniseg v0.2.0 // indirect - golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect + golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect ) diff --git a/go.sum b/go.sum index ce15a01..0e97fcd 100644 --- a/go.sum +++ b/go.sum @@ -79,8 +79,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 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= @@ -184,13 +184,14 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= -github.com/juju/ansiterm v0.0.0-20210706145210-9283cdf370b5 h1:Q5klzs6BL5FkassBX65t+KkG0XjYcjxEm+GNcQAsuaw= -github.com/juju/ansiterm v0.0.0-20210706145210-9283cdf370b5/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= +github.com/juju/ansiterm v0.0.0-20210929141451-8b71cc96ebdc h1:ZQrgZFsLzkw7o3CoDzsfBhx0bf/1rVBXrLy8dXKRe8o= +github.com/juju/ansiterm v0.0.0-20210929141451-8b71cc96ebdc/go.mod h1:PyXUpnI3olx3bsPcHt98FGPX/KCFZ1Fi+hw1XLI6384= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 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= @@ -202,14 +203,17 @@ github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9ky github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.10/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= -github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -425,8 +429,10 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/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-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -596,8 +602,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=