From b9c522b89b83cdda0d83047b6297483637589dc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krisztia=CC=81n=20Go=CC=88drei?= Date: Thu, 23 Sep 2021 09:22:39 +0200 Subject: [PATCH 1/5] Migrate to the new ruby package. --- go.mod | 4 +- go.sum | 10 + main.go | 151 +++++----- .../go-steputils/command/gems/bundler.go | 48 ---- .../go-steputils/command/ruby/command.go | 140 +++++++++ .../rubycommand.go => ruby/environment.go} | 255 +++++------------ .../go-steputils/stepconf/errors.go | 26 ++ .../go-steputils/stepconf/secret.go | 15 + .../go-steputils/stepconf/stepconf.go | 170 ++--------- .../go-steputils/stepconf/stepinput.go | 24 ++ .../go-steputils/stepconf/strings.go | 49 ++++ .../bitrise-io/go-steputils/tools/tools.go | 10 +- .../bitrise-io/go-utils/command/command.go | 270 +++++------------- .../bitrise-io/go-utils/command/file.go | 5 +- .../github.com/bitrise-io/go-utils/env/env.go | 58 ++++ .../bitrise-io/go-utils/fileutil/fileutil.go | 46 +++ .../bitrise-io/go-utils/log/defaultlogger.go | 57 ---- .../bitrise-io/go-utils/log/dummylogger.go | 30 -- .../bitrise-io/go-utils/log/json_logger.go | 33 --- .../github.com/bitrise-io/go-utils/log/log.go | 236 ++++++++++++++- .../bitrise-io/go-utils/log/logger.go | 12 - .../bitrise-io/go-utils/log/print.go | 115 -------- .../bitrise-io/go-utils/log/raw_logger.go | 33 --- .../bitrise-io/go-utils/log/severity.go | 26 +- .../bitrise-io/go-utils/pathutil/glob.go | 13 - .../go-utils/pathutil/path_filter.go | 21 ++ .../bitrise-io/go-utils/pathutil/pathutil.go | 219 +++++++------- .../go-utils/pathutil/sortable_path.go | 31 ++ .../hashicorp/go-retryablehttp/.travis.yml | 12 - .../hashicorp/go-retryablehttp/README.md | 1 + .../hashicorp/go-retryablehttp/client.go | 157 +++++++--- .../go-retryablehttp/roundtripper.go | 11 +- vendor/modules.txt | 9 +- 33 files changed, 1166 insertions(+), 1131 deletions(-) delete mode 100644 vendor/github.com/bitrise-io/go-steputils/command/gems/bundler.go create mode 100644 vendor/github.com/bitrise-io/go-steputils/command/ruby/command.go rename vendor/github.com/bitrise-io/go-steputils/command/{rubycommand/rubycommand.go => ruby/environment.go} (50%) create mode 100644 vendor/github.com/bitrise-io/go-steputils/stepconf/errors.go create mode 100644 vendor/github.com/bitrise-io/go-steputils/stepconf/secret.go create mode 100644 vendor/github.com/bitrise-io/go-steputils/stepconf/stepinput.go create mode 100644 vendor/github.com/bitrise-io/go-steputils/stepconf/strings.go create mode 100644 vendor/github.com/bitrise-io/go-utils/env/env.go delete mode 100644 vendor/github.com/bitrise-io/go-utils/log/defaultlogger.go delete mode 100644 vendor/github.com/bitrise-io/go-utils/log/dummylogger.go delete mode 100644 vendor/github.com/bitrise-io/go-utils/log/json_logger.go delete mode 100644 vendor/github.com/bitrise-io/go-utils/log/logger.go delete mode 100644 vendor/github.com/bitrise-io/go-utils/log/print.go delete mode 100644 vendor/github.com/bitrise-io/go-utils/log/raw_logger.go delete mode 100644 vendor/github.com/bitrise-io/go-utils/pathutil/glob.go delete mode 100644 vendor/github.com/hashicorp/go-retryablehttp/.travis.yml diff --git a/go.mod b/go.mod index 0f79f5d..e97374c 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,8 @@ go 1.12 require ( github.com/bitrise-io/bitrise-init v0.0.0-20210520122036-d213de321eb8 github.com/bitrise-io/go-android v0.0.0-20210527143215-3ad22ad02e2e - github.com/bitrise-io/go-steputils v0.0.0-20210527075147-910ce7a105a1 - github.com/bitrise-io/go-utils v0.0.0-20210520073355-367fa34178f5 + github.com/bitrise-io/go-steputils v0.0.0-20210923053150-ddc3f70aacd2 + github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72 github.com/bitrise-io/go-xcode v0.0.0-20210521101355-fb6a1eb6e05b github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 ) diff --git a/go.sum b/go.sum index fb12d7c..c687cd3 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,10 @@ github.com/bitrise-io/go-steputils v0.0.0-20210507072936-92fde382fb33/go.mod h1: github.com/bitrise-io/go-steputils v0.0.0-20210514150206-5b6261447e77/go.mod h1:H0iZjgsAR5NA6pnlD/zKB6AbxEsskq55pwJ9klVmP8w= github.com/bitrise-io/go-steputils v0.0.0-20210527075147-910ce7a105a1 h1:gi29hTdxGXAGQvZckPZ9V8BAEfP3eK/tiZgTC5s6h1c= github.com/bitrise-io/go-steputils v0.0.0-20210527075147-910ce7a105a1/go.mod h1:H0iZjgsAR5NA6pnlD/zKB6AbxEsskq55pwJ9klVmP8w= +github.com/bitrise-io/go-steputils v0.0.0-20210922204217-d5e2f9ce0e4a h1:BVq3lyp7xY1h1zWGYdmB8pi6VLKIqw8kEqAHuLTdHDA= +github.com/bitrise-io/go-steputils v0.0.0-20210922204217-d5e2f9ce0e4a/go.mod h1:e3iET6YTYpobuCbA5iyvy1pxHUb+qfCDOpeMel0bI6Q= +github.com/bitrise-io/go-steputils v0.0.0-20210923053150-ddc3f70aacd2 h1:aKbxnR3yQpdUVDv80qsJKiFzIUSvCiCXDkff58qnQRc= +github.com/bitrise-io/go-steputils v0.0.0-20210923053150-ddc3f70aacd2/go.mod h1:e3iET6YTYpobuCbA5iyvy1pxHUb+qfCDOpeMel0bI6Q= github.com/bitrise-io/go-utils v0.0.0-20210505091801-98b7dc39ee61/go.mod h1:nhdaDQFvaMny1CugVV6KjK92/q97ENo0RuKSW5I4fbA= github.com/bitrise-io/go-utils v0.0.0-20210505121718-07411d72e36e/go.mod h1:nhdaDQFvaMny1CugVV6KjK92/q97ENo0RuKSW5I4fbA= github.com/bitrise-io/go-utils v0.0.0-20210506064210-b22e2b7b3ad3/go.mod h1:nhdaDQFvaMny1CugVV6KjK92/q97ENo0RuKSW5I4fbA= @@ -23,6 +27,8 @@ github.com/bitrise-io/go-utils v0.0.0-20210507100250-37de47dfa6ce/go.mod h1:15EZ github.com/bitrise-io/go-utils v0.0.0-20210514083430-4d1fb0330dfe/go.mod h1:DRx7oFuAqk0dbKpAKCqWl0TgrowfJUb/MqYPRscxJOQ= github.com/bitrise-io/go-utils v0.0.0-20210520073355-367fa34178f5 h1:kclxBfygfNK6kWUB+9xcsfPLBen8Us9gubhitfL/Z6c= github.com/bitrise-io/go-utils v0.0.0-20210520073355-367fa34178f5/go.mod h1:DRx7oFuAqk0dbKpAKCqWl0TgrowfJUb/MqYPRscxJOQ= +github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72 h1:Eov/ocBE9sfljzLo7C/6GuLUtACWJpY6dRLDhTtJ2L8= +github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72/go.mod h1:Vi4MHnaZVL3PVoPPA/Yp6g2pzntkDH8LGiRSY7qw6KQ= github.com/bitrise-io/go-xcode v0.0.0-20210520114025-bdbec53ee59f/go.mod h1:a5IANtAnyazHgNjI6/kwQw5vU/WJo1zQ4Lja9WRUNmA= github.com/bitrise-io/go-xcode v0.0.0-20210521101355-fb6a1eb6e05b h1:JyTlzvdOBOxtYZ7aZVCog2dZUv8LgA8UftT+TpVWtZY= github.com/bitrise-io/go-xcode v0.0.0-20210521101355-fb6a1eb6e05b/go.mod h1:6Nv5RAsAVS745xN5IihUExVmCA9n9f7s/DSVow4hXrI= @@ -47,6 +53,8 @@ github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxC github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4= +github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw= github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -85,6 +93,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -95,6 +104,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/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-20210615035016-665e8c7367d1/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-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/main.go b/main.go index df7632b..5aec724 100644 --- a/main.go +++ b/main.go @@ -13,9 +13,10 @@ import ( "github.com/bitrise-io/go-steputils/cache" "github.com/bitrise-io/go-steputils/command/gems" - "github.com/bitrise-io/go-steputils/command/rubycommand" + "github.com/bitrise-io/go-steputils/command/ruby" "github.com/bitrise-io/go-steputils/stepconf" "github.com/bitrise-io/go-utils/command" + "github.com/bitrise-io/go-utils/env" "github.com/bitrise-io/go-utils/errorutil" "github.com/bitrise-io/go-utils/fileutil" "github.com/bitrise-io/go-utils/log" @@ -78,20 +79,26 @@ func failf(format string, v ...interface{}) { } func fastlaneDebugInfo(workDir string, useBundler bool, bundlerVersion gems.Version) (string, error) { - envCmd := []string{"fastlane", "env"} - if useBundler { - envCmd = append(gems.BundleExecPrefix(bundlerVersion), envCmd...) - } - - cmd, err := rubycommand.NewFromSlice(envCmd) + factory, err := ruby.NewCommandFactory(command.NewFactory(env.NewRepository()), env.NewCommandLocator()) if err != nil { - return "", fmt.Errorf("failed to create command model, error: %s", err) + return "", err } + name := "fastlane" + args := []string{"env"} var outBuffer bytes.Buffer - cmd.SetStdin(strings.NewReader("n")) - cmd.SetStdout(bufio.NewWriter(&outBuffer)).SetStderr(os.Stderr) - cmd.SetDir(workDir) + opts := &command.Opts{ + Stdin: strings.NewReader("n"), + Stdout: bufio.NewWriter(&outBuffer), + Stderr: os.Stderr, + Dir: workDir, + } + var cmd command.Command + if useBundler { + cmd = factory.CreateBundleExec(name, args, bundlerVersion.Version, opts) + } else { + cmd = factory.Create(name, args, opts) + } log.Debugf("$ %s", cmd.PrintableCommandArgs()) if err := cmd.Run(); err != nil { @@ -131,7 +138,8 @@ func handleSessionDataError(err error) { func main() { var config Config - if err := stepconf.Parse(&config); err != nil { + parser := stepconf.NewInputParser(env.NewRepository()) + if err := parser.Parse(&config); err != nil { failf("Issue with input: %s", err) } @@ -180,10 +188,22 @@ func main() { log.Donef("Expanded WorkDir: %s", workDir) - if rbenvVersionsCommand := gems.RbenvVersionsCommand(); rbenvVersionsCommand != nil { + cmdLocator := env.NewCommandLocator() + factory, err := ruby.NewCommandFactory(command.NewFactory(env.NewRepository()), cmdLocator) + if err != nil { + panic(err) + } + + if _, err := cmdLocator.LookPath("rbenv"); err != nil { + cmd := factory.Create("rbenv", []string{"versions"}, &command.Opts{ + Stderr: os.Stderr, + Stdout: os.Stdout, + Dir: workDir, + }) + fmt.Println() - log.Donef("$ %s", rbenvVersionsCommand.PrintableCommandArgs()) - if err := rbenvVersionsCommand.SetStdout(os.Stdout).SetStderr(os.Stderr).SetDir(workDir).Run(); err != nil { + log.Donef("$ %s", cmd.PrintableCommandArgs()) + if err := cmd.Run(); err != nil { log.Warnf("%s", err) } } @@ -246,50 +266,47 @@ func main() { // install bundler with `gem install bundler [-v version]` // in some configurations, the command "bunder _1.2.3_" can return 'Command not found', installing bundler solves this - installBundlerCommand := gems.InstallBundlerCommand(gemVersions.bundler) - - log.Donef("$ %s", installBundlerCommand.PrintableCommandArgs()) - fmt.Println() - - installBundlerCommand.SetStdout(os.Stdout).SetStderr(os.Stderr) - installBundlerCommand.SetDir(workDir) + cmds := factory.CreateGemInstall("bunder", gemVersions.bundler.Version, false, true, &command.Opts{ + Stdout: os.Stdout, + Stderr: os.Stderr, + Dir: workDir, + }) + for _, cmd := range cmds { + log.Donef("$ %s", cmd.PrintableCommandArgs()) + fmt.Println() - if err := installBundlerCommand.Run(); err != nil { - failf("command failed, error: %s", err) + if err := cmd.Run(); err != nil { + failf("command failed, error: %s", err) + } } // install Gemfile.lock gems with `bundle [_version_] install ...` fmt.Println() log.Infof("Install Fastlane with bundler") - cmd, err := gems.BundleInstallCommand(gemVersions.bundler) - if err != nil { - failf("failed to create bundle command, error: %s", err) - } + cmd := factory.CreateBundleInstall(gemVersions.bundler.Version, &command.Opts{ + Stdout: os.Stdout, + Stderr: os.Stderr, + Dir: workDir, + }) log.Donef("$ %s", cmd.PrintableCommandArgs()) fmt.Println() - cmd.SetStdout(os.Stdout).SetStderr(os.Stderr) - cmd.SetDir(workDir) - if err := cmd.Run(); err != nil { failf("Command failed, error: %s", err) } } else if config.UpdateFastlane { log.Infof("Update system installed Fastlane") - cmds, err := rubycommand.GemInstall("fastlane", "", false) - if err != nil { - failf("Failed to create command model, error: %s", err) - } - + cmds := factory.CreateGemInstall("fastlane", "", false, false, &command.Opts{ + Stdout: os.Stdout, + Stderr: os.Stderr, + Dir: workDir, + }) for _, cmd := range cmds { log.Donef("$ %s", cmd.PrintableCommandArgs()) - cmd.SetStdout(os.Stdout).SetStderr(os.Stderr) - cmd.SetDir(workDir) - if err := cmd.Run(); err != nil { failf("Command failed, error: %s", err) } @@ -301,20 +318,21 @@ func main() { fmt.Println() log.Infof("Fastlane version") - versionCmd := []string{"fastlane", "--version"} - if useBundler { - versionCmd = append(gems.BundleExecPrefix(gemVersions.bundler), versionCmd...) + name := "fastlane" + args := []string{"--version"} + opts := &command.Opts{ + Stdout: os.Stdout, + Stderr: os.Stderr, + Dir: workDir, } - - log.Donef("$ %s", command.PrintableCommandArgs(false, versionCmd)) - - cmd, err := rubycommand.NewFromSlice(versionCmd) - if err != nil { - failf("Command failed, error: %s", err) + var cmd command.Command + if useBundler { + cmd = factory.CreateBundleExec(name, args, gemVersions.bundler.Version, opts) + } else { + cmd = factory.Create(name, args, opts) } - cmd.SetStdout(os.Stdout).SetStderr(os.Stderr) - cmd.SetDir(workDir) + log.Donef("$ %s", cmd.PrintableCommandArgs()) if err := cmd.Run(); err != nil { failf("Command failed, error: %s", err) @@ -342,24 +360,7 @@ func main() { log.Infof("To stop overriding authentication-related environment variables, please set Bitrise Apple Developer Connection input to 'off' and leave authentication-related inputs empty.") } - fastlaneCmd := []string{"fastlane"} - fastlaneCmd = append(fastlaneCmd, laneOptions...) - if useBundler { - fastlaneCmd = append(gems.BundleExecPrefix(gemVersions.bundler), fastlaneCmd...) - } - - log.Donef("$ %s", command.PrintableCommandArgs(false, fastlaneCmd)) - - cmd, err = rubycommand.NewFromSlice(fastlaneCmd) - if err != nil { - failf("Failed to create command model, error: %s", err) - } - - cmd.SetStdout(os.Stdout).SetStderr(os.Stderr) - cmd.SetDir(workDir) - buildlogPth := "" - if tempDir, err := pathutil.NormalizedOSTempDirPath("fastlane_logs"); err != nil { log.Errorf("Failed to create temp dir for fastlane logs, error: %s", err) } else { @@ -367,7 +368,21 @@ func main() { envs = append(envs, "FL_BUILDLOG_PATH="+buildlogPth) } - cmd.AppendEnvs(envs...) + name = "fastlane" + args = laneOptions + opts = &command.Opts{ + Stdout: os.Stdout, + Stderr: os.Stderr, + Dir: workDir, + Env: append(os.Environ(), envs...), + } + if useBundler { + cmd = factory.CreateBundleExec(name, args, gemVersions.bundler.Version, opts) + } else { + cmd = factory.Create(name, args, opts) + } + + log.Donef("$ %s", cmd.PrintableCommandArgs()) deployDir := os.Getenv("BITRISE_DEPLOY_DIR") if deployDir == "" { diff --git a/vendor/github.com/bitrise-io/go-steputils/command/gems/bundler.go b/vendor/github.com/bitrise-io/go-steputils/command/gems/bundler.go deleted file mode 100644 index 0763041..0000000 --- a/vendor/github.com/bitrise-io/go-steputils/command/gems/bundler.go +++ /dev/null @@ -1,48 +0,0 @@ -package gems - -import ( - "fmt" - "os/exec" - - "github.com/bitrise-io/go-steputils/command/rubycommand" - "github.com/bitrise-io/go-utils/command" -) - -// InstallBundlerCommand returns a command to install a specific bundler version -func InstallBundlerCommand(gemfileLockVersion Version) *command.Model { - args := []string{"install", "bundler", "--force", "--no-document"} - if gemfileLockVersion.Found { - args = append(args, []string{"--version", gemfileLockVersion.Version}...) - } - - return command.New("gem", args...) -} - -// BundleInstallCommand returns a command to install a bundle using bundler -func BundleInstallCommand(gemfileLockVersion Version) (*command.Model, error) { - var args []string - if gemfileLockVersion.Found { - args = append(args, "_"+gemfileLockVersion.Version+"_") - } - args = append(args, []string{"install", "--jobs", "20", "--retry", "5"}...) - - return rubycommand.New("bundle", args...) -} - -// BundleExecPrefix returns a slice containing: "bundle [_verson_] exec" -func BundleExecPrefix(bundlerVersion Version) []string { - bundleExec := []string{"bundle"} - if bundlerVersion.Found { - bundleExec = append(bundleExec, fmt.Sprintf("_%s_", bundlerVersion.Version)) - } - return append(bundleExec, "exec") -} - -// RbenvVersionsCommand retruns a command to print used and available ruby versions if rbenv is installed -func RbenvVersionsCommand() *command.Model { - if _, err := exec.LookPath("rbenv"); err != nil { - return nil - } - - return command.New("rbenv", "versions") -} diff --git a/vendor/github.com/bitrise-io/go-steputils/command/ruby/command.go b/vendor/github.com/bitrise-io/go-steputils/command/ruby/command.go new file mode 100644 index 0000000..32953a0 --- /dev/null +++ b/vendor/github.com/bitrise-io/go-steputils/command/ruby/command.go @@ -0,0 +1,140 @@ +package ruby + +import ( + "errors" + "strings" + + "github.com/bitrise-io/go-utils/env" + + "github.com/bitrise-io/go-utils/command" +) + +// CommandFactory ... +type CommandFactory interface { + Create(name string, args []string, opts *command.Opts) command.Command + CreateBundleExec(name string, args []string, bundlerVersion string, opts *command.Opts) command.Command + CreateBundleInstall(bundlerVersion string, opts *command.Opts) command.Command + CreateGemInstall(gem, version string, enablePrerelease, force bool, opts *command.Opts) []command.Command + CreateGemUpdate(gem string, opts *command.Opts) []command.Command +} + +type commandFactory struct { + cmdFactory command.Factory + installType InstallType +} + +// NewCommandFactory ... +func NewCommandFactory(cmdFactory command.Factory, cmdLocator env.CommandLocator) (CommandFactory, error) { + installType := rubyInstallType(cmdLocator) + if installType == Unknown { + return nil, errors.New("unknown Ruby installation") + } + + return commandFactory{ + cmdFactory: cmdFactory, + installType: installType, + }, nil +} + +func (f commandFactory) Create(name string, args []string, opts *command.Opts) command.Command { + s := append([]string{name}, args...) + if sudoNeeded(f.installType, s...) { + return f.cmdFactory.Create("sudo", s, opts) + } + return f.cmdFactory.Create(name, args, opts) +} + +// CreateBundleExec ... +func (f commandFactory) CreateBundleExec(name string, args []string, bundlerVersion string, opts *command.Opts) command.Command { + a := bundleCommandArgs(append([]string{"exec", name}, args...), bundlerVersion) + return f.Create("bundle", a, opts) +} + +// CreateBundleInstall returns a command to install a bundle using bundler +func (f commandFactory) CreateBundleInstall(bundlerVersion string, opts *command.Opts) command.Command { + a := bundleCommandArgs([]string{"install", "--jobs", "20", "--retry", "5"}, bundlerVersion) + return f.Create("bundle", a, opts) +} + +// CreateGemInstall ... +func (f commandFactory) CreateGemInstall(gem, version string, enablePrerelease, force bool, opts *command.Opts) []command.Command { + a := gemInstallCommandArgs(gem, version, enablePrerelease, force) + cmd := f.Create("gem", a, opts) + cmds := []command.Command{cmd} + + if f.installType == RbenvRuby { + cmd := f.Create("rbenv", []string{"rehash"}, nil) + cmds = append(cmds, cmd) + } + + return cmds +} + +// CreateGemUpdate ... +func (f commandFactory) CreateGemUpdate(gem string, opts *command.Opts) []command.Command { + cmd := f.Create("gem", []string{"update", gem, "--no-document"}, opts) + cmds := []command.Command{cmd} + + if f.installType == RbenvRuby { + cmd := f.Create("rbenv", []string{"rehash"}, nil) + cmds = append(cmds, cmd) + } + + return cmds +} + +func bundleCommandArgs(args []string, bundlerVersion string) []string { + var a []string + if bundlerVersion != "" { + a = append(a, "_"+bundlerVersion+"_") + } + return append(a, args...) +} + +func gemInstallCommandArgs(gem, version string, enablePrerelease, force bool) []string { + slice := []string{"install", gem, "--no-document"} + if enablePrerelease { + slice = append(slice, "--prerelease") + } + if version != "" { + slice = append(slice, "-v", version) + } + if force { + slice = append(slice, "--force") + } + + return slice +} + +func sudoNeeded(installType InstallType, slice ...string) bool { + if installType != SystemRuby { + return false + } + + if len(slice) < 2 { + return false + } + + name := slice[0] + if name == "bundle" { + cmd := slice[1] + /* + bundle command can contain version: + `bundle _2.0.1_ install` + */ + const bundleVersionMarker = "_" + if strings.HasPrefix(slice[1], bundleVersionMarker) && strings.HasSuffix(slice[1], bundleVersionMarker) { + if len(slice) < 3 { + return false + } + cmd = slice[2] + } + + return cmd == "install" || cmd == "update" + } else if name == "gem" { + cmd := slice[1] + return cmd == "install" || cmd == "uninstall" + } + + return false +} diff --git a/vendor/github.com/bitrise-io/go-steputils/command/rubycommand/rubycommand.go b/vendor/github.com/bitrise-io/go-steputils/command/ruby/environment.go similarity index 50% rename from vendor/github.com/bitrise-io/go-steputils/command/rubycommand/rubycommand.go rename to vendor/github.com/bitrise-io/go-steputils/command/ruby/environment.go index 4ce6cde..b376372 100644 --- a/vendor/github.com/bitrise-io/go-steputils/command/rubycommand/rubycommand.go +++ b/vendor/github.com/bitrise-io/go-steputils/command/ruby/environment.go @@ -1,14 +1,14 @@ -package rubycommand +package ruby import ( "bufio" "bytes" - "errors" "fmt" "regexp" "strings" "github.com/bitrise-io/go-utils/command" + "github.com/bitrise-io/go-utils/env" "github.com/bitrise-io/go-utils/pathutil" ) @@ -22,8 +22,8 @@ const ( type InstallType int8 const ( - // Unkown ... - Unkown InstallType = iota + // Unknown ... + Unknown InstallType = iota // SystemRuby ... SystemRuby // BrewRuby ... @@ -34,191 +34,85 @@ const ( RbenvRuby ) -func cmdExist(slice ...string) bool { - if len(slice) == 0 { - return false - } - - cmd, err := command.NewWithParams(slice...) - if err != nil { - return false - } - - return (cmd.Run() == nil) +// Environment ... +type Environment interface { + RubyInstallType() InstallType + IsGemInstalled(gem, version string) (bool, error) + IsSpecifiedRbenvRubyInstalled(workdir string) (bool, string, error) } -// RubyInstallType returns which version manager was used for the ruby install -func RubyInstallType() InstallType { - whichRuby, err := command.New("which", "ruby").RunAndReturnTrimmedCombinedOutput() - if err != nil { - return Unkown - } - - installType := Unkown - if whichRuby == systemRubyPth { - installType = SystemRuby - } else if whichRuby == brewRubyPth { - installType = BrewRuby - } else if whichRuby == brewRubyPthAlt { - installType = BrewRuby - } else if cmdExist("rvm", "-v") { - installType = RVMRuby - } else if cmdExist("rbenv", "-v") { - installType = RbenvRuby - } - - return installType +type environment struct { + factory CommandFactory + cmdLocator env.CommandLocator } -func sudoNeeded(installType InstallType, slice ...string) bool { - if installType != SystemRuby { - return false +// NewEnvironment ... +func NewEnvironment(factory CommandFactory, cmdLocator env.CommandLocator) Environment { + return environment{ + factory: factory, + cmdLocator: cmdLocator, } - - if len(slice) < 2 { - return false - } - - name := slice[0] - if name == "bundle" { - command := slice[1] - /* - bundle command can contain version: - `bundle _2.0.1_ install` - */ - const bundleVersionMarker = "_" - if strings.HasPrefix(slice[1], bundleVersionMarker) && strings.HasSuffix(slice[1], bundleVersionMarker) { - if len(slice) < 3 { - return false - } - command = slice[2] - } - - return (command == "install" || command == "update") - } else if name == "gem" { - command := slice[1] - return (command == "install" || command == "uninstall") - } - - return false -} - -// NewWithParams ... -func NewWithParams(params ...string) (*command.Model, error) { - rubyInstallType := RubyInstallType() - if rubyInstallType == Unkown { - return nil, errors.New("unknown ruby installation type") - } - - if sudoNeeded(rubyInstallType, params...) { - params = append([]string{"sudo"}, params...) - } - - return command.NewWithParams(params...) -} - -// NewFromSlice ... -func NewFromSlice(slice []string) (*command.Model, error) { - return NewWithParams(slice...) } -// New ... -func New(name string, args ...string) (*command.Model, error) { - slice := append([]string{name}, args...) - return NewWithParams(slice...) +// RubyInstallType returns which version manager was used for the ruby install +func (m environment) RubyInstallType() InstallType { + return rubyInstallType(m.cmdLocator) } -// GemUpdate ... -func GemUpdate(gem string) ([]*command.Model, error) { - cmds := []*command.Model{} +func (m environment) IsGemInstalled(gem, version string) (bool, error) { + cmd := m.factory.Create("gem", []string{"list"}, nil) - cmd, err := New("gem", "update", gem, "--no-document") + out, err := cmd.RunAndReturnTrimmedCombinedOutput() if err != nil { - return []*command.Model{}, err - } - - cmds = append(cmds, cmd) - - rubyInstallType := RubyInstallType() - if rubyInstallType == RbenvRuby { - cmd, err := New("rbenv", "rehash") - if err != nil { - return []*command.Model{}, err - } - - cmds = append(cmds, cmd) - } - - return cmds, nil -} - -func gemInstallCommand(gem, version string, enablePrerelease bool) []string { - slice := []string{"gem", "install", gem, "--no-document"} - if enablePrerelease { - slice = append(slice, "--prerelease") - } - if version != "" { - slice = append(slice, "-v", version) + return false, fmt.Errorf("%s: error: %s", out, err) } - return slice + return findGemInList(out, gem, version) } -// GemInstall ... -func GemInstall(gem, version string, enablePrerelease bool) ([]*command.Model, error) { - cmd, err := NewFromSlice(gemInstallCommand(gem, version, enablePrerelease)) +// IsSpecifiedRbenvRubyInstalled checks if the selected ruby version is installed via rbenv. +// Ruby version is set by +// 1. The RBENV_VERSION environment variable +// 2. The first .ruby-version file found by searching the directory of the script you are executing and each of its +// parent directories until reaching the root of your filesystem. +// 3.The first .ruby-version file found by searching the current working directory and each of its parent directories +// until reaching the root of your filesystem. +// 4. The global ~/.rbenv/version file. You can modify this file using the rbenv global command. +// src: https://github.com/rbenv/rbenv#choosing-the-ruby-version +func (m environment) IsSpecifiedRbenvRubyInstalled(workdir string) (bool, string, error) { + absWorkdir, err := pathutil.AbsPath(workdir) if err != nil { - return []*command.Model{}, err - } - - cmds := []*command.Model{cmd} - - rubyInstallType := RubyInstallType() - if rubyInstallType == RbenvRuby { - cmd, err := New("rbenv", "rehash") - if err != nil { - return []*command.Model{}, err - } - - cmds = append(cmds, cmd) + return false, "", fmt.Errorf("failed to get absolute path for ( %s ), error: %s", workdir, err) } - return cmds, nil -} - -func findGemInList(gemList, gem, version string) (bool, error) { - // minitest (5.10.1, 5.9.1, 5.9.0, 5.8.3, 4.7.5) - pattern := fmt.Sprintf(`^%s \(.*%s.*\)`, gem, version) - re := regexp.MustCompile(pattern) - - reader := bytes.NewReader([]byte(gemList)) - scanner := bufio.NewScanner(reader) - for scanner.Scan() { - line := scanner.Text() - match := re.FindString(line) - if match != "" { - return true, nil - } - } - if err := scanner.Err(); err != nil { - return false, err + cmd := m.factory.Create("rbenv", []string{"version"}, &command.Opts{Dir: absWorkdir}) + out, err := cmd.RunAndReturnTrimmedCombinedOutput() + if err != nil { + return false, "", fmt.Errorf("failed to check installed ruby version, %s error: %s", out, err) } - return false, nil + return isSpecifiedRbenvRubyInstalled(out) } -// IsGemInstalled ... -func IsGemInstalled(gem, version string) (bool, error) { - cmd, err := New("gem", "list") +func rubyInstallType(cmdLocator env.CommandLocator) InstallType { + pth, err := cmdLocator.LookPath("ruby") if err != nil { - return false, err + return Unknown } - out, err := cmd.RunAndReturnTrimmedCombinedOutput() - if err != nil { - return false, fmt.Errorf("%s: error: %s", out, err) + installType := Unknown + if pth == systemRubyPth { + installType = SystemRuby + } else if pth == brewRubyPth { + installType = BrewRuby + } else if pth == brewRubyPthAlt { + installType = BrewRuby + } else if _, err := cmdLocator.LookPath("rvm"); err == nil { + installType = RVMRuby + } else if _, err := cmdLocator.LookPath("rbenv"); err == nil { + installType = RbenvRuby } - return findGemInList(out, gem, version) + return installType } func isSpecifiedRbenvRubyInstalled(message string) (bool, string, error) { @@ -251,25 +145,22 @@ func isSpecifiedRbenvRubyInstalled(message string) (bool, string, error) { return false, version, nil } -// IsSpecifiedRbenvRubyInstalled checks if the selected ruby version is installed via rbenv. -// Ruby version is set by -// 1. The RBENV_VERSION environment variable -// 2. The first .ruby-version file found by searching the directory of the script you are executing and each of its -// parent directories until reaching the root of your filesystem. -// 3.The first .ruby-version file found by searching the current working directory and each of its parent directories -// until reaching the root of your filesystem. -// 4. The global ~/.rbenv/version file. You can modify this file using the rbenv global command. -// src: https://github.com/rbenv/rbenv#choosing-the-ruby-version -func IsSpecifiedRbenvRubyInstalled(workdir string) (bool, string, error) { - absWorkdir, err := pathutil.AbsPath(workdir) - if err != nil { - return false, "", fmt.Errorf("failed to get absolute path for ( %s ), error: %s", workdir, err) - } +func findGemInList(gemList, gem, version string) (bool, error) { + // minitest (5.10.1, 5.9.1, 5.9.0, 5.8.3, 4.7.5) + pattern := fmt.Sprintf(`^%s \(.*%s.*\)`, gem, version) + re := regexp.MustCompile(pattern) - cmd := command.New("rbenv", "version").SetDir(absWorkdir) - out, err := cmd.RunAndReturnTrimmedCombinedOutput() - if err != nil { - return false, "", fmt.Errorf("failed to check installed ruby version, %s error: %s", out, err) + reader := bytes.NewReader([]byte(gemList)) + scanner := bufio.NewScanner(reader) + for scanner.Scan() { + line := scanner.Text() + match := re.FindString(line) + if match != "" { + return true, nil + } } - return isSpecifiedRbenvRubyInstalled(out) + if err := scanner.Err(); err != nil { + return false, err + } + return false, nil } diff --git a/vendor/github.com/bitrise-io/go-steputils/stepconf/errors.go b/vendor/github.com/bitrise-io/go-steputils/stepconf/errors.go new file mode 100644 index 0000000..52b6d0b --- /dev/null +++ b/vendor/github.com/bitrise-io/go-steputils/stepconf/errors.go @@ -0,0 +1,26 @@ +package stepconf + +import ( + "errors" + "strings" +) + +// ErrNotStructPtr indicates a type is not a pointer to a struct. +var ErrNotStructPtr = errors.New("must be a pointer to a struct") + +// ParseError occurs when a struct field cannot be set. +type ParseError struct { + Field string + Value string + Err error +} + +// Error implements builtin errors.Error. +func (e *ParseError) Error() string { + segments := []string{e.Field} + if e.Value != "" { + segments = append(segments, e.Value) + } + segments = append(segments, e.Err.Error()) + return strings.Join(segments, ": ") +} diff --git a/vendor/github.com/bitrise-io/go-steputils/stepconf/secret.go b/vendor/github.com/bitrise-io/go-steputils/stepconf/secret.go new file mode 100644 index 0000000..f9140ce --- /dev/null +++ b/vendor/github.com/bitrise-io/go-steputils/stepconf/secret.go @@ -0,0 +1,15 @@ +package stepconf + +// Secret variables are not shown in the printed output. +type Secret string + +const secret = "*****" + +// String implements fmt.Stringer.String. +// When a Secret is printed, it's masking the underlying string with asterisks. +func (s Secret) String() string { + if s == "" { + return "" + } + return secret +} diff --git a/vendor/github.com/bitrise-io/go-steputils/stepconf/stepconf.go b/vendor/github.com/bitrise-io/go-steputils/stepconf/stepconf.go index da06ab3..932bf80 100644 --- a/vendor/github.com/bitrise-io/go-steputils/stepconf/stepconf.go +++ b/vendor/github.com/bitrise-io/go-steputils/stepconf/stepconf.go @@ -9,136 +9,22 @@ import ( "strconv" "strings" - "github.com/bitrise-io/go-utils/colorstring" + "github.com/bitrise-io/go-utils/env" "github.com/bitrise-io/go-utils/parseutil" ) -// ErrNotStructPtr indicates a type is not a pointer to a struct. -var ErrNotStructPtr = errors.New("must be a pointer to a struct") - -// ParseError occurs when a struct field cannot be set. -type ParseError struct { - Field string - Value string - Err error -} - -const rangeMinimumGroupName = "min" -const rangeMaximumGroupName = "max" -const rangeMinBracketGroupName = "minbr" -const rangeMaxBracketGroupName = "maxbr" -const rangeRegex = `range(?P<` + rangeMinBracketGroupName + `>\[|\])(?P<` + rangeMinimumGroupName + `>.*?)\.\.(?P<` + rangeMaximumGroupName + `>.*?)(?P<` + rangeMaxBracketGroupName + `>\[|\])` -const multilineConstraintName = "multiline" - -// Error implements builtin errors.Error. -func (e *ParseError) Error() string { - segments := []string{e.Field} - if e.Value != "" { - segments = append(segments, e.Value) - } - segments = append(segments, e.Err.Error()) - return strings.Join(segments, ": ") -} - -// Secret variables are not shown in the printed output. -type Secret string - -const secret = "*****" - -// String implements fmt.Stringer.String. -// When a Secret is printed, it's masking the underlying string with asterisks. -func (s Secret) String() string { - if s == "" { - return "" - } - return secret -} - -// Print the name of the struct with Title case in blue color with followed by a newline, -// then print all fields formatted as '- field name: field value` separated by newline. -func Print(config interface{}) { - fmt.Print(toString(config)) -} - -func valueString(v reflect.Value) string { - if v.Kind() != reflect.Ptr { - return fmt.Sprintf("%v", v.Interface()) - } - - if !v.IsNil() { - return fmt.Sprintf("%v", v.Elem().Interface()) - } - - return "" -} - -// returns the name of the struct with Title case in blue color followed by a newline, -// then print all fields formatted as '- field name: field value` separated by newline. -func toString(config interface{}) string { - v := reflect.ValueOf(config) - t := reflect.TypeOf(config) - - if v.Kind() == reflect.Ptr { - v = v.Elem() - } - - if t.Kind() == reflect.Ptr { - t = t.Elem() - } - - str := fmt.Sprint(colorstring.Bluef("%s:\n", strings.Title(t.Name()))) - for i := 0; i < t.NumField(); i++ { - str += fmt.Sprintf("- %s: %s\n", t.Field(i).Name, valueString(v.Field(i))) - } - - return str -} - -// parseTag splits a struct field's env tag into its name and option. -func parseTag(tag string) (string, string) { - if idx := strings.Index(tag, ","); idx != -1 { - return tag[:idx], tag[idx+1:] - } - return tag, "" -} - -// EnvProvider ... -type EnvProvider interface { - Getenv(key string) string -} - -// OSEnvProvider ... -type OSEnvProvider struct{} - -// NewOSEnvProvider ... -func NewOSEnvProvider() EnvProvider { - return OSEnvProvider{} -} - -// Getenv ... -func (p OSEnvProvider) Getenv(key string) string { - return os.Getenv(key) -} - -// EnvParser ... -type EnvParser struct { - envProvider EnvProvider -} - -// NewDefaultEnvParser ... -func NewDefaultEnvParser() EnvParser { - return NewEnvParser(NewOSEnvProvider()) -} - -// NewEnvParser ... -func NewEnvParser(envProvider EnvProvider) EnvParser { - return EnvParser{ - envProvider: envProvider, - } -} +const ( + rangeMinimumGroupName = "min" + rangeMaximumGroupName = "max" + rangeMinBracketGroupName = "minbr" + rangeMaxBracketGroupName = "maxbr" + rangeRegex = `range(?P<` + rangeMinBracketGroupName + `>\[|\])(?P<` + rangeMinimumGroupName + `>.*?)\.\.(?P<` + rangeMaximumGroupName + `>.*?)(?P<` + rangeMaxBracketGroupName + `>\[|\])` + multilineConstraintName = "multiline" +) -// Parse ... -func (p EnvParser) Parse(conf interface{}) error { +// parse populates a struct with the retrieved values from environment variables +// described by struct tags and applies the defined validations. +func parse(conf interface{}, envRepository env.Repository) error { c := reflect.ValueOf(conf) if c.Kind() != reflect.Ptr { return ErrNotStructPtr @@ -156,7 +42,7 @@ func (p EnvParser) Parse(conf interface{}) error { continue } key, constraint := parseTag(tag) - value := p.envProvider.Getenv(key) + value := envRepository.Get(key) if err := setField(c.Field(i), value, constraint); err != nil { errs = append(errs, &ParseError{t.Field(i).Name, value, err}) @@ -175,20 +61,12 @@ func (p EnvParser) Parse(conf interface{}) error { return nil } -var defaultEnvParser *EnvParser - -func getDefaultEnvParser() EnvParser { - if defaultEnvParser == nil { - parser := NewDefaultEnvParser() - defaultEnvParser = &parser +// parseTag splits a struct field's env tag into its name and option. +func parseTag(tag string) (string, string) { + if idx := strings.Index(tag, ","); idx != -1 { + return tag[:idx], tag[idx+1:] } - return *defaultEnvParser -} - -// Parse populates a struct with the retrieved values from environment variables -// described by struct tags and applies the defined validations. -func Parse(conf interface{}) error { - return getDefaultEnvParser().Parse(conf) + return tag, "" } func setField(field reflect.Value, value, constraint string) error { @@ -261,7 +139,7 @@ func validateConstraint(value, constraint string) error { return fmt.Errorf("value is not in value options (%s)", constraint) } case regexp.MustCompile(rangeRegex).FindString(constraint): - if err := ValidateRangeFields(value, constraint); err != nil { + if err := validateRangeFields(value, constraint); err != nil { return err } case multilineConstraintName: @@ -272,12 +150,12 @@ func validateConstraint(value, constraint string) error { return nil } -//ValidateRangeFields validates if the given range is proper. Ranges are optional, empty values are valid. -func ValidateRangeFields(valueStr, constraint string) error { +// validateRangeFields validates if the given range is proper. Ranges are optional, empty values are valid. +func validateRangeFields(valueStr, constraint string) error { if valueStr == "" { return nil } - constraintMin, constraintMax, constraintMinBr, constraintMaxBr, err := GetRangeValues(constraint) + constraintMin, constraintMax, constraintMinBr, constraintMaxBr, err := getRangeValues(constraint) if err != nil { return err } @@ -497,8 +375,8 @@ func validateRangeMaxFieldValue(max float64, value float64, inclusive bool) erro return nil } -// GetRangeValues reads up the given range constraint and returns the values, or an error if the constraint is malformed or could not be parsed. -func GetRangeValues(value string) (min string, max string, minBracket string, maxBracket string, err error) { +// getRangeValues reads up the given range constraint and returns the values, or an error if the constraint is malformed or could not be parsed. +func getRangeValues(value string) (min string, max string, minBracket string, maxBracket string, err error) { regex := regexp.MustCompile(rangeRegex) groups := regex.FindStringSubmatch(value) if len(groups) < 1 { diff --git a/vendor/github.com/bitrise-io/go-steputils/stepconf/stepinput.go b/vendor/github.com/bitrise-io/go-steputils/stepconf/stepinput.go new file mode 100644 index 0000000..d4b57c1 --- /dev/null +++ b/vendor/github.com/bitrise-io/go-steputils/stepconf/stepinput.go @@ -0,0 +1,24 @@ +package stepconf + +import "github.com/bitrise-io/go-utils/env" + +// InputParser ... +type InputParser interface { + Parse(input interface{}) error +} + +type defaultInputParser struct { + envRepository env.Repository +} + +// NewInputParser ... +func NewInputParser(envRepository env.Repository) InputParser { + return defaultInputParser{ + envRepository: envRepository, + } +} + +// Parse ... +func (p defaultInputParser) Parse(input interface{}) error { + return parse(input, p.envRepository) +} diff --git a/vendor/github.com/bitrise-io/go-steputils/stepconf/strings.go b/vendor/github.com/bitrise-io/go-steputils/stepconf/strings.go new file mode 100644 index 0000000..365e50c --- /dev/null +++ b/vendor/github.com/bitrise-io/go-steputils/stepconf/strings.go @@ -0,0 +1,49 @@ +package stepconf + +import ( + "fmt" + "reflect" + "strings" + + "github.com/bitrise-io/go-utils/colorstring" +) + +// Print the name of the struct with Title case in blue color with followed by a newline, +// then print all fields formatted as '- field name: field value` separated by newline. +func Print(config interface{}) { + fmt.Print(toString(config)) +} + +func valueString(v reflect.Value) string { + if v.Kind() != reflect.Ptr { + return fmt.Sprintf("%v", v.Interface()) + } + + if !v.IsNil() { + return fmt.Sprintf("%v", v.Elem().Interface()) + } + + return "" +} + +// returns the name of the struct with Title case in blue color followed by a newline, +// then print all fields formatted as '- field name: field value` separated by newline. +func toString(config interface{}) string { + v := reflect.ValueOf(config) + t := reflect.TypeOf(config) + + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + + str := fmt.Sprint(colorstring.Bluef("%s:\n", strings.Title(t.Name()))) + for i := 0; i < t.NumField(); i++ { + str += fmt.Sprintf("- %s: %s\n", t.Field(i).Name, valueString(v.Field(i))) + } + + return str +} diff --git a/vendor/github.com/bitrise-io/go-steputils/tools/tools.go b/vendor/github.com/bitrise-io/go-steputils/tools/tools.go index 3372b16..f665afa 100644 --- a/vendor/github.com/bitrise-io/go-steputils/tools/tools.go +++ b/vendor/github.com/bitrise-io/go-steputils/tools/tools.go @@ -1,14 +1,16 @@ package tools import ( - "strings" - "github.com/bitrise-io/go-utils/command" + "github.com/bitrise-io/go-utils/env" + "strings" ) +// TODO remove +var temporaryFactory = command.NewFactory(env.NewRepository()) + // ExportEnvironmentWithEnvman ... func ExportEnvironmentWithEnvman(key, value string) error { - cmd := command.New("envman", "add", "--key", key) - cmd.SetStdin(strings.NewReader(value)) + cmd := temporaryFactory.Create("envman", []string{"add", "--key", key}, &command.Opts{Stdin: strings.NewReader(value)}) return cmd.Run() } diff --git a/vendor/github.com/bitrise-io/go-utils/command/command.go b/vendor/github.com/bitrise-io/go-utils/command/command.go index c068490..0ef8af3 100644 --- a/vendor/github.com/bitrise-io/go-utils/command/command.go +++ b/vendor/github.com/bitrise-io/go-utils/command/command.go @@ -1,129 +1,113 @@ package command import ( - "errors" "io" - "os" "os/exec" "strconv" "strings" -) - -// ---------- -// Model ... -type Model struct { - cmd *exec.Cmd -} + "github.com/bitrise-io/go-utils/env" +) -// New ... -func New(name string, args ...string) *Model { - return &Model{ - cmd: exec.Command(name, args...), - } +// Opts ... +type Opts struct { + Stdout io.Writer + Stderr io.Writer + Stdin io.Reader + Env []string + Dir string } -// NewWithStandardOuts - same as NewCommand, but sets the command's -// stdout and stderr to the standard (OS) out (os.Stdout) and err (os.Stderr) -func NewWithStandardOuts(name string, args ...string) *Model { - return New(name, args...).SetStdout(os.Stdout).SetStderr(os.Stderr) +// Factory ... +type Factory interface { + Create(name string, args []string, opts *Opts) Command } -// NewWithParams ... -func NewWithParams(params ...string) (*Model, error) { - if len(params) == 0 { - return nil, errors.New("no command provided") - } else if len(params) == 1 { - return New(params[0]), nil - } - - return New(params[0], params[1:]...), nil +type defaultFactory struct { + envRepository env.Repository } -// NewFromSlice ... -func NewFromSlice(slice []string) (*Model, error) { - return NewWithParams(slice...) +// NewFactory ... +func NewFactory(envRepository env.Repository) Factory { + return defaultFactory{envRepository: envRepository} } -// NewWithCmd ... -func NewWithCmd(cmd *exec.Cmd) *Model { - return &Model{ - cmd: cmd, +// Create ... +func (f defaultFactory) Create(name string, args []string, opts *Opts) Command { + cmd := exec.Command(name, args...) + if opts != nil { + cmd.Stdout = opts.Stdout + cmd.Stderr = opts.Stderr + cmd.Stdin = opts.Stdin + + // If Env is nil, the new process uses the current process's + // environment. + // If we pass env vars we want to append them to the + // current process's environment. + cmd.Env = append(f.envRepository.List(), opts.Env...) + cmd.Dir = opts.Dir } + return defaultCommand{cmd} } -// GetCmd ... -func (m *Model) GetCmd() *exec.Cmd { - return m.cmd +// Command ... +type Command interface { + PrintableCommandArgs() string + Run() error + RunAndReturnExitCode() (int, error) + RunAndReturnTrimmedOutput() (string, error) + RunAndReturnTrimmedCombinedOutput() (string, error) + Start() error + Wait() error } -// SetDir ... -func (m *Model) SetDir(dir string) *Model { - m.cmd.Dir = dir - return m -} - -// SetEnvs ... -func (m *Model) SetEnvs(envs ...string) *Model { - m.cmd.Env = envs - return m -} - -// AppendEnvs - appends the envs to the current os.Environ() -// Calling this multiple times will NOT appens the envs one by one, -// only the last "envs" set will be appended to os.Environ()! -func (m *Model) AppendEnvs(envs ...string) *Model { - return m.SetEnvs(append(os.Environ(), envs...)...) -} - -// SetStdin ... -func (m *Model) SetStdin(in io.Reader) *Model { - m.cmd.Stdin = in - return m -} - -// SetStdout ... -func (m *Model) SetStdout(out io.Writer) *Model { - m.cmd.Stdout = out - return m +type defaultCommand struct { + cmd *exec.Cmd } -// SetStderr ... -func (m *Model) SetStderr(err io.Writer) *Model { - m.cmd.Stderr = err - return m +// PrintableCommandArgs ... +func (c defaultCommand) PrintableCommandArgs() string { + return printableCommandArgs(false, c.cmd.Args) } // Run ... -func (m Model) Run() error { - return m.cmd.Run() +func (c defaultCommand) Run() error { + return c.cmd.Run() } // RunAndReturnExitCode ... -func (m Model) RunAndReturnExitCode() (int, error) { - return RunCmdAndReturnExitCode(m.cmd) +func (c defaultCommand) RunAndReturnExitCode() (int, error) { + err := c.cmd.Run() + exitCode := c.cmd.ProcessState.ExitCode() + return exitCode, err } // RunAndReturnTrimmedOutput ... -func (m Model) RunAndReturnTrimmedOutput() (string, error) { - return RunCmdAndReturnTrimmedOutput(m.cmd) +func (c defaultCommand) RunAndReturnTrimmedOutput() (string, error) { + outBytes, err := c.cmd.Output() + outStr := string(outBytes) + return strings.TrimSpace(outStr), err } // RunAndReturnTrimmedCombinedOutput ... -func (m Model) RunAndReturnTrimmedCombinedOutput() (string, error) { - return RunCmdAndReturnTrimmedCombinedOutput(m.cmd) +func (c defaultCommand) RunAndReturnTrimmedCombinedOutput() (string, error) { + outBytes, err := c.cmd.CombinedOutput() + outStr := string(outBytes) + return strings.TrimSpace(outStr), err } -// PrintableCommandArgs ... -func (m Model) PrintableCommandArgs() string { - return PrintableCommandArgs(false, m.cmd.Args) +// Start ... +func (c defaultCommand) Start() error { + return c.cmd.Start() } -// ---------- +// Wait ... +func (c defaultCommand) Wait() error { + return c.cmd.Wait() +} -// PrintableCommandArgs ... -func PrintableCommandArgs(isQuoteFirst bool, fullCommandArgs []string) string { - cmdArgsDecorated := []string{} +func printableCommandArgs(isQuoteFirst bool, fullCommandArgs []string) string { + var cmdArgsDecorated []string for idx, anArg := range fullCommandArgs { quotedArg := strconv.Quote(anArg) if idx == 0 && !isQuoteFirst { @@ -134,119 +118,3 @@ func PrintableCommandArgs(isQuoteFirst bool, fullCommandArgs []string) string { return strings.Join(cmdArgsDecorated, " ") } - -// RunCmdAndReturnExitCode ... -func RunCmdAndReturnExitCode(cmd *exec.Cmd) (exitCode int, err error) { - err = cmd.Run() - exitCode = cmd.ProcessState.ExitCode() - return -} - -// RunCmdAndReturnTrimmedOutput ... -func RunCmdAndReturnTrimmedOutput(cmd *exec.Cmd) (string, error) { - outBytes, err := cmd.Output() - outStr := string(outBytes) - return strings.TrimSpace(outStr), err -} - -// RunCmdAndReturnTrimmedCombinedOutput ... -func RunCmdAndReturnTrimmedCombinedOutput(cmd *exec.Cmd) (string, error) { - outBytes, err := cmd.CombinedOutput() - outStr := string(outBytes) - return strings.TrimSpace(outStr), err -} - -// RunCommandWithReaderAndWriters ... -func RunCommandWithReaderAndWriters(inReader io.Reader, outWriter, errWriter io.Writer, name string, args ...string) error { - cmd := exec.Command(name, args...) - cmd.Stdin = inReader - cmd.Stdout = outWriter - cmd.Stderr = errWriter - return cmd.Run() -} - -// RunCommandWithWriters ... -func RunCommandWithWriters(outWriter, errWriter io.Writer, name string, args ...string) error { - cmd := exec.Command(name, args...) - cmd.Stdout = outWriter - cmd.Stderr = errWriter - return cmd.Run() -} - -// RunCommandInDirWithEnvsAndReturnExitCode ... -func RunCommandInDirWithEnvsAndReturnExitCode(envs []string, dir, name string, args ...string) (int, error) { - cmd := exec.Command(name, args...) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if dir != "" { - cmd.Dir = dir - } - if len(envs) > 0 { - cmd.Env = envs - } - - return RunCmdAndReturnExitCode(cmd) -} - -// RunCommandInDirAndReturnExitCode ... -func RunCommandInDirAndReturnExitCode(dir, name string, args ...string) (int, error) { - return RunCommandInDirWithEnvsAndReturnExitCode([]string{}, dir, name, args...) -} - -// RunCommandWithEnvsAndReturnExitCode ... -func RunCommandWithEnvsAndReturnExitCode(envs []string, name string, args ...string) (int, error) { - return RunCommandInDirWithEnvsAndReturnExitCode(envs, "", name, args...) -} - -// RunCommandInDir ... -func RunCommandInDir(dir, name string, args ...string) error { - cmd := exec.Command(name, args...) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if dir != "" { - cmd.Dir = dir - } - return cmd.Run() -} - -// RunCommand ... -func RunCommand(name string, args ...string) error { - return RunCommandInDir("", name, args...) -} - -// RunCommandAndReturnStdout .. -func RunCommandAndReturnStdout(name string, args ...string) (string, error) { - cmd := exec.Command(name, args...) - return RunCmdAndReturnTrimmedOutput(cmd) -} - -// RunCommandInDirAndReturnCombinedStdoutAndStderr ... -func RunCommandInDirAndReturnCombinedStdoutAndStderr(dir, name string, args ...string) (string, error) { - cmd := exec.Command(name, args...) - if dir != "" { - cmd.Dir = dir - } - return RunCmdAndReturnTrimmedCombinedOutput(cmd) -} - -// RunCommandAndReturnCombinedStdoutAndStderr .. -func RunCommandAndReturnCombinedStdoutAndStderr(name string, args ...string) (string, error) { - return RunCommandInDirAndReturnCombinedStdoutAndStderr("", name, args...) -} - -// RunBashCommand ... -func RunBashCommand(cmdStr string) error { - return RunCommand("bash", "-c", cmdStr) -} - -// RunBashCommandLines ... -func RunBashCommandLines(cmdLines []string) error { - for _, aLine := range cmdLines { - if err := RunCommand("bash", "-c", aLine); err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/bitrise-io/go-utils/command/file.go b/vendor/github.com/bitrise-io/go-utils/command/file.go index 6b22172..be29aa1 100644 --- a/vendor/github.com/bitrise-io/go-utils/command/file.go +++ b/vendor/github.com/bitrise-io/go-utils/command/file.go @@ -2,6 +2,7 @@ package command import ( "errors" + "github.com/bitrise-io/go-utils/env" "os" "strings" @@ -20,7 +21,7 @@ func CopyFile(src, dst string) error { return errors.New("Source is a directory: " + src) } args := []string{src, dst} - return RunCommand("rsync", args...) + return NewFactory(env.NewRepository()).Create("rsync", args, &Opts{Stderr: os.Stderr, Stdout: os.Stdout}).Run() } // CopyDir ... @@ -29,7 +30,7 @@ func CopyDir(src, dst string, isOnlyContent bool) error { src = src + "/" } args := []string{"-ar", src, dst} - return RunCommand("rsync", args...) + return NewFactory(env.NewRepository()).Create("rsync", args, &Opts{Stderr: os.Stderr, Stdout: os.Stdout}).Run() } // RemoveDir ... diff --git a/vendor/github.com/bitrise-io/go-utils/env/env.go b/vendor/github.com/bitrise-io/go-utils/env/env.go new file mode 100644 index 0000000..221f27d --- /dev/null +++ b/vendor/github.com/bitrise-io/go-utils/env/env.go @@ -0,0 +1,58 @@ +package env + +import ( + "os" + "os/exec" +) + +// CommandLocator ... +type CommandLocator interface { + LookPath(file string) (string, error) +} + +type commandLocator struct{} + +// NewCommandLocator ... +func NewCommandLocator() CommandLocator { + return commandLocator{} +} + +// LookPath ... +func (l commandLocator) LookPath(file string) (string, error) { + return exec.LookPath(file) +} + +// Repository ... +type Repository interface { + List() []string + Unset(key string) error + Get(key string) string + Set(key, value string) error +} + +// NewRepository ... +func NewRepository() Repository { + return defaultRepository{} +} + +type defaultRepository struct{} + +// Get ... +func (d defaultRepository) Get(key string) string { + return os.Getenv(key) +} + +// Set ... +func (d defaultRepository) Set(key, value string) error { + return os.Setenv(key, value) +} + +// Unset ... +func (d defaultRepository) Unset(key string) error { + return os.Unsetenv(key) +} + +// List ... +func (d defaultRepository) List() []string { + return os.Environ() +} diff --git a/vendor/github.com/bitrise-io/go-utils/fileutil/fileutil.go b/vendor/github.com/bitrise-io/go-utils/fileutil/fileutil.go index 80c913b..3633e28 100644 --- a/vendor/github.com/bitrise-io/go-utils/fileutil/fileutil.go +++ b/vendor/github.com/bitrise-io/go-utils/fileutil/fileutil.go @@ -7,10 +7,56 @@ import ( "io/ioutil" "log" "os" + "path/filepath" "github.com/bitrise-io/go-utils/pathutil" ) +// FileManager ... +type FileManager interface { + Remove(path string) error + RemoveAll(path string) error + Write(path string, value string, mode os.FileMode) error +} + +type fileManager struct{} + +// NewFileManager ... +func NewFileManager() FileManager { + return fileManager{} +} + +// Remove ... +func (fileManager) Remove(path string) error { + return os.Remove(path) +} + +// RemoveAll ... +func (fileManager) RemoveAll(path string) error { + return os.RemoveAll(path) +} + +// Write ... +func (fileManager) Write(path string, value string, mode os.FileMode) error { + if err := ensureSavePath(path); err != nil { + return err + } + + if err := WriteStringToFile(path, value); err != nil { + return err + } + + if err := os.Chmod(path, mode); err != nil { + return err + } + return nil +} + +func ensureSavePath(savePath string) error { + dirPath := filepath.Dir(savePath) + return os.MkdirAll(dirPath, 0700) +} + // WriteStringToFile ... func WriteStringToFile(pth string, fileCont string) error { return WriteBytesToFile(pth, []byte(fileCont)) diff --git a/vendor/github.com/bitrise-io/go-utils/log/defaultlogger.go b/vendor/github.com/bitrise-io/go-utils/log/defaultlogger.go deleted file mode 100644 index 0d2a307..0000000 --- a/vendor/github.com/bitrise-io/go-utils/log/defaultlogger.go +++ /dev/null @@ -1,57 +0,0 @@ -package log - -// DefaultLogger ... -type DefaultLogger struct { - ts bool -} - -// NewDefaultLogger ... -func NewDefaultLogger(withTimestamp bool) DefaultLogger { - return DefaultLogger{withTimestamp} -} - -// Donef ... -func (dl DefaultLogger) Donef(format string, v ...interface{}) { - fSelect(dl.ts, TDonef, Donef)(format, v...) -} - -// Successf ... -func (dl DefaultLogger) Successf(format string, v ...interface{}) { - fSelect(dl.ts, TSuccessf, Successf)(format, v...) -} - -// Infof ... -func (dl DefaultLogger) Infof(format string, v ...interface{}) { - fSelect(dl.ts, TInfof, Infof)(format, v...) -} - -// Printf ... -func (dl DefaultLogger) Printf(format string, v ...interface{}) { - fSelect(dl.ts, TPrintf, Printf)(format, v...) -} - -// Warnf ... -func (dl DefaultLogger) Warnf(format string, v ...interface{}) { - fSelect(dl.ts, TWarnf, Warnf)(format, v...) -} - -// Errorf ... -func (dl DefaultLogger) Errorf(format string, v ...interface{}) { - fSelect(dl.ts, TErrorf, Errorf)(format, v...) -} - -// Debugf ... -func (dl DefaultLogger) Debugf(format string, v ...interface{}) { - if enableDebugLog { - fSelect(dl.ts, TDebugf, Debugf)(format, v...) - } -} - -type logfunc func(string, ...interface{}) - -func fSelect(t bool, tf logfunc, f logfunc) logfunc { - if t { - return tf - } - return f -} diff --git a/vendor/github.com/bitrise-io/go-utils/log/dummylogger.go b/vendor/github.com/bitrise-io/go-utils/log/dummylogger.go deleted file mode 100644 index 54b0bb9..0000000 --- a/vendor/github.com/bitrise-io/go-utils/log/dummylogger.go +++ /dev/null @@ -1,30 +0,0 @@ -package log - -// DummyLogger ... -type DummyLogger struct{} - -// NewDummyLogger ... -func NewDummyLogger() DummyLogger { - return DummyLogger{} -} - -// Donef ... -func (dl DummyLogger) Donef(format string, v ...interface{}) {} - -// Successf ... -func (dl DummyLogger) Successf(format string, v ...interface{}) {} - -// Infof ... -func (dl DummyLogger) Infof(format string, v ...interface{}) {} - -// Printf ... -func (dl DummyLogger) Printf(format string, v ...interface{}) {} - -// Debugf ... -func (dl DummyLogger) Debugf(format string, v ...interface{}) {} - -// Warnf ... -func (dl DummyLogger) Warnf(format string, v ...interface{}) {} - -// Errorf ... -func (dl DummyLogger) Errorf(format string, v ...interface{}) {} diff --git a/vendor/github.com/bitrise-io/go-utils/log/json_logger.go b/vendor/github.com/bitrise-io/go-utils/log/json_logger.go deleted file mode 100644 index 31148b3..0000000 --- a/vendor/github.com/bitrise-io/go-utils/log/json_logger.go +++ /dev/null @@ -1,33 +0,0 @@ -package log - -import ( - "fmt" - "io" - "os" -) - -// JSONLoger ... -type JSONLoger struct { - writer io.Writer -} - -// NewJSONLoger ... -func NewJSONLoger(writer io.Writer) *JSONLoger { - return &JSONLoger{ - writer: writer, - } -} - -// NewDefaultJSONLoger ... -func NewDefaultJSONLoger() JSONLoger { - return JSONLoger{ - writer: os.Stdout, - } -} - -// Print ... -func (l JSONLoger) Print(f Formatable) { - if _, err := fmt.Fprint(l.writer, f.JSON()); err != nil { - fmt.Printf("failed to print message: %s, error: %s\n", f.JSON(), err) - } -} diff --git a/vendor/github.com/bitrise-io/go-utils/log/log.go b/vendor/github.com/bitrise-io/go-utils/log/log.go index 1b69028..84bd490 100644 --- a/vendor/github.com/bitrise-io/go-utils/log/log.go +++ b/vendor/github.com/bitrise-io/go-utils/log/log.go @@ -7,28 +7,240 @@ import ( "time" ) -var outWriter io.Writer = os.Stdout +// Logger ... +type Logger interface { + Infof(format string, v ...interface{}) + Warnf(format string, v ...interface{}) + Printf(format string, v ...interface{}) + Donef(format string, v ...interface{}) + Debugf(format string, v ...interface{}) + Errorf(format string, v ...interface{}) + TInfof(format string, v ...interface{}) + TWarnf(format string, v ...interface{}) + TPrintf(format string, v ...interface{}) + TDonef(format string, v ...interface{}) + TDebugf(format string, v ...interface{}) + TErrorf(format string, v ...interface{}) + Println() + EnableDebugLog(enable bool) +} -// SetOutWriter ... -func SetOutWriter(writer io.Writer) { - outWriter = writer +const defaultTimeStampLayout = "15:04:05" + +type defaultLogger struct { + enableDebugLog bool + timestampLayout string + stdout io.Writer +} + +// NewLogger ... +func NewLogger() Logger { + return &defaultLogger{enableDebugLog: false, timestampLayout: defaultTimeStampLayout, stdout: os.Stdout} +} + +// EnableDebugLog ... +func (l *defaultLogger) EnableDebugLog(enable bool) { + l.enableDebugLog = enable +} + +// Infof ... +func (l *defaultLogger) Infof(format string, v ...interface{}) { + l.printf(infoSeverity, false, format, v...) +} + +// Warnf ... +func (l *defaultLogger) Warnf(format string, v ...interface{}) { + l.printf(warnSeverity, false, format, v...) +} + +// Printf ... +func (l *defaultLogger) Printf(format string, v ...interface{}) { + l.printf(normalSeverity, false, format, v...) +} + +// Donef ... +func (l *defaultLogger) Donef(format string, v ...interface{}) { + l.printf(doneSeverity, false, format, v...) +} + +// Debugf ... +func (l *defaultLogger) Debugf(format string, v ...interface{}) { + if l.enableDebugLog { + l.printf(debugSeverity, false, format, v...) + } +} + +// Errorf ... +func (l *defaultLogger) Errorf(format string, v ...interface{}) { + l.printf(errorSeverity, false, format, v...) +} + +// TInfof ... +func (l *defaultLogger) TInfof(format string, v ...interface{}) { + l.printf(infoSeverity, true, format, v...) +} + +// TWarnf ... +func (l *defaultLogger) TWarnf(format string, v ...interface{}) { + l.printf(warnSeverity, true, format, v...) +} + +// TPrintf ... +func (l *defaultLogger) TPrintf(format string, v ...interface{}) { + l.printf(normalSeverity, true, format, v...) +} + +// TDonef ... +func (l *defaultLogger) TDonef(format string, v ...interface{}) { + l.printf(doneSeverity, true, format, v...) +} + +// TDebugf ... +func (l *defaultLogger) TDebugf(format string, v ...interface{}) { + if l.enableDebugLog { + l.printf(debugSeverity, true, format, v...) + } +} + +// TErrorf ... +func (l *defaultLogger) TErrorf(format string, v ...interface{}) { + l.printf(errorSeverity, true, format, v...) +} + +// Println ... +func (l *defaultLogger) Println() { + fmt.Println() +} + +func (l *defaultLogger) timestampField() string { + currentTime := time.Now() + return fmt.Sprintf("[%s]", currentTime.Format(l.timestampLayout)) +} + +func (l *defaultLogger) prefixCurrentTime(message string) string { + return fmt.Sprintf("%s %s", l.timestampField(), message) } -var enableDebugLog = false +func (l *defaultLogger) createLogMsg(severity Severity, withTime bool, format string, v ...interface{}) string { + colorFunc := severityColorFuncMap[severity] + message := colorFunc(format, v...) + if withTime { + message = l.prefixCurrentTime(message) + } + + return message +} + +func (l *defaultLogger) printf(severity Severity, withTime bool, format string, v ...interface{}) { + message := l.createLogMsg(severity, withTime, format, v...) + if _, err := fmt.Fprintln(l.stdout, message); err != nil { + fmt.Printf("failed to print message: %s, error: %s\n", message, err) + } +} + +// RInfof ... +func RInfof(stepID string, tag string, data map[string]interface{}, format string, v ...interface{}) { + rprintf("info", stepID, tag, data, format, v...) +} + +// RWarnf ... +func RWarnf(stepID string, tag string, data map[string]interface{}, format string, v ...interface{}) { + rprintf("warn", stepID, tag, data, format, v...) +} + +// RErrorf ... +func RErrorf(stepID string, tag string, data map[string]interface{}, format string, v ...interface{}) { + rprintf("error", stepID, tag, data, format, v...) +} + +var deprecatedLogger = defaultLogger{stdout: os.Stdout, enableDebugLog: false, timestampLayout: defaultTimeStampLayout} // SetEnableDebugLog ... +// Deprecated: use Logger instead. func SetEnableDebugLog(enable bool) { - enableDebugLog = enable + deprecatedLogger.enableDebugLog = enable } -var timestampLayout = "15:04:05" - // SetTimestampLayout ... +// Deprecated: use Logger instead. func SetTimestampLayout(layout string) { - timestampLayout = layout + deprecatedLogger.timestampLayout = layout } -func timestampField() string { - currentTime := time.Now() - return fmt.Sprintf("[%s]", currentTime.Format(timestampLayout)) +// SetOutWriter ... +// Deprecated: use Logger for verification instead. +func SetOutWriter(writer io.Writer) { + deprecatedLogger.stdout = writer +} + +// Donef ... +// Deprecated: use Logger instead. +func Donef(format string, v ...interface{}) { + deprecatedLogger.Donef(format, v...) +} + +// Infof ... +// Deprecated: use Logger instead. +func Infof(format string, v ...interface{}) { + deprecatedLogger.Infof(format, v...) +} + +// Printf ... +// Deprecated: use Logger instead. +func Printf(format string, v ...interface{}) { + deprecatedLogger.Printf(format, v...) +} + +// Debugf ... +// Deprecated: use Logger instead. +func Debugf(format string, v ...interface{}) { + deprecatedLogger.Debugf(format, v...) +} + +// Warnf ... +// Deprecated: use Logger instead. +func Warnf(format string, v ...interface{}) { + deprecatedLogger.Warnf(format, v...) +} + +// Errorf ... +// Deprecated: use Logger instead. +func Errorf(format string, v ...interface{}) { + deprecatedLogger.Errorf(format, v...) +} + +// TDonef ... +// Deprecated: use Logger instead. +func TDonef(format string, v ...interface{}) { + deprecatedLogger.TDonef(format, v...) +} + +// TInfof ... +// Deprecated: use Logger instead. +func TInfof(format string, v ...interface{}) { + deprecatedLogger.TInfof(format, v...) +} + +// TPrintf ... +// Deprecated: use Logger instead. +func TPrintf(format string, v ...interface{}) { + deprecatedLogger.TPrintf(format, v...) +} + +// TDebugf ... +// Deprecated: use Logger instead. +func TDebugf(format string, v ...interface{}) { + deprecatedLogger.TDebugf(format, v...) +} + +// TWarnf ... +// Deprecated: use Logger instead. +func TWarnf(format string, v ...interface{}) { + deprecatedLogger.TWarnf(format, v...) +} + +// TErrorf ... +// Deprecated: use Logger instead. +func TErrorf(format string, v ...interface{}) { + deprecatedLogger.TErrorf(format, v...) } diff --git a/vendor/github.com/bitrise-io/go-utils/log/logger.go b/vendor/github.com/bitrise-io/go-utils/log/logger.go deleted file mode 100644 index 4691122..0000000 --- a/vendor/github.com/bitrise-io/go-utils/log/logger.go +++ /dev/null @@ -1,12 +0,0 @@ -package log - -// Logger ... -type Logger interface { - Print(f Formatable) -} - -// Formatable ... -type Formatable interface { - String() string - JSON() string -} diff --git a/vendor/github.com/bitrise-io/go-utils/log/print.go b/vendor/github.com/bitrise-io/go-utils/log/print.go deleted file mode 100644 index 1c817c4..0000000 --- a/vendor/github.com/bitrise-io/go-utils/log/print.go +++ /dev/null @@ -1,115 +0,0 @@ -package log - -import ( - "fmt" -) - -func printf(severity Severity, withTime bool, format string, v ...interface{}) { - message := createLogMsg(severity, withTime, format, v...) - if _, err := fmt.Fprintln(outWriter, message); err != nil { - fmt.Printf("failed to print message: %s, error: %s\n", message, err) - } -} - -func createLogMsg(severity Severity, withTime bool, format string, v ...interface{}) string { - colorFunc := severityColorFuncMap[severity] - message := colorFunc(format, v...) - if withTime { - message = prefixCurrentTime(message) - } - - return message -} - -func prefixCurrentTime(message string) string { - return fmt.Sprintf("%s %s", timestampField(), message) -} - -// Successf ... -func Successf(format string, v ...interface{}) { - printf(successSeverity, false, format, v...) -} - -// Donef ... -func Donef(format string, v ...interface{}) { - Successf(format, v...) -} - -// Infof ... -func Infof(format string, v ...interface{}) { - printf(infoSeverity, false, format, v...) -} - -// Printf ... -func Printf(format string, v ...interface{}) { - printf(normalSeverity, false, format, v...) -} - -// Debugf ... -func Debugf(format string, v ...interface{}) { - if enableDebugLog { - printf(debugSeverity, false, format, v...) - } -} - -// Warnf ... -func Warnf(format string, v ...interface{}) { - printf(warnSeverity, false, format, v...) -} - -// Errorf ... -func Errorf(format string, v ...interface{}) { - printf(errorSeverity, false, format, v...) -} - -// TSuccessf ... -func TSuccessf(format string, v ...interface{}) { - printf(successSeverity, true, format, v...) -} - -// TDonef ... -func TDonef(format string, v ...interface{}) { - TSuccessf(format, v...) -} - -// TInfof ... -func TInfof(format string, v ...interface{}) { - printf(infoSeverity, true, format, v...) -} - -// TPrintf ... -func TPrintf(format string, v ...interface{}) { - printf(normalSeverity, true, format, v...) -} - -// TDebugf ... -func TDebugf(format string, v ...interface{}) { - if enableDebugLog { - printf(debugSeverity, true, format, v...) - } -} - -// TWarnf ... -func TWarnf(format string, v ...interface{}) { - printf(warnSeverity, true, format, v...) -} - -// TErrorf ... -func TErrorf(format string, v ...interface{}) { - printf(errorSeverity, true, format, v...) -} - -// RInfof ... -func RInfof(stepID string, tag string, data map[string]interface{}, format string, v ...interface{}) { - rprintf("info", stepID, tag, data, format, v...) -} - -// RWarnf ... -func RWarnf(stepID string, tag string, data map[string]interface{}, format string, v ...interface{}) { - rprintf("warn", stepID, tag, data, format, v...) -} - -// RErrorf ... -func RErrorf(stepID string, tag string, data map[string]interface{}, format string, v ...interface{}) { - rprintf("error", stepID, tag, data, format, v...) -} diff --git a/vendor/github.com/bitrise-io/go-utils/log/raw_logger.go b/vendor/github.com/bitrise-io/go-utils/log/raw_logger.go deleted file mode 100644 index a673380..0000000 --- a/vendor/github.com/bitrise-io/go-utils/log/raw_logger.go +++ /dev/null @@ -1,33 +0,0 @@ -package log - -import ( - "fmt" - "io" - "os" -) - -// RawLogger ... -type RawLogger struct { - writer io.Writer -} - -// NewRawLogger ... -func NewRawLogger(writer io.Writer) *RawLogger { - return &RawLogger{ - writer: writer, - } -} - -// NewDefaultRawLogger ... -func NewDefaultRawLogger() RawLogger { - return RawLogger{ - writer: os.Stdout, - } -} - -// Print ... -func (l RawLogger) Print(f Formatable) { - if _, err := fmt.Fprintln(l.writer, f.String()); err != nil { - fmt.Printf("failed to print message: %s, error: %s\n", f.String(), err) - } -} diff --git a/vendor/github.com/bitrise-io/go-utils/log/severity.go b/vendor/github.com/bitrise-io/go-utils/log/severity.go index 4e7786d..fc1fc96 100644 --- a/vendor/github.com/bitrise-io/go-utils/log/severity.go +++ b/vendor/github.com/bitrise-io/go-utils/log/severity.go @@ -10,26 +10,26 @@ const ( warnSeverity normalSeverity infoSeverity - successSeverity + doneSeverity debugSeverity ) type severityColorFunc colorstring.ColorfFunc var ( - successSeverityColorFunc severityColorFunc = colorstring.Greenf - infoSeverityColorFunc severityColorFunc = colorstring.Bluef - normalSeverityColorFunc severityColorFunc = colorstring.NoColorf - debugSeverityColorFunc severityColorFunc = colorstring.Magentaf - warnSeverityColorFunc severityColorFunc = colorstring.Yellowf - errorSeverityColorFunc severityColorFunc = colorstring.Redf + doneSeverityColorFunc severityColorFunc = colorstring.Greenf + infoSeverityColorFunc severityColorFunc = colorstring.Bluef + normalSeverityColorFunc severityColorFunc = colorstring.NoColorf + debugSeverityColorFunc severityColorFunc = colorstring.Magentaf + warnSeverityColorFunc severityColorFunc = colorstring.Yellowf + errorSeverityColorFunc severityColorFunc = colorstring.Redf ) var severityColorFuncMap = map[Severity]severityColorFunc{ - successSeverity: successSeverityColorFunc, - infoSeverity: infoSeverityColorFunc, - normalSeverity: normalSeverityColorFunc, - debugSeverity: debugSeverityColorFunc, - warnSeverity: warnSeverityColorFunc, - errorSeverity: errorSeverityColorFunc, + doneSeverity: doneSeverityColorFunc, + infoSeverity: infoSeverityColorFunc, + normalSeverity: normalSeverityColorFunc, + debugSeverity: debugSeverityColorFunc, + warnSeverity: warnSeverityColorFunc, + errorSeverity: errorSeverityColorFunc, } diff --git a/vendor/github.com/bitrise-io/go-utils/pathutil/glob.go b/vendor/github.com/bitrise-io/go-utils/pathutil/glob.go deleted file mode 100644 index 232dd51..0000000 --- a/vendor/github.com/bitrise-io/go-utils/pathutil/glob.go +++ /dev/null @@ -1,13 +0,0 @@ -package pathutil - -// EscapeGlobPath escapes a partial path, determined at runtime, used as a parameter for filepath.Glob -func EscapeGlobPath(path string) string { - var escaped string - for _, ch := range path { - if ch == '[' || ch == ']' || ch == '-' || ch == '*' || ch == '?' || ch == '\\' { - escaped += "\\" - } - escaped += string(ch) - } - return escaped -} diff --git a/vendor/github.com/bitrise-io/go-utils/pathutil/path_filter.go b/vendor/github.com/bitrise-io/go-utils/pathutil/path_filter.go index 0bfd0fc..db0665d 100644 --- a/vendor/github.com/bitrise-io/go-utils/pathutil/path_filter.go +++ b/vendor/github.com/bitrise-io/go-utils/pathutil/path_filter.go @@ -9,6 +9,27 @@ import ( "strings" ) +// ListEntries filters contents of a directory using the provided filters +func ListEntries(dir string, filters ...FilterFunc) ([]string, error) { + absDir, err := filepath.Abs(dir) + if err != nil { + return []string{}, err + } + + entries, err := ioutil.ReadDir(absDir) + if err != nil { + return []string{}, err + } + + var paths []string + for _, entry := range entries { + pth := filepath.Join(absDir, entry.Name()) + paths = append(paths, pth) + } + + return FilterPaths(paths, filters...) +} + // FilterPaths ... func FilterPaths(fileList []string, filters ...FilterFunc) ([]string, error) { var filtered []string diff --git a/vendor/github.com/bitrise-io/go-utils/pathutil/pathutil.go b/vendor/github.com/bitrise-io/go-utils/pathutil/pathutil.go index db577e3..aeb8e22 100644 --- a/vendor/github.com/bitrise-io/go-utils/pathutil/pathutil.go +++ b/vendor/github.com/bitrise-io/go-utils/pathutil/pathutil.go @@ -10,47 +10,53 @@ import ( "strings" ) -// RevokableChangeDir ... -func RevokableChangeDir(dir string) (func() error, error) { - origDir, err := CurrentWorkingDirectoryAbsolutePath() - if err != nil { - return nil, err - } - - revokeFn := func() error { - return os.Chdir(origDir) - } +// +// Path provider functions - return revokeFn, os.Chdir(dir) +// PathProvider ... +type PathProvider interface { + CreateTempDir(prefix string) (string, error) } -// ChangeDirForFunction ... -func ChangeDirForFunction(dir string, fn func()) error { - revokeFn, err := RevokableChangeDir(dir) - if err != nil { - return err - } +type defaultPathProvider struct{} - fn() +// NewPathProvider ... +func NewPathProvider() PathProvider { + return defaultPathProvider{} +} - return revokeFn() +func (defaultPathProvider) CreateTempDir(prefix string) (string, error) { + return NormalizedOSTempDirPath(prefix) } -// IsRelativePath ... -func IsRelativePath(pth string) bool { - if strings.HasPrefix(pth, "./") { - return true +// NormalizedOSTempDirPath ... +// Creates a temp dir, and returns its path. +// If tmpDirNamePrefix is provided it'll be used +// as the tmp dir's name prefix. +// Normalized: it's guaranteed that the path won't end with '/'. +func NormalizedOSTempDirPath(tmpDirNamePrefix string) (retPth string, err error) { + retPth, err = ioutil.TempDir("", tmpDirNamePrefix) + if strings.HasSuffix(retPth, "/") { + retPth = retPth[:len(retPth)-1] } + return +} - if strings.HasPrefix(pth, "/") { - return false - } +// CurrentWorkingDirectoryAbsolutePath ... +func CurrentWorkingDirectoryAbsolutePath() (string, error) { + return filepath.Abs("./") +} - if strings.HasPrefix(pth, "$") { - return false +// UserHomeDir ... +func UserHomeDir() string { + if runtime.GOOS == "windows" { + home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") + if home == "" { + home = os.Getenv("USERPROFILE") + } + return home } - - return true + return os.Getenv("HOME") } // EnsureDirExist ... @@ -62,6 +68,25 @@ func EnsureDirExist(dir string) error { return nil } +// +// Path checker functions + +// PathChecker ... +type PathChecker interface { + IsPathExists(pth string) (bool, error) +} + +type defaultPathChecker struct{} + +// NewPathChecker ... +func NewPathChecker() PathChecker { + return defaultPathChecker{} +} + +func (c defaultPathChecker) IsPathExists(pth string) (bool, error) { + return IsPathExists(pth) +} + func genericIsPathExists(pth string) (os.FileInfo, bool, error) { if pth == "" { return nil, false, errors.New("No path provided") @@ -76,12 +101,6 @@ func genericIsPathExists(pth string) (os.FileInfo, bool, error) { return fileInf, false, err } -// IsPathExists ... -func IsPathExists(pth string) (bool, error) { - _, isExists, err := genericIsPathExists(pth) - return isExists, err -} - // PathCheckAndInfos ... // Returns: // 1. file info or nil @@ -106,6 +125,32 @@ func IsDirExists(pth string) (bool, error) { return fileInf.IsDir(), nil } +// IsPathExists ... +func IsPathExists(pth string) (bool, error) { + _, isExists, err := genericIsPathExists(pth) + return isExists, err +} + +// +// Path modifier functions + +// PathModifier ... +type PathModifier interface { + AbsPath(pth string) (string, error) +} + +type defaultPathModifier struct{} + +// NewPathModifier ... +func NewPathModifier() PathModifier { + return defaultPathModifier{} +} + +// AbsPath ... +func (defaultPathModifier) AbsPath(pth string) (string, error) { + return AbsPath(pth) +} + // AbsPath expands ENV vars and the ~ character // then call Go's Abs func AbsPath(pth string) (string, error) { @@ -150,34 +195,21 @@ func ExpandTilde(pth string) (string, error) { return pth, nil } -// CurrentWorkingDirectoryAbsolutePath ... -func CurrentWorkingDirectoryAbsolutePath() (string, error) { - return filepath.Abs("./") -} +// IsRelativePath ... +func IsRelativePath(pth string) bool { + if strings.HasPrefix(pth, "./") { + return true + } -// UserHomeDir ... -func UserHomeDir() string { - if runtime.GOOS == "windows" { - home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") - if home == "" { - home = os.Getenv("USERPROFILE") - } - return home + if strings.HasPrefix(pth, "/") { + return false } - return os.Getenv("HOME") -} -// NormalizedOSTempDirPath ... -// Creates a temp dir, and returns its path. -// If tmpDirNamePrefix is provided it'll be used -// as the tmp dir's name prefix. -// Normalized: it's guaranteed that the path won't end with '/'. -func NormalizedOSTempDirPath(tmpDirNamePrefix string) (retPth string, err error) { - retPth, err = ioutil.TempDir("", tmpDirNamePrefix) - if strings.HasSuffix(retPth, "/") { - retPth = retPth[:len(retPth)-1] + if strings.HasPrefix(pth, "$") { + return false } - return + + return true } // GetFileName returns the name of the file from a given path or the name of the directory if it is a directory @@ -185,54 +217,43 @@ func GetFileName(path string) string { return strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)) } -// ListPathInDirSortedByComponents ... -func ListPathInDirSortedByComponents(searchDir string, relPath bool) ([]string, error) { - searchDir, err := filepath.Abs(searchDir) - if err != nil { - return []string{}, err - } - - var fileList []string - - if err := filepath.Walk(searchDir, func(path string, _ os.FileInfo, walkErr error) error { - if walkErr != nil { - return walkErr +// EscapeGlobPath escapes a partial path, determined at runtime, used as a parameter for filepath.Glob +func EscapeGlobPath(path string) string { + var escaped string + for _, ch := range path { + if ch == '[' || ch == ']' || ch == '-' || ch == '*' || ch == '?' || ch == '\\' { + escaped += "\\" } - - if relPath { - rel, err := filepath.Rel(searchDir, path) - if err != nil { - return err - } - path = rel - } - - fileList = append(fileList, path) - - return nil - }); err != nil { - return []string{}, err + escaped += string(ch) } - return SortPathsByComponents(fileList) + return escaped } -// ListEntries filters contents of a directory using the provided filters -func ListEntries(dir string, filters ...FilterFunc) ([]string, error) { - absDir, err := filepath.Abs(dir) +// +// Change dir functions + +// RevokableChangeDir ... +func RevokableChangeDir(dir string) (func() error, error) { + origDir, err := CurrentWorkingDirectoryAbsolutePath() if err != nil { - return []string{}, err + return nil, err } - entries, err := ioutil.ReadDir(absDir) - if err != nil { - return []string{}, err + revokeFn := func() error { + return os.Chdir(origDir) } - var paths []string - for _, entry := range entries { - pth := filepath.Join(absDir, entry.Name()) - paths = append(paths, pth) + return revokeFn, os.Chdir(dir) +} + +// ChangeDirForFunction ... +func ChangeDirForFunction(dir string, fn func()) error { + revokeFn, err := RevokableChangeDir(dir) + if err != nil { + return err } - return FilterPaths(paths, filters...) + fn() + + return revokeFn() } diff --git a/vendor/github.com/bitrise-io/go-utils/pathutil/sortable_path.go b/vendor/github.com/bitrise-io/go-utils/pathutil/sortable_path.go index 4bed6bf..97f63c3 100644 --- a/vendor/github.com/bitrise-io/go-utils/pathutil/sortable_path.go +++ b/vendor/github.com/bitrise-io/go-utils/pathutil/sortable_path.go @@ -7,6 +7,37 @@ import ( "strings" ) +// ListPathInDirSortedByComponents ... +func ListPathInDirSortedByComponents(searchDir string, relPath bool) ([]string, error) { + searchDir, err := filepath.Abs(searchDir) + if err != nil { + return []string{}, err + } + + var fileList []string + + if err := filepath.Walk(searchDir, func(path string, _ os.FileInfo, walkErr error) error { + if walkErr != nil { + return walkErr + } + + if relPath { + rel, err := filepath.Rel(searchDir, path) + if err != nil { + return err + } + path = rel + } + + fileList = append(fileList, path) + + return nil + }); err != nil { + return []string{}, err + } + return SortPathsByComponents(fileList) +} + // SortablePath ... type SortablePath struct { Pth string diff --git a/vendor/github.com/hashicorp/go-retryablehttp/.travis.yml b/vendor/github.com/hashicorp/go-retryablehttp/.travis.yml deleted file mode 100644 index c4fb6d6..0000000 --- a/vendor/github.com/hashicorp/go-retryablehttp/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -sudo: false - -language: go - -go: - - 1.12.4 - -branches: - only: - - master - -script: make updatedeps test diff --git a/vendor/github.com/hashicorp/go-retryablehttp/README.md b/vendor/github.com/hashicorp/go-retryablehttp/README.md index 30357c7..8943bec 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/README.md +++ b/vendor/github.com/hashicorp/go-retryablehttp/README.md @@ -26,6 +26,7 @@ fails so that the full request can be attempted again. See the details. Version 0.6.0 and before are compatible with Go prior to 1.12. From 0.6.1 onward, Go 1.12+ is required. +From 0.6.7 onward, Go 1.13+ is required. Example Use =========== diff --git a/vendor/github.com/hashicorp/go-retryablehttp/client.go b/vendor/github.com/hashicorp/go-retryablehttp/client.go index f1ccd3d..adbdd92 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/client.go +++ b/vendor/github.com/hashicorp/go-retryablehttp/client.go @@ -35,11 +35,12 @@ import ( "net/url" "os" "regexp" + "strconv" "strings" "sync" "time" - "github.com/hashicorp/go-cleanhttp" + cleanhttp "github.com/hashicorp/go-cleanhttp" ) var ( @@ -276,12 +277,16 @@ type Logger interface { Printf(string, ...interface{}) } -// LeveledLogger interface implements the basic methods that a logger library needs +// LeveledLogger is an interface that can be implemented by any logger or a +// logger wrapper to provide leveled logging. The methods accept a message +// string and a variadic number of key-value pairs. For log.Printf style +// formatting where message string contains a format specifier, use Logger +// interface. type LeveledLogger interface { - Error(string, ...interface{}) - Info(string, ...interface{}) - Debug(string, ...interface{}) - Warn(string, ...interface{}) + Error(msg string, keysAndValues ...interface{}) + Info(msg string, keysAndValues ...interface{}) + Debug(msg string, keysAndValues ...interface{}) + Warn(msg string, keysAndValues ...interface{}) } // hookLogger adapts an LeveledLogger to Logger for use by the existing hook functions @@ -357,6 +362,7 @@ type Client struct { ErrorHandler ErrorHandler loggerInit sync.Once + clientInit sync.Once } // NewClient creates a new Client with default settings. @@ -398,21 +404,39 @@ func DefaultRetryPolicy(ctx context.Context, resp *http.Response, err error) (bo return false, ctx.Err() } + // don't propagate other errors + shouldRetry, _ := baseRetryPolicy(resp, err) + return shouldRetry, nil +} + +// ErrorPropagatedRetryPolicy is the same as DefaultRetryPolicy, except it +// propagates errors back instead of returning nil. This allows you to inspect +// why it decided to retry or not. +func ErrorPropagatedRetryPolicy(ctx context.Context, resp *http.Response, err error) (bool, error) { + // do not retry on context.Canceled or context.DeadlineExceeded + if ctx.Err() != nil { + return false, ctx.Err() + } + + return baseRetryPolicy(resp, err) +} + +func baseRetryPolicy(resp *http.Response, err error) (bool, error) { if err != nil { if v, ok := err.(*url.Error); ok { // Don't retry if the error was due to too many redirects. if redirectsErrorRe.MatchString(v.Error()) { - return false, nil + return false, v } // Don't retry if the error was due to an invalid protocol scheme. if schemeErrorRe.MatchString(v.Error()) { - return false, nil + return false, v } // Don't retry if the error was due to TLS cert verification failure. if _, ok := v.Err.(x509.UnknownAuthorityError); ok { - return false, nil + return false, v } } @@ -420,12 +444,19 @@ func DefaultRetryPolicy(ctx context.Context, resp *http.Response, err error) (bo return true, nil } + // 429 Too Many Requests is recoverable. Sometimes the server puts + // a Retry-After response header to indicate when the server is + // available to start processing request from client. + if resp.StatusCode == http.StatusTooManyRequests { + return true, nil + } + // Check the response code. We retry on 500-range responses to allow // the server time to recover, as 500's are typically not permanent // errors and may relate to outages on the server side. This will catch // invalid response codes as well, like 0 and 999. if resp.StatusCode == 0 || (resp.StatusCode >= 500 && resp.StatusCode != 501) { - return true, nil + return true, fmt.Errorf("unexpected HTTP status %s", resp.Status) } return false, nil @@ -434,7 +465,21 @@ func DefaultRetryPolicy(ctx context.Context, resp *http.Response, err error) (bo // DefaultBackoff provides a default callback for Client.Backoff which // will perform exponential backoff based on the attempt number and limited // by the provided minimum and maximum durations. +// +// It also tries to parse Retry-After response header when a http.StatusTooManyRequests +// (HTTP Code 429) is found in the resp parameter. Hence it will return the number of +// seconds the server states it may be ready to process more requests from this client. func DefaultBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { + if resp != nil { + if resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode == http.StatusServiceUnavailable { + if s, ok := resp.Header["Retry-After"]; ok { + if sleep, err := strconv.ParseInt(s[0], 10, 64); err == nil { + return time.Second * time.Duration(sleep) + } + } + } + } + mult := math.Pow(2, float64(attemptNum)) * float64(min) sleep := time.Duration(mult) if float64(sleep) != mult || sleep > max { @@ -490,25 +535,31 @@ func PassthroughErrorHandler(resp *http.Response, err error, _ int) (*http.Respo // Do wraps calling an HTTP method with retries. func (c *Client) Do(req *Request) (*http.Response, error) { - if c.HTTPClient == nil { - c.HTTPClient = cleanhttp.DefaultPooledClient() - } + c.clientInit.Do(func() { + if c.HTTPClient == nil { + c.HTTPClient = cleanhttp.DefaultPooledClient() + } + }) logger := c.logger() if logger != nil { switch v := logger.(type) { - case Logger: - v.Printf("[DEBUG] %s %s", req.Method, req.URL) case LeveledLogger: v.Debug("performing request", "method", req.Method, "url", req.URL) + case Logger: + v.Printf("[DEBUG] %s %s", req.Method, req.URL) } } var resp *http.Response - var err error + var attempt int + var shouldRetry bool + var doErr, checkErr error for i := 0; ; i++ { + attempt++ + var code int // HTTP response code // Always rewind the request body when non-nil. @@ -527,30 +578,30 @@ func (c *Client) Do(req *Request) (*http.Response, error) { if c.RequestLogHook != nil { switch v := logger.(type) { - case Logger: - c.RequestLogHook(v, req.Request, i) case LeveledLogger: c.RequestLogHook(hookLogger{v}, req.Request, i) + case Logger: + c.RequestLogHook(v, req.Request, i) default: c.RequestLogHook(nil, req.Request, i) } } // Attempt the request - resp, err = c.HTTPClient.Do(req.Request) + resp, doErr = c.HTTPClient.Do(req.Request) if resp != nil { code = resp.StatusCode } // Check if we should continue with retries. - checkOK, checkErr := c.CheckRetry(req.Context(), resp, err) + shouldRetry, checkErr = c.CheckRetry(req.Context(), resp, doErr) - if err != nil { + if doErr != nil { switch v := logger.(type) { - case Logger: - v.Printf("[ERR] %s %s request failed: %v", req.Method, req.URL, err) case LeveledLogger: - v.Error("request failed", "error", err, "method", req.Method, "url", req.URL) + v.Error("request failed", "error", doErr, "method", req.Method, "url", req.URL) + case Logger: + v.Printf("[ERR] %s %s request failed: %v", req.Method, req.URL, doErr) } } else { // Call this here to maintain the behavior of logging all requests, @@ -558,23 +609,18 @@ func (c *Client) Do(req *Request) (*http.Response, error) { if c.ResponseLogHook != nil { // Call the response logger function if provided. switch v := logger.(type) { - case Logger: - c.ResponseLogHook(v, resp) case LeveledLogger: c.ResponseLogHook(hookLogger{v}, resp) + case Logger: + c.ResponseLogHook(v, resp) default: c.ResponseLogHook(nil, resp) } } } - // Now decide if we should continue. - if !checkOK { - if checkErr != nil { - err = checkErr - } - c.HTTPClient.CloseIdleConnections() - return resp, err + if !shouldRetry { + break } // We do this before drainBody because there's no need for the I/O if @@ -585,7 +631,7 @@ func (c *Client) Do(req *Request) (*http.Response, error) { } // We're going to retry, consume any response to reuse the connection. - if err == nil && resp != nil { + if doErr == nil { c.drainBody(resp.Body) } @@ -596,10 +642,10 @@ func (c *Client) Do(req *Request) (*http.Response, error) { } if logger != nil { switch v := logger.(type) { - case Logger: - v.Printf("[DEBUG] %s: retrying in %s (%d left)", desc, wait, remain) case LeveledLogger: v.Debug("retrying request", "request", desc, "timeout", wait, "remaining", remain) + case Logger: + v.Printf("[DEBUG] %s: retrying in %s (%d left)", desc, wait, remain) } } select { @@ -608,21 +654,44 @@ func (c *Client) Do(req *Request) (*http.Response, error) { return nil, req.Context().Err() case <-time.After(wait): } + + // Make shallow copy of http Request so that we can modify its body + // without racing against the closeBody call in persistConn.writeLoop. + httpreq := *req.Request + req.Request = &httpreq + } + + // this is the closest we have to success criteria + if doErr == nil && checkErr == nil && !shouldRetry { + return resp, nil + } + + defer c.HTTPClient.CloseIdleConnections() + + err := doErr + if checkErr != nil { + err = checkErr } if c.ErrorHandler != nil { - c.HTTPClient.CloseIdleConnections() - return c.ErrorHandler(resp, err, c.RetryMax+1) + return c.ErrorHandler(resp, err, attempt) } // By default, we close the response body and return an error without // returning the response if resp != nil { - resp.Body.Close() + c.drainBody(resp.Body) } - c.HTTPClient.CloseIdleConnections() - return nil, fmt.Errorf("%s %s giving up after %d attempts", - req.Method, req.URL, c.RetryMax+1) + + // this means CheckRetry thought the request was a failure, but didn't + // communicate why + if err == nil { + return nil, fmt.Errorf("%s %s giving up after %d attempt(s)", + req.Method, req.URL, attempt) + } + + return nil, fmt.Errorf("%s %s giving up after %d attempt(s): %w", + req.Method, req.URL, attempt, err) } // Try to read the response body so we can reuse this connection. @@ -632,10 +701,10 @@ func (c *Client) drainBody(body io.ReadCloser) { if err != nil { if c.logger() != nil { switch v := c.logger().(type) { - case Logger: - v.Printf("[ERR] error reading response body: %v", err) case LeveledLogger: v.Error("error reading response body", "error", err) + case Logger: + v.Printf("[ERR] error reading response body: %v", err) } } } diff --git a/vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go b/vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go index b841b4c..8f3ee35 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go +++ b/vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go @@ -1,7 +1,9 @@ package retryablehttp import ( + "errors" "net/http" + "net/url" "sync" ) @@ -39,5 +41,12 @@ func (rt *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { } // Execute the request. - return rt.Client.Do(retryableReq) + resp, err := rt.Client.Do(retryableReq) + // If we got an error returned by standard library's `Do` method, unwrap it + // otherwise we will wind up erroneously re-nesting the error. + if _, ok := err.(*url.Error); ok { + return resp, errors.Unwrap(err) + } + + return resp, err } diff --git a/vendor/modules.txt b/vendor/modules.txt index 234f348..b2f24cd 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -12,17 +12,18 @@ github.com/bitrise-io/bitrise-init/utility github.com/bitrise-io/envman/models # github.com/bitrise-io/go-android v0.0.0-20210527143215-3ad22ad02e2e github.com/bitrise-io/go-android/cache -# github.com/bitrise-io/go-steputils v0.0.0-20210527075147-910ce7a105a1 +# github.com/bitrise-io/go-steputils v0.0.0-20210923053150-ddc3f70aacd2 github.com/bitrise-io/go-steputils/cache github.com/bitrise-io/go-steputils/command/gems -github.com/bitrise-io/go-steputils/command/rubycommand +github.com/bitrise-io/go-steputils/command/ruby github.com/bitrise-io/go-steputils/input github.com/bitrise-io/go-steputils/step github.com/bitrise-io/go-steputils/stepconf github.com/bitrise-io/go-steputils/tools -# github.com/bitrise-io/go-utils v0.0.0-20210520073355-367fa34178f5 +# github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72 github.com/bitrise-io/go-utils/colorstring github.com/bitrise-io/go-utils/command +github.com/bitrise-io/go-utils/env github.com/bitrise-io/go-utils/errorutil github.com/bitrise-io/go-utils/filedownloader github.com/bitrise-io/go-utils/fileutil @@ -39,7 +40,7 @@ github.com/bitrise-io/go-xcode/devportalservice github.com/bitrise-io/stepman/models # github.com/hashicorp/go-cleanhttp v0.5.1 github.com/hashicorp/go-cleanhttp -# github.com/hashicorp/go-retryablehttp v0.6.6 +# github.com/hashicorp/go-retryablehttp v0.7.0 github.com/hashicorp/go-retryablehttp # github.com/hashicorp/go-version v1.3.0 github.com/hashicorp/go-version From ea99326460c77dcf6306e448e6f06dc849b5c4b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krisztia=CC=81n=20Go=CC=88drei?= Date: Fri, 24 Sep 2021 09:46:27 +0200 Subject: [PATCH 2/5] Update to latest go-steputils. --- go.mod | 2 +- go.sum | 10 ++-------- main.go | 2 +- .../go-steputils/{command => }/ruby/command.go | 3 +-- .../go-steputils/{command => }/ruby/environment.go | 0 vendor/modules.txt | 4 ++-- 6 files changed, 7 insertions(+), 14 deletions(-) rename vendor/github.com/bitrise-io/go-steputils/{command => }/ruby/command.go (99%) rename vendor/github.com/bitrise-io/go-steputils/{command => }/ruby/environment.go (100%) diff --git a/go.mod b/go.mod index e97374c..d7c5ada 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.12 require ( github.com/bitrise-io/bitrise-init v0.0.0-20210520122036-d213de321eb8 github.com/bitrise-io/go-android v0.0.0-20210527143215-3ad22ad02e2e - github.com/bitrise-io/go-steputils v0.0.0-20210923053150-ddc3f70aacd2 + github.com/bitrise-io/go-steputils v0.0.0-20210924074053-431016d2ea34 github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72 github.com/bitrise-io/go-xcode v0.0.0-20210521101355-fb6a1eb6e05b github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 diff --git a/go.sum b/go.sum index c687cd3..2a2e7bc 100644 --- a/go.sum +++ b/go.sum @@ -14,18 +14,13 @@ github.com/bitrise-io/go-android v0.0.0-20210527143215-3ad22ad02e2e/go.mod h1:gG github.com/bitrise-io/go-plist v0.0.0-20210301100253-4b1a112ccd10/go.mod h1:pARutiL3kEuRLV3JvswidvfCj+9Y3qMZtji2BDqLFsA= github.com/bitrise-io/go-steputils v0.0.0-20210507072936-92fde382fb33/go.mod h1:YCtb1VETn/rF9tCt9oInhd/cwbt1ETPm+dTlDIfyD+A= github.com/bitrise-io/go-steputils v0.0.0-20210514150206-5b6261447e77/go.mod h1:H0iZjgsAR5NA6pnlD/zKB6AbxEsskq55pwJ9klVmP8w= -github.com/bitrise-io/go-steputils v0.0.0-20210527075147-910ce7a105a1 h1:gi29hTdxGXAGQvZckPZ9V8BAEfP3eK/tiZgTC5s6h1c= -github.com/bitrise-io/go-steputils v0.0.0-20210527075147-910ce7a105a1/go.mod h1:H0iZjgsAR5NA6pnlD/zKB6AbxEsskq55pwJ9klVmP8w= -github.com/bitrise-io/go-steputils v0.0.0-20210922204217-d5e2f9ce0e4a h1:BVq3lyp7xY1h1zWGYdmB8pi6VLKIqw8kEqAHuLTdHDA= -github.com/bitrise-io/go-steputils v0.0.0-20210922204217-d5e2f9ce0e4a/go.mod h1:e3iET6YTYpobuCbA5iyvy1pxHUb+qfCDOpeMel0bI6Q= -github.com/bitrise-io/go-steputils v0.0.0-20210923053150-ddc3f70aacd2 h1:aKbxnR3yQpdUVDv80qsJKiFzIUSvCiCXDkff58qnQRc= -github.com/bitrise-io/go-steputils v0.0.0-20210923053150-ddc3f70aacd2/go.mod h1:e3iET6YTYpobuCbA5iyvy1pxHUb+qfCDOpeMel0bI6Q= +github.com/bitrise-io/go-steputils v0.0.0-20210924074053-431016d2ea34 h1:D1SOAAhTfD1+70Yo8VMQNRZT7C0EutHBQiqMYt3BdDE= +github.com/bitrise-io/go-steputils v0.0.0-20210924074053-431016d2ea34/go.mod h1:e3iET6YTYpobuCbA5iyvy1pxHUb+qfCDOpeMel0bI6Q= github.com/bitrise-io/go-utils v0.0.0-20210505091801-98b7dc39ee61/go.mod h1:nhdaDQFvaMny1CugVV6KjK92/q97ENo0RuKSW5I4fbA= github.com/bitrise-io/go-utils v0.0.0-20210505121718-07411d72e36e/go.mod h1:nhdaDQFvaMny1CugVV6KjK92/q97ENo0RuKSW5I4fbA= github.com/bitrise-io/go-utils v0.0.0-20210506064210-b22e2b7b3ad3/go.mod h1:nhdaDQFvaMny1CugVV6KjK92/q97ENo0RuKSW5I4fbA= github.com/bitrise-io/go-utils v0.0.0-20210507100250-37de47dfa6ce/go.mod h1:15EZZf02noI5nWFqXMZEoyb1CyqYRXTMz5Fyu4CWFzI= github.com/bitrise-io/go-utils v0.0.0-20210514083430-4d1fb0330dfe/go.mod h1:DRx7oFuAqk0dbKpAKCqWl0TgrowfJUb/MqYPRscxJOQ= -github.com/bitrise-io/go-utils v0.0.0-20210520073355-367fa34178f5 h1:kclxBfygfNK6kWUB+9xcsfPLBen8Us9gubhitfL/Z6c= github.com/bitrise-io/go-utils v0.0.0-20210520073355-367fa34178f5/go.mod h1:DRx7oFuAqk0dbKpAKCqWl0TgrowfJUb/MqYPRscxJOQ= github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72 h1:Eov/ocBE9sfljzLo7C/6GuLUtACWJpY6dRLDhTtJ2L8= github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72/go.mod h1:Vi4MHnaZVL3PVoPPA/Yp6g2pzntkDH8LGiRSY7qw6KQ= @@ -51,7 +46,6 @@ github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVo github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4= github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= diff --git a/main.go b/main.go index 5aec724..929c42b 100644 --- a/main.go +++ b/main.go @@ -13,7 +13,7 @@ import ( "github.com/bitrise-io/go-steputils/cache" "github.com/bitrise-io/go-steputils/command/gems" - "github.com/bitrise-io/go-steputils/command/ruby" + "github.com/bitrise-io/go-steputils/ruby" "github.com/bitrise-io/go-steputils/stepconf" "github.com/bitrise-io/go-utils/command" "github.com/bitrise-io/go-utils/env" diff --git a/vendor/github.com/bitrise-io/go-steputils/command/ruby/command.go b/vendor/github.com/bitrise-io/go-steputils/ruby/command.go similarity index 99% rename from vendor/github.com/bitrise-io/go-steputils/command/ruby/command.go rename to vendor/github.com/bitrise-io/go-steputils/ruby/command.go index 32953a0..8f70b65 100644 --- a/vendor/github.com/bitrise-io/go-steputils/command/ruby/command.go +++ b/vendor/github.com/bitrise-io/go-steputils/ruby/command.go @@ -4,9 +4,8 @@ import ( "errors" "strings" - "github.com/bitrise-io/go-utils/env" - "github.com/bitrise-io/go-utils/command" + "github.com/bitrise-io/go-utils/env" ) // CommandFactory ... diff --git a/vendor/github.com/bitrise-io/go-steputils/command/ruby/environment.go b/vendor/github.com/bitrise-io/go-steputils/ruby/environment.go similarity index 100% rename from vendor/github.com/bitrise-io/go-steputils/command/ruby/environment.go rename to vendor/github.com/bitrise-io/go-steputils/ruby/environment.go diff --git a/vendor/modules.txt b/vendor/modules.txt index b2f24cd..1811f89 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -12,11 +12,11 @@ github.com/bitrise-io/bitrise-init/utility github.com/bitrise-io/envman/models # github.com/bitrise-io/go-android v0.0.0-20210527143215-3ad22ad02e2e github.com/bitrise-io/go-android/cache -# github.com/bitrise-io/go-steputils v0.0.0-20210923053150-ddc3f70aacd2 +# github.com/bitrise-io/go-steputils v0.0.0-20210924074053-431016d2ea34 github.com/bitrise-io/go-steputils/cache github.com/bitrise-io/go-steputils/command/gems -github.com/bitrise-io/go-steputils/command/ruby github.com/bitrise-io/go-steputils/input +github.com/bitrise-io/go-steputils/ruby github.com/bitrise-io/go-steputils/step github.com/bitrise-io/go-steputils/stepconf github.com/bitrise-io/go-steputils/tools From 5a12583cd16ebef4147a8bc679c4b65c4c30b513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krisztia=CC=81n=20Go=CC=88drei?= Date: Fri, 24 Sep 2021 10:19:45 +0200 Subject: [PATCH 3/5] Update go-android package. --- cache.go | 4 +- go.mod | 2 +- go.sum | 7 +++ .../bitrise-io/go-android/cache/cache.go | 52 ++++++++++--------- .../bitrise-io/go-android/cache/gradle.go | 6 +-- vendor/modules.txt | 2 +- 6 files changed, 43 insertions(+), 30 deletions(-) diff --git a/cache.go b/cache.go index d6ff0dc..76c5b89 100644 --- a/cache.go +++ b/cache.go @@ -8,6 +8,8 @@ import ( "github.com/bitrise-io/bitrise-init/scanners/android" androidCache "github.com/bitrise-io/go-android/cache" "github.com/bitrise-io/go-steputils/cache" + "github.com/bitrise-io/go-utils/command" + "github.com/bitrise-io/go-utils/env" "github.com/bitrise-io/go-utils/log" "github.com/bitrise-io/go-utils/pathutil" ) @@ -79,7 +81,7 @@ func androidDeps(dir string) ([]string, []string, error) { var include []string var exclude []string for _, dir := range scanner.ProjectRoots { - i, e, err := androidCache.NewAndroidGradleCacheItemCollector().Collect(dir, cache.LevelDeps) + i, e, err := androidCache.NewAndroidGradleCacheItemCollector(command.NewFactory(env.NewRepository())).Collect(dir, cache.LevelDeps) if err != nil { return nil, nil, err } diff --git a/go.mod b/go.mod index d7c5ada..dcf9d99 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.12 require ( github.com/bitrise-io/bitrise-init v0.0.0-20210520122036-d213de321eb8 - github.com/bitrise-io/go-android v0.0.0-20210527143215-3ad22ad02e2e + github.com/bitrise-io/go-android v0.0.0-20210913151943-e1ea0b4df36d github.com/bitrise-io/go-steputils v0.0.0-20210924074053-431016d2ea34 github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72 github.com/bitrise-io/go-xcode v0.0.0-20210521101355-fb6a1eb6e05b diff --git a/go.sum b/go.sum index 2a2e7bc..b48a4b7 100644 --- a/go.sum +++ b/go.sum @@ -11,9 +11,12 @@ github.com/bitrise-io/envman v0.0.0-20210517135508-b2b4fe89eac5 h1:3jVXjsejV+1EW github.com/bitrise-io/envman v0.0.0-20210517135508-b2b4fe89eac5/go.mod h1:m8pTp1o3Sw9uzDxb1WRm5IBRnMau2iOvPMSnRCAhQNI= github.com/bitrise-io/go-android v0.0.0-20210527143215-3ad22ad02e2e h1:lkJnz+yXbIqFGpDTdRBBshqxeX0UCndJmEOp0yy2GRQ= github.com/bitrise-io/go-android v0.0.0-20210527143215-3ad22ad02e2e/go.mod h1:gGXmY8hJ1x44AC98TIvZZvxP7o+hs4VI6wgmO4JMfEg= +github.com/bitrise-io/go-android v0.0.0-20210913151943-e1ea0b4df36d h1:F4VCaMk4hZZSwI5MiyBwVnkxmgmvkOz4+uXAacEaRC0= +github.com/bitrise-io/go-android v0.0.0-20210913151943-e1ea0b4df36d/go.mod h1:yTe4i6RfahvAmOChFrS9uCPmJiH0eBEV4jya30v2tTc= github.com/bitrise-io/go-plist v0.0.0-20210301100253-4b1a112ccd10/go.mod h1:pARutiL3kEuRLV3JvswidvfCj+9Y3qMZtji2BDqLFsA= github.com/bitrise-io/go-steputils v0.0.0-20210507072936-92fde382fb33/go.mod h1:YCtb1VETn/rF9tCt9oInhd/cwbt1ETPm+dTlDIfyD+A= github.com/bitrise-io/go-steputils v0.0.0-20210514150206-5b6261447e77/go.mod h1:H0iZjgsAR5NA6pnlD/zKB6AbxEsskq55pwJ9klVmP8w= +github.com/bitrise-io/go-steputils v0.0.0-20210819160244-b3962254d553/go.mod h1:gPr5wQVOi3wZCY1RkMzk/Ij0rmdgEIP0Og84YgHmVSU= github.com/bitrise-io/go-steputils v0.0.0-20210924074053-431016d2ea34 h1:D1SOAAhTfD1+70Yo8VMQNRZT7C0EutHBQiqMYt3BdDE= github.com/bitrise-io/go-steputils v0.0.0-20210924074053-431016d2ea34/go.mod h1:e3iET6YTYpobuCbA5iyvy1pxHUb+qfCDOpeMel0bI6Q= github.com/bitrise-io/go-utils v0.0.0-20210505091801-98b7dc39ee61/go.mod h1:nhdaDQFvaMny1CugVV6KjK92/q97ENo0RuKSW5I4fbA= @@ -22,6 +25,8 @@ github.com/bitrise-io/go-utils v0.0.0-20210506064210-b22e2b7b3ad3/go.mod h1:nhda github.com/bitrise-io/go-utils v0.0.0-20210507100250-37de47dfa6ce/go.mod h1:15EZZf02noI5nWFqXMZEoyb1CyqYRXTMz5Fyu4CWFzI= github.com/bitrise-io/go-utils v0.0.0-20210514083430-4d1fb0330dfe/go.mod h1:DRx7oFuAqk0dbKpAKCqWl0TgrowfJUb/MqYPRscxJOQ= github.com/bitrise-io/go-utils v0.0.0-20210520073355-367fa34178f5/go.mod h1:DRx7oFuAqk0dbKpAKCqWl0TgrowfJUb/MqYPRscxJOQ= +github.com/bitrise-io/go-utils v0.0.0-20210819105546-07a5bda18d68/go.mod h1:UprBoSn6HxcN9G7yGRSOoe9bSZLh7gLl4yA0/iqwYsI= +github.com/bitrise-io/go-utils v0.0.0-20210819143908-bbd923881fab/go.mod h1:UprBoSn6HxcN9G7yGRSOoe9bSZLh7gLl4yA0/iqwYsI= github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72 h1:Eov/ocBE9sfljzLo7C/6GuLUtACWJpY6dRLDhTtJ2L8= github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72/go.mod h1:Vi4MHnaZVL3PVoPPA/Yp6g2pzntkDH8LGiRSY7qw6KQ= github.com/bitrise-io/go-xcode v0.0.0-20210520114025-bdbec53ee59f/go.mod h1:a5IANtAnyazHgNjI6/kwQw5vU/WJo1zQ4Lja9WRUNmA= @@ -99,8 +104,10 @@ golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210819072135-bce67f096156/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-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/vendor/github.com/bitrise-io/go-android/cache/cache.go b/vendor/github.com/bitrise-io/go-android/cache/cache.go index 1a282a0..2396339 100644 --- a/vendor/github.com/bitrise-io/go-android/cache/cache.go +++ b/vendor/github.com/bitrise-io/go-android/cache/cache.go @@ -6,7 +6,6 @@ import ( "io" "io/ioutil" "os" - "os/exec" "path/filepath" "strings" @@ -19,11 +18,12 @@ import ( // AndroidGradleCacheItemCollector ... type AndroidGradleCacheItemCollector struct { + cmdFactory command.Factory } // NewAndroidGradleCacheItemCollector ... -func NewAndroidGradleCacheItemCollector() cache.ItemCollector { - return AndroidGradleCacheItemCollector{} +func NewAndroidGradleCacheItemCollector(cmdFactory command.Factory) cache.ItemCollector { + return AndroidGradleCacheItemCollector{cmdFactory: cmdFactory} } // Collect ... @@ -39,12 +39,12 @@ func (c AndroidGradleCacheItemCollector) Collect(dir string, cacheLevel cache.Le return nil, nil, fmt.Errorf("cache collection skipped: failed to determine project root path") } - includePths, err := collectIncludePaths(homeDir, projectRoot, cacheLevel) + includePths, err := c.collectIncludePaths(homeDir, projectRoot, cacheLevel) if err != nil { return nil, nil, err } - excludePths := collectExcludePaths(homeDir, projectRoot) + excludePths := c.collectExcludePaths(homeDir, projectRoot) return includePths, excludePths, nil } @@ -53,8 +53,8 @@ func (c AndroidGradleCacheItemCollector) Collect(dir string, cacheLevel cache.Le // paths for caching based on the value of cacheLevel. Returns an error if there // was an underlying error that would lead to a corrupted cache file, otherwise // the given path is skipped. -func Collect(projectRoot string, cacheLevel cache.Level) error { - cacheItemCollector := NewAndroidGradleCacheItemCollector() +func Collect(projectRoot string, cacheLevel cache.Level, cmdFactory command.Factory) error { + cacheItemCollector := NewAndroidGradleCacheItemCollector(cmdFactory) includes, excludes, err := cacheItemCollector.Collect(projectRoot, cacheLevel) if err != nil { return err @@ -74,7 +74,7 @@ func Collect(projectRoot string, cacheLevel cache.Level) error { return nil } -func collectIncludePaths(homeDir, projectDir string, cacheLevel cache.Level) ([]string, error) { +func (c AndroidGradleCacheItemCollector) collectIncludePaths(homeDir, projectDir string, cacheLevel cache.Level) ([]string, error) { var includePths []string lockFilePath := filepath.Join(projectDir, "gradle.deps") @@ -93,7 +93,7 @@ func collectIncludePaths(homeDir, projectDir string, cacheLevel cache.Level) ([] return nil } - unmodified, err := prepareUnmodifiedIndicator(path) + unmodified, err := c.prepareUnmodifiedIndicator(path) if err != nil { log.Debugf(err.Error()) unmodified = path @@ -148,21 +148,21 @@ func collectIncludePaths(homeDir, projectDir string, cacheLevel cache.Level) ([] /* If the indicator is version controlled in git and has changes, we create a copy of it with its original content. */ -func prepareUnmodifiedIndicator(indicator string) (unmodified string, err error) { +func (c AndroidGradleCacheItemCollector) prepareUnmodifiedIndicator(indicator string) (unmodified string, err error) { indicatorDir := filepath.Dir(indicator) indicatorFile := filepath.Base(indicator) + opts := command.Opts{Dir: indicatorDir} - cmd := exec.Command("git", "ls-files", "--error-unmatch", indicatorFile) - cmd.Dir = indicatorDir - m := command.NewWithCmd(cmd) - code, err := m.RunAndReturnExitCode() + lsArgs := []string{"ls-files", "--error-unmatch", indicatorFile} + lsCmd := c.cmdFactory.Create("git", lsArgs, &opts) + code, err := lsCmd.RunAndReturnExitCode() if code != 0 { return "", fmt.Errorf("%s is not under git version control", indicator) } - cmd = exec.Command("git", "diff", "-s", "--exit-code", indicatorFile) - cmd.Dir = indicatorDir - m = command.NewWithCmd(cmd) - code, err = m.RunAndReturnExitCode() + + diffArgs := []string{"diff", "-s", "--exit-code", indicatorFile} + diffCmd := c.cmdFactory.Create("git", diffArgs, &opts) + code, err = diffCmd.RunAndReturnExitCode() if code == 0 { return "", fmt.Errorf("%s has not modification compared to HEAD", indicator) } @@ -178,10 +178,14 @@ func prepareUnmodifiedIndicator(indicator string) (unmodified string, err error) } }() - cmd = exec.Command("git", "show", "HEAD:"+indicatorFile) - cmd.Dir = indicatorDir - m = command.NewWithCmd(cmd).SetStdout(file).SetStderr(os.Stderr) - code, err = m.RunAndReturnExitCode() + showArgs := []string{"show", "HEAD:" + indicatorFile} + showOpts := command.Opts{ + Stdout: file, + Stderr: os.Stderr, + Dir: indicatorDir, + } + showCmd := c.cmdFactory.Create("git", showArgs, &showOpts) + code, err = showCmd.RunAndReturnExitCode() if err != nil || code != 0 { return "", err } @@ -207,7 +211,7 @@ func computeMD5String(filePath string) (string, error) { return fmt.Sprintf("%x", h.Sum(nil)), nil } -func collectExcludePaths(homeDir, projectDir string) []string { +func (c AndroidGradleCacheItemCollector) collectExcludePaths(homeDir, projectDir string) []string { excludePths := []string{ "!~/.gradle/daemon/*/daemon-*.out.log", // excludes Gradle daemon logs, like: ~/.gradle/daemon/6.1.1/daemon-3122.out.log "~/.android/build-cache/**", @@ -225,7 +229,7 @@ func collectExcludePaths(homeDir, projectDir string) []string { "!*.apk", } - ver, err := projectGradleVersion(projectDir) + ver, err := projectGradleVersion(projectDir, c.cmdFactory) if err != nil { log.Warnf("Failed to get project gradle version: %s", err) return nil diff --git a/vendor/github.com/bitrise-io/go-android/cache/gradle.go b/vendor/github.com/bitrise-io/go-android/cache/gradle.go index f34d3f7..4a72392 100644 --- a/vendor/github.com/bitrise-io/go-android/cache/gradle.go +++ b/vendor/github.com/bitrise-io/go-android/cache/gradle.go @@ -38,7 +38,7 @@ func parseGradleVersion(out string) (string, error) { return matches[1], nil } -func projectGradleVersion(projectPth string) (string, error) { +func projectGradleVersion(projectPth string, cmdFactory command.Factory) (string, error) { gradlewPth := filepath.Join(projectPth, "gradlew") exist, err := pathutil.IsPathExists(gradlewPth) if err != nil { @@ -48,8 +48,8 @@ func projectGradleVersion(projectPth string) (string, error) { return "", fmt.Errorf("no gradlew found at: %s", gradlewPth) } - versionCmd := command.New("./gradlew", "-version") - versionCmd.SetDir(filepath.Dir(gradlewPth)) + versionCmdOpts := command.Opts{Dir: filepath.Dir(gradlewPth)} + versionCmd := cmdFactory.Create("./gradlew", []string{"-version"}, &versionCmdOpts) out, err := versionCmd.RunAndReturnTrimmedCombinedOutput() if err != nil { if errorutil.IsExitStatusError(err) { diff --git a/vendor/modules.txt b/vendor/modules.txt index 1811f89..2c80ee7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -10,7 +10,7 @@ github.com/bitrise-io/bitrise-init/steps github.com/bitrise-io/bitrise-init/utility # github.com/bitrise-io/envman v0.0.0-20210517135508-b2b4fe89eac5 github.com/bitrise-io/envman/models -# github.com/bitrise-io/go-android v0.0.0-20210527143215-3ad22ad02e2e +# github.com/bitrise-io/go-android v0.0.0-20210913151943-e1ea0b4df36d github.com/bitrise-io/go-android/cache # github.com/bitrise-io/go-steputils v0.0.0-20210924074053-431016d2ea34 github.com/bitrise-io/go-steputils/cache From 43abdacd73fbc5caee5a41c4e1c6dd361fcc27ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krisztia=CC=81n=20Go=CC=88drei?= Date: Fri, 24 Sep 2021 10:44:06 +0200 Subject: [PATCH 4/5] Typo fix. --- main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 929c42b..457bc8a 100644 --- a/main.go +++ b/main.go @@ -265,8 +265,8 @@ func main() { log.Infof("Install bundler") // install bundler with `gem install bundler [-v version]` - // in some configurations, the command "bunder _1.2.3_" can return 'Command not found', installing bundler solves this - cmds := factory.CreateGemInstall("bunder", gemVersions.bundler.Version, false, true, &command.Opts{ + // in some configurations, the command "bundler _1.2.3_" can return 'Command not found', installing bundler solves this + cmds := factory.CreateGemInstall("bundler", gemVersions.bundler.Version, false, true, &command.Opts{ Stdout: os.Stdout, Stderr: os.Stderr, Dir: workDir, From ce986a647de9eb83f2eff78fb7db423f2ec72ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krisztia=CC=81n=20Go=CC=88drei?= Date: Fri, 24 Sep 2021 13:43:54 +0200 Subject: [PATCH 5/5] Update to the master version of go-utils and go-steputils. --- go.mod | 4 ++-- go.sum | 10 ++++------ .../bitrise-io/go-steputils/ruby/command.go | 16 ++++++++-------- vendor/modules.txt | 4 ++-- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index dcf9d99..6f3d354 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,8 @@ go 1.12 require ( github.com/bitrise-io/bitrise-init v0.0.0-20210520122036-d213de321eb8 github.com/bitrise-io/go-android v0.0.0-20210913151943-e1ea0b4df36d - github.com/bitrise-io/go-steputils v0.0.0-20210924074053-431016d2ea34 - github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72 + github.com/bitrise-io/go-steputils v0.0.0-20210924114124-851d30b88892 + github.com/bitrise-io/go-utils v0.0.0-20210924090918-3e7a04d0da9d github.com/bitrise-io/go-xcode v0.0.0-20210521101355-fb6a1eb6e05b github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 ) diff --git a/go.sum b/go.sum index b48a4b7..3cad58d 100644 --- a/go.sum +++ b/go.sum @@ -9,16 +9,14 @@ github.com/bitrise-io/colorstring v0.0.0-20180614154802-a8cd70115192/go.mod h1:C github.com/bitrise-io/envman v0.0.0-20200512105748-919e33f391ee/go.mod h1:m8pTp1o3Sw9uzDxb1WRm5IBRnMau2iOvPMSnRCAhQNI= github.com/bitrise-io/envman v0.0.0-20210517135508-b2b4fe89eac5 h1:3jVXjsejV+1EW9Sp7ef+sMinD0J3HFsPgh4Du6ctqZc= github.com/bitrise-io/envman v0.0.0-20210517135508-b2b4fe89eac5/go.mod h1:m8pTp1o3Sw9uzDxb1WRm5IBRnMau2iOvPMSnRCAhQNI= -github.com/bitrise-io/go-android v0.0.0-20210527143215-3ad22ad02e2e h1:lkJnz+yXbIqFGpDTdRBBshqxeX0UCndJmEOp0yy2GRQ= -github.com/bitrise-io/go-android v0.0.0-20210527143215-3ad22ad02e2e/go.mod h1:gGXmY8hJ1x44AC98TIvZZvxP7o+hs4VI6wgmO4JMfEg= github.com/bitrise-io/go-android v0.0.0-20210913151943-e1ea0b4df36d h1:F4VCaMk4hZZSwI5MiyBwVnkxmgmvkOz4+uXAacEaRC0= github.com/bitrise-io/go-android v0.0.0-20210913151943-e1ea0b4df36d/go.mod h1:yTe4i6RfahvAmOChFrS9uCPmJiH0eBEV4jya30v2tTc= github.com/bitrise-io/go-plist v0.0.0-20210301100253-4b1a112ccd10/go.mod h1:pARutiL3kEuRLV3JvswidvfCj+9Y3qMZtji2BDqLFsA= github.com/bitrise-io/go-steputils v0.0.0-20210507072936-92fde382fb33/go.mod h1:YCtb1VETn/rF9tCt9oInhd/cwbt1ETPm+dTlDIfyD+A= github.com/bitrise-io/go-steputils v0.0.0-20210514150206-5b6261447e77/go.mod h1:H0iZjgsAR5NA6pnlD/zKB6AbxEsskq55pwJ9klVmP8w= github.com/bitrise-io/go-steputils v0.0.0-20210819160244-b3962254d553/go.mod h1:gPr5wQVOi3wZCY1RkMzk/Ij0rmdgEIP0Og84YgHmVSU= -github.com/bitrise-io/go-steputils v0.0.0-20210924074053-431016d2ea34 h1:D1SOAAhTfD1+70Yo8VMQNRZT7C0EutHBQiqMYt3BdDE= -github.com/bitrise-io/go-steputils v0.0.0-20210924074053-431016d2ea34/go.mod h1:e3iET6YTYpobuCbA5iyvy1pxHUb+qfCDOpeMel0bI6Q= +github.com/bitrise-io/go-steputils v0.0.0-20210924114124-851d30b88892 h1:aD5jTvdf5zIngQ5HeR7Idteae4yaXLqJGn8PE4k2xtI= +github.com/bitrise-io/go-steputils v0.0.0-20210924114124-851d30b88892/go.mod h1:6Y7Dl40gwgW9YG1RAWcjFBk1u9uotuix8g2IkVTXK34= github.com/bitrise-io/go-utils v0.0.0-20210505091801-98b7dc39ee61/go.mod h1:nhdaDQFvaMny1CugVV6KjK92/q97ENo0RuKSW5I4fbA= github.com/bitrise-io/go-utils v0.0.0-20210505121718-07411d72e36e/go.mod h1:nhdaDQFvaMny1CugVV6KjK92/q97ENo0RuKSW5I4fbA= github.com/bitrise-io/go-utils v0.0.0-20210506064210-b22e2b7b3ad3/go.mod h1:nhdaDQFvaMny1CugVV6KjK92/q97ENo0RuKSW5I4fbA= @@ -27,8 +25,8 @@ github.com/bitrise-io/go-utils v0.0.0-20210514083430-4d1fb0330dfe/go.mod h1:DRx7 github.com/bitrise-io/go-utils v0.0.0-20210520073355-367fa34178f5/go.mod h1:DRx7oFuAqk0dbKpAKCqWl0TgrowfJUb/MqYPRscxJOQ= github.com/bitrise-io/go-utils v0.0.0-20210819105546-07a5bda18d68/go.mod h1:UprBoSn6HxcN9G7yGRSOoe9bSZLh7gLl4yA0/iqwYsI= github.com/bitrise-io/go-utils v0.0.0-20210819143908-bbd923881fab/go.mod h1:UprBoSn6HxcN9G7yGRSOoe9bSZLh7gLl4yA0/iqwYsI= -github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72 h1:Eov/ocBE9sfljzLo7C/6GuLUtACWJpY6dRLDhTtJ2L8= -github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72/go.mod h1:Vi4MHnaZVL3PVoPPA/Yp6g2pzntkDH8LGiRSY7qw6KQ= +github.com/bitrise-io/go-utils v0.0.0-20210924090918-3e7a04d0da9d h1:jU5wvShTLKSo2gYlIBoXONS2MRRL8UwiPOSqi88JF2k= +github.com/bitrise-io/go-utils v0.0.0-20210924090918-3e7a04d0da9d/go.mod h1:Vi4MHnaZVL3PVoPPA/Yp6g2pzntkDH8LGiRSY7qw6KQ= github.com/bitrise-io/go-xcode v0.0.0-20210520114025-bdbec53ee59f/go.mod h1:a5IANtAnyazHgNjI6/kwQw5vU/WJo1zQ4Lja9WRUNmA= github.com/bitrise-io/go-xcode v0.0.0-20210521101355-fb6a1eb6e05b h1:JyTlzvdOBOxtYZ7aZVCog2dZUv8LgA8UftT+TpVWtZY= github.com/bitrise-io/go-xcode v0.0.0-20210521101355-fb6a1eb6e05b/go.mod h1:6Nv5RAsAVS745xN5IihUExVmCA9n9f7s/DSVow4hXrI= diff --git a/vendor/github.com/bitrise-io/go-steputils/ruby/command.go b/vendor/github.com/bitrise-io/go-steputils/ruby/command.go index 8f70b65..b7c7e15 100644 --- a/vendor/github.com/bitrise-io/go-steputils/ruby/command.go +++ b/vendor/github.com/bitrise-io/go-steputils/ruby/command.go @@ -105,33 +105,33 @@ func gemInstallCommandArgs(gem, version string, enablePrerelease, force bool) [] return slice } -func sudoNeeded(installType InstallType, slice ...string) bool { +func sudoNeeded(installType InstallType, command ...string) bool { if installType != SystemRuby { return false } - if len(slice) < 2 { + if len(command) < 2 { return false } - name := slice[0] + name := command[0] if name == "bundle" { - cmd := slice[1] + cmd := command[1] /* bundle command can contain version: `bundle _2.0.1_ install` */ const bundleVersionMarker = "_" - if strings.HasPrefix(slice[1], bundleVersionMarker) && strings.HasSuffix(slice[1], bundleVersionMarker) { - if len(slice) < 3 { + if strings.HasPrefix(command[1], bundleVersionMarker) && strings.HasSuffix(command[1], bundleVersionMarker) { + if len(command) < 3 { return false } - cmd = slice[2] + cmd = command[2] } return cmd == "install" || cmd == "update" } else if name == "gem" { - cmd := slice[1] + cmd := command[1] return cmd == "install" || cmd == "uninstall" } diff --git a/vendor/modules.txt b/vendor/modules.txt index 2c80ee7..04b47a2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -12,7 +12,7 @@ github.com/bitrise-io/bitrise-init/utility github.com/bitrise-io/envman/models # github.com/bitrise-io/go-android v0.0.0-20210913151943-e1ea0b4df36d github.com/bitrise-io/go-android/cache -# github.com/bitrise-io/go-steputils v0.0.0-20210924074053-431016d2ea34 +# github.com/bitrise-io/go-steputils v0.0.0-20210924114124-851d30b88892 github.com/bitrise-io/go-steputils/cache github.com/bitrise-io/go-steputils/command/gems github.com/bitrise-io/go-steputils/input @@ -20,7 +20,7 @@ github.com/bitrise-io/go-steputils/ruby github.com/bitrise-io/go-steputils/step github.com/bitrise-io/go-steputils/stepconf github.com/bitrise-io/go-steputils/tools -# github.com/bitrise-io/go-utils v0.0.0-20210922201414-6d7c12191c72 +# github.com/bitrise-io/go-utils v0.0.0-20210924090918-3e7a04d0da9d github.com/bitrise-io/go-utils/colorstring github.com/bitrise-io/go-utils/command github.com/bitrise-io/go-utils/env