From 6ed845c7b6d8b14d4496a33d543b4614d95d0ae9 Mon Sep 17 00:00:00 2001 From: lpusok <7979773+lpusok@users.noreply.github.com> Date: Thu, 24 Jun 2021 15:41:44 +0200 Subject: [PATCH] Update expected SDK layout (#75) * Using NewDefaultModel to initialize SDK * Update NDK lookup path --- go.mod | 8 +- go.sum | 30 +- main.go | 78 +-- step.yml | 7 - .../bitrise-io/go-android/sdk/sdk.go | 99 ++- .../go-android/sdkmanager/sdkmanager.go | 43 +- .../go-steputils/input/fileprovider.go | 89 --- .../bitrise-io/go-steputils/input/input.go | 75 --- .../go-steputils/stepconf/stepconf.go | 572 ++++++++++++++++++ .../go-utils/parseutil/parseutil.go | 95 +++ .../bitrise-io/go-utils/pathutil/glob.go | 13 + .../go-utils/pathutil/path_filter.go | 143 +++++ .../bitrise-io/go-utils/pathutil/pathutil.go | 52 ++ .../go-utils/pathutil/sortable_path.go | 88 +++ .../bitrise-io/go-utils/pointers/pointers.go | 98 +++ .../hashicorp/go-retryablehttp/.travis.yml | 12 + .../hashicorp/go-retryablehttp/README.md | 1 - .../hashicorp/go-retryablehttp/client.go | 157 ++--- .../go-retryablehttp/roundtripper.go | 11 +- vendor/github.com/pkg/errors/.gitignore | 24 - vendor/github.com/pkg/errors/.travis.yml | 10 - vendor/github.com/pkg/errors/LICENSE | 23 - vendor/github.com/pkg/errors/Makefile | 44 -- vendor/github.com/pkg/errors/README.md | 59 -- vendor/github.com/pkg/errors/appveyor.yml | 32 - vendor/github.com/pkg/errors/errors.go | 288 --------- vendor/github.com/pkg/errors/go113.go | 38 -- vendor/github.com/pkg/errors/stack.go | 177 ------ vendor/modules.txt | 16 +- 29 files changed, 1286 insertions(+), 1096 deletions(-) delete mode 100644 vendor/github.com/bitrise-io/go-steputils/input/fileprovider.go delete mode 100644 vendor/github.com/bitrise-io/go-steputils/input/input.go create mode 100644 vendor/github.com/bitrise-io/go-steputils/stepconf/stepconf.go create mode 100644 vendor/github.com/bitrise-io/go-utils/parseutil/parseutil.go create mode 100644 vendor/github.com/bitrise-io/go-utils/pathutil/glob.go create mode 100644 vendor/github.com/bitrise-io/go-utils/pathutil/path_filter.go create mode 100644 vendor/github.com/bitrise-io/go-utils/pathutil/sortable_path.go create mode 100644 vendor/github.com/bitrise-io/go-utils/pointers/pointers.go create mode 100644 vendor/github.com/hashicorp/go-retryablehttp/.travis.yml delete mode 100644 vendor/github.com/pkg/errors/.gitignore delete mode 100644 vendor/github.com/pkg/errors/.travis.yml delete mode 100644 vendor/github.com/pkg/errors/LICENSE delete mode 100644 vendor/github.com/pkg/errors/Makefile delete mode 100644 vendor/github.com/pkg/errors/README.md delete mode 100644 vendor/github.com/pkg/errors/appveyor.yml delete mode 100644 vendor/github.com/pkg/errors/errors.go delete mode 100644 vendor/github.com/pkg/errors/go113.go delete mode 100644 vendor/github.com/pkg/errors/stack.go diff --git a/go.mod b/go.mod index 5eb5bef..14b512b 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,9 @@ module github.com/bitrise-steplib/steps-install-missing-android-tools go 1.16 require ( - github.com/bitrise-io/go-android v0.0.0-20210301151701-791fb4b5216b - github.com/bitrise-io/go-steputils v0.0.0-20210507072936-92fde382fb33 - github.com/bitrise-io/go-utils v0.0.0-20210507100250-37de47dfa6ce + 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/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-retryablehttp v0.7.0 // indirect github.com/hashicorp/go-version v1.3.0 - github.com/pkg/errors v0.9.1 ) diff --git a/go.sum b/go.sum index e0786c5..1bcfb65 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,11 @@ -github.com/bitrise-io/go-android v0.0.0-20210301151701-791fb4b5216b h1:lsdgaoWqwLWa7ohHRBblY2lAafvK+m9bKAWm8ZCjNo8= -github.com/bitrise-io/go-android v0.0.0-20210301151701-791fb4b5216b/go.mod h1:ZMsq2ivTUD2q50BYEUGjd68S9CXYqDYqFds43rnx84g= -github.com/bitrise-io/go-steputils v0.0.0-20210507072936-92fde382fb33 h1:4QpxkX2oNefww7k76ZUD4C7unfP4c8H0c0QP7SdfrTQ= -github.com/bitrise-io/go-steputils v0.0.0-20210507072936-92fde382fb33/go.mod h1:YCtb1VETn/rF9tCt9oInhd/cwbt1ETPm+dTlDIfyD+A= -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 h1:z9t020cBpCZdwO4teTXbj7XyLwQDvMcMmfnhHe36mWc= +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-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-utils v0.0.0-20210507100250-37de47dfa6ce/go.mod h1:15EZZf02noI5nWFqXMZEoyb1CyqYRXTMz5Fyu4CWFzI= +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/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -13,17 +14,14 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 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= github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw= github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As= github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -32,14 +30,24 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= 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= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/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= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 55977ae..88f82dc 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/bitrise-io/go-android/sdk" - "github.com/bitrise-io/go-steputils/input" + "github.com/bitrise-io/go-steputils/stepconf" "github.com/bitrise-io/go-steputils/tools" "github.com/bitrise-io/go-utils/command" "github.com/bitrise-io/go-utils/fileutil" @@ -17,50 +17,19 @@ import ( "github.com/bitrise-io/go-utils/pathutil" "github.com/bitrise-steplib/steps-install-missing-android-tools/androidcomponents" "github.com/hashicorp/go-version" - "github.com/pkg/errors" ) const platformDirName = "platforms" const androidNDKHome = "ANDROID_NDK_HOME" -// ConfigsModel ... -type ConfigsModel struct { - GradlewPath string - AndroidHome string - NDKRevision string +// Config ... +type Config struct { + GradlewPath string `env:"gradlew_path,file"` + AndroidHome string `env:"ANDROID_HOME"` + AndroidSDKRoot string `env:"ANDROID_SDK_ROOT"` + NDKRevision string `env:"ndk_revision"` } -func createConfigsModelFromEnvs() ConfigsModel { - return ConfigsModel{ - GradlewPath: os.Getenv("gradlew_path"), - AndroidHome: os.Getenv("ANDROID_HOME"), - NDKRevision: os.Getenv("ndk_revision"), - } -} - -func (configs ConfigsModel) print() { - log.Infof("Configs:") - log.Printf("- GradlewPath: %s", configs.GradlewPath) - log.Printf("- AndroidHome: %s", configs.AndroidHome) - log.Printf("- NDKRevision: %s", configs.NDKRevision) -} - -func (configs ConfigsModel) validate() error { - if err := input.ValidateIfPathExists(configs.GradlewPath); err != nil { - return errors.New("Issue with input GradlewPath: " + err.Error()) - } - - if err := input.ValidateIfNotEmpty(configs.AndroidHome); err != nil { - return errors.New("Issue with input AndroidHome: " + err.Error()) - } - - return nil -} - -// ----------------------- -// --- Functions -// ----------------------- - func failf(format string, v ...interface{}) { log.Errorf(format, v...) os.Exit(1) @@ -101,6 +70,9 @@ func ndkHome() string { if v := os.Getenv("ANDROID_HOME"); v != "" { return filepath.Join(v, "android-ndk-bundle") } + if v := os.Getenv("ANDROID_SDK_ROOT"); v != "" { + return filepath.Join(v, "android-ndk-bundle") + } if v := os.Getenv("HOME"); v != "" { return filepath.Join(v, "android-ndk-bundle") } @@ -196,35 +168,30 @@ func updateNDKPath(path string) error { return nil } -// ----------------------- -// --- Main -// ----------------------- - func main() { // Input validation - configs := createConfigsModelFromEnvs() + var config Config + if err := stepconf.Parse(&config); err != nil { + log.Errorf("%s", err) + } fmt.Println() - configs.print() - - if err := configs.validate(); err != nil { - failf(err.Error()) - } + stepconf.Print(config) fmt.Println() log.Infof("Preparation") // Set executable permission for gradlew log.Printf("Set executable permission for gradlew") - if err := os.Chmod(configs.GradlewPath, 0770); err != nil { + if err := os.Chmod(config.GradlewPath, 0770); err != nil { failf("Failed to set executable permission for gradlew, error: %s", err) } fmt.Println() - if configs.NDKRevision != "" { + if config.NDKRevision != "" { log.Infof("Installing NDK bundle") - if err := updateNDK(configs.NDKRevision); err != nil { + if err := updateNDK(config.NDKRevision); err != nil { failf("Failed to download NDK bundle, error: %s", err) } } else { @@ -242,9 +209,12 @@ func main() { // Initialize Android SDK log.Printf("Initialize Android SDK") - androidSdk, err := sdk.New(configs.AndroidHome) + androidSdk, err := sdk.NewDefaultModel(sdk.Environment{ + AndroidHome: config.AndroidHome, + AndroidSDKRoot: config.AndroidSDKRoot, + }) if err != nil { - failf("Failed to initialize Android SDK, error: %s", err) + failf("Failed to initialize Android SDK: %s", err) } androidcomponents.SetLogger(log.NewDefaultLogger(false)) @@ -260,7 +230,7 @@ func main() { fmt.Println() log.Infof("Ensure required Android SDK components") - if err := androidcomponents.Ensure(androidSdk, configs.GradlewPath); err != nil { + if err := androidcomponents.Ensure(androidSdk, config.GradlewPath); err != nil { failf("Failed to ensure android components, error: %s", err) } diff --git a/step.yml b/step.yml index 3af9147..9381716 100755 --- a/step.yml +++ b/step.yml @@ -38,15 +38,8 @@ project_type_tags: - react-native type_tags: - installer -is_requires_admin_user: false is_always_run: false is_skippable: false -deps: - brew: - - name: go - apt_get: - - name: golang - bin_name: go toolkit: go: package_name: github.com/bitrise-steplib/steps-install-missing-android-tools diff --git a/vendor/github.com/bitrise-io/go-android/sdk/sdk.go b/vendor/github.com/bitrise-io/go-android/sdk/sdk.go index f59920e..5698b88 100644 --- a/vendor/github.com/bitrise-io/go-android/sdk/sdk.go +++ b/vendor/github.com/bitrise-io/go-android/sdk/sdk.go @@ -3,6 +3,7 @@ package sdk import ( "errors" "fmt" + "os" "path/filepath" "strings" @@ -15,25 +16,76 @@ type Model struct { androidHome string } +// Environment is used to pass in environment variables used to locate Android SDK +type Environment struct { + AndroidHome string // ANDROID_HOME + AndroidSDKRoot string // ANDROID_SDK_ROOT +} + +// NewEnvironment gets needed environment variables +func NewEnvironment() *Environment { + return &Environment{ + AndroidHome: os.Getenv("ANDROID_HOME"), + AndroidSDKRoot: os.Getenv("ANDROID_SDK_ROOT"), + } +} + // AndroidSdkInterface ... type AndroidSdkInterface interface { GetAndroidHome() string + CmdlineToolsPath() (string, error) } -// New ... +// New creates a Model with a supplied Android SDK path func New(androidHome string) (*Model, error) { - evaluatedAndroidHome, err := filepath.EvalSymlinks(androidHome) + evaluatedSDKRoot, err := validateAndroidSDKRoot(androidHome) if err != nil { return nil, err } - if exist, err := pathutil.IsDirExists(evaluatedAndroidHome); err != nil { - return nil, err + return &Model{androidHome: evaluatedSDKRoot}, nil +} + +// NewDefaultModel locates Android SDK based on environement variables +func NewDefaultModel(envs Environment) (*Model, error) { + // https://developer.android.com/studio/command-line/variables#envar + // Sets the path to the SDK installation directory. + // ANDROID_HOME, which also points to the SDK installation directory, is deprecated. + // If you continue to use it, the following rules apply: + // If ANDROID_HOME is defined and contains a valid SDK installation, its value is used instead of the value in ANDROID_SDK_ROOT. + // If ANDROID_HOME is not defined, the value in ANDROID_SDK_ROOT is used. + var warnings []string + for _, SDKdir := range []string{envs.AndroidHome, envs.AndroidSDKRoot} { + if SDKdir == "" { + warnings = append(warnings, "environment variable is unset or empty") + continue + } + + evaluatedSDKRoot, err := validateAndroidSDKRoot(SDKdir) + if err != nil { + warnings = append(warnings, err.Error()) + continue + } + + return &Model{androidHome: evaluatedSDKRoot}, nil + } + + return nil, fmt.Errorf("could not locate Android SDK root directory: %s", warnings) +} + +func validateAndroidSDKRoot(androidSDKRoot string) (string, error) { + evaluatedSDKRoot, err := filepath.EvalSymlinks(androidSDKRoot) + if err != nil { + return "", err + } + + if exist, err := pathutil.IsDirExists(evaluatedSDKRoot); err != nil { + return "", err } else if !exist { - return nil, fmt.Errorf("android home not exists at: %s", evaluatedAndroidHome) + return "", fmt.Errorf("(%s) is not a valid Android SDK root", evaluatedSDKRoot) } - return &Model{androidHome: evaluatedAndroidHome}, nil + return evaluatedSDKRoot, nil } // GetAndroidHome ... @@ -87,3 +139,38 @@ func (model *Model) LatestBuildToolPath(name string) (string, error) { return pth, nil } + +// CmdlineToolsPath locates the command-line tools directory +func (model *Model) CmdlineToolsPath() (string, error) { + toolPaths := []string{ + filepath.Join(model.GetAndroidHome(), "cmdline-tools", "latest", "bin"), + filepath.Join(model.GetAndroidHome(), "cmdline-tools", "*", "bin"), + filepath.Join(model.GetAndroidHome(), "tools", "bin"), + filepath.Join(model.GetAndroidHome(), "tools"), // legacy + } + + var warnings []string + for _, dirPattern := range toolPaths { + matches, err := filepath.Glob(dirPattern) + if err != nil { + return "", fmt.Errorf("failed to locate Android command-line tools directory, invalid patterns specified (%s): %s", toolPaths, err) + } + + if len(matches) == 0 { + continue + } + + sdkmanagerPath := matches[0] + if exists, err := pathutil.IsDirExists(sdkmanagerPath); err != nil { + warnings = append(warnings, fmt.Sprintf("failed to validate path (%s): %v", sdkmanagerPath, err)) + continue + } else if !exists { + warnings = append(warnings, "path (%s) does not exist or it is not a directory") + continue + } + + return sdkmanagerPath, nil + } + + return "", fmt.Errorf("failed to locate Android command-line tools directory on paths (%s), warnings: %s", toolPaths, warnings) +} diff --git a/vendor/github.com/bitrise-io/go-android/sdkmanager/sdkmanager.go b/vendor/github.com/bitrise-io/go-android/sdkmanager/sdkmanager.go index deb9b77..5b2d9f5 100644 --- a/vendor/github.com/bitrise-io/go-android/sdkmanager/sdkmanager.go +++ b/vendor/github.com/bitrise-io/go-android/sdkmanager/sdkmanager.go @@ -4,10 +4,10 @@ import ( "fmt" "path/filepath" - "github.com/bitrise-io/go-utils/command" - "github.com/bitrise-io/go-utils/pathutil" "github.com/bitrise-io/go-android/sdk" "github.com/bitrise-io/go-android/sdkcomponent" + "github.com/bitrise-io/go-utils/command" + "github.com/bitrise-io/go-utils/pathutil" ) // Model ... @@ -17,34 +17,35 @@ type Model struct { binPth string } -// IsLegacySDKManager ... -func IsLegacySDKManager(androidHome string) (bool, error) { - exist, err := pathutil.IsPathExists(filepath.Join(androidHome, "tools", "bin", "sdkmanager")) - return !exist, err -} - // New ... func New(sdk sdk.AndroidSdkInterface) (*Model, error) { - binPth := filepath.Join(sdk.GetAndroidHome(), "tools", "bin", "sdkmanager") - - legacy, err := IsLegacySDKManager(sdk.GetAndroidHome()) + cmdlineToolsPath, err := sdk.CmdlineToolsPath() if err != nil { return nil, err - } else if legacy { - binPth = filepath.Join(sdk.GetAndroidHome(), "tools", "android") } - if exist, err := pathutil.IsPathExists(binPth); err != nil { + sdkmanagerPath := filepath.Join(cmdlineToolsPath, "sdkmanager") + if exist, err := pathutil.IsPathExists(sdkmanagerPath); err != nil { + return nil, err + } else if exist { + return &Model{ + androidHome: sdk.GetAndroidHome(), + binPth: sdkmanagerPath, + }, nil + } + + legacySdkmanagerPath := filepath.Join(cmdlineToolsPath, "android") + if exist, err := pathutil.IsPathExists(legacySdkmanagerPath); err != nil { return nil, err - } else if !exist { - return nil, fmt.Errorf("no sdk manager tool found at: %s", binPth) + } else if exist { + return &Model{ + androidHome: sdk.GetAndroidHome(), + legacy: true, + binPth: legacySdkmanagerPath, + }, nil } - return &Model{ - androidHome: sdk.GetAndroidHome(), - legacy: legacy, - binPth: binPth, - }, nil + return nil, fmt.Errorf("no sdkmanager tool found at: %s", sdkmanagerPath) } // IsLegacySDK ... diff --git a/vendor/github.com/bitrise-io/go-steputils/input/fileprovider.go b/vendor/github.com/bitrise-io/go-steputils/input/fileprovider.go deleted file mode 100644 index b8528e6..0000000 --- a/vendor/github.com/bitrise-io/go-steputils/input/fileprovider.go +++ /dev/null @@ -1,89 +0,0 @@ -package input - -import ( - "net/url" - "path" - "path/filepath" - "strings" - - "github.com/bitrise-io/go-utils/pathutil" -) - -const ( - fileSchema = "file://" -) - -// FileDownloader .. -type FileDownloader interface { - Get(destination, source string) error -} - -// FileProvider supports retrieving the local path to a file either provided -// as a local path using `file://` scheme -// or downloading the file to a temporary location and return the path to it. -type FileProvider struct { - filedownloader FileDownloader -} - -// NewFileProvider ... -func NewFileProvider(filedownloader FileDownloader) FileProvider { - return FileProvider{ - filedownloader: filedownloader, - } -} - -// LocalPath ... -func (fileProvider FileProvider) LocalPath(path string) (string, error) { - - var localPath string - if strings.HasPrefix(path, fileSchema) { - trimmedPath, err := fileProvider.trimmedFilePath(path) - if err != nil { - return "", err - } - localPath = trimmedPath - } else { - downloadedPath, err := fileProvider.downloadFile(path) - if err != nil { - return "", err - } - localPath = downloadedPath - } - - return localPath, nil -} - -// Removes file:// from the begining of the path -func (fileProvider FileProvider) trimmedFilePath(path string) (string, error) { - pth := strings.TrimPrefix(path, fileSchema) - return pathutil.AbsPath(pth) -} - -func (fileProvider FileProvider) downloadFile(url string) (string, error) { - tmpDir, err := pathutil.NormalizedOSTempDirPath("FileProviderprovider") - if err != nil { - return "", err - } - - fileName, err := fileProvider.fileNameFromPathURL(url) - if err != nil { - return "", err - } - localPath := path.Join(tmpDir, fileName) - if err := fileProvider.filedownloader.Get(localPath, url); err != nil { - return "", err - } - - return localPath, nil -} - -// Returns the file's name from a URL that starts with -// `http://` or `https://` -func (fileProvider FileProvider) fileNameFromPathURL(urlPath string) (string, error) { - url, err := url.Parse(urlPath) - if err != nil { - return "", err - } - - return filepath.Base(url.Path), nil -} diff --git a/vendor/github.com/bitrise-io/go-steputils/input/input.go b/vendor/github.com/bitrise-io/go-steputils/input/input.go deleted file mode 100644 index 9cf4a29..0000000 --- a/vendor/github.com/bitrise-io/go-steputils/input/input.go +++ /dev/null @@ -1,75 +0,0 @@ -package input - -import ( - "fmt" - "strconv" - - "github.com/bitrise-io/go-utils/pathutil" -) - -// ValidateIfNotEmpty ... -func ValidateIfNotEmpty(input string) error { - if input == "" { - return fmt.Errorf("parameter not specified") - } - return nil -} - -// ValidateWithOptions ... -func ValidateWithOptions(value string, options ...string) error { - if err := ValidateIfNotEmpty(value); err != nil { - return err - } - for _, option := range options { - if option == value { - return nil - } - } - return fmt.Errorf("invalid parameter: %s, available: %v", value, options) -} - -// ValidateIfPathExists ... -func ValidateIfPathExists(input string) error { - if err := ValidateIfNotEmpty(input); err != nil { - return err - } - if exist, err := pathutil.IsPathExists(input); err != nil { - return fmt.Errorf("failed to check if path exist at: %s, error: %s", input, err) - } else if !exist { - return fmt.Errorf("path not exist at: %s", input) - } - return nil -} - -// ValidateIfDirExists ... -func ValidateIfDirExists(input string) error { - if err := ValidateIfNotEmpty(input); err != nil { - return err - } - if exist, err := pathutil.IsDirExists(input); err != nil { - return fmt.Errorf("failed to check if dir exist at: %s, error: %s", input, err) - } else if !exist { - return fmt.Errorf("dir not exist at: %s", input) - } - return nil -} - -// ValidateInt ... -func ValidateInt(input string) (int, error) { - if input == "" { - return 0, nil - } - num, err := strconv.Atoi(input) - if err != nil { - return 0, fmt.Errorf("can't convert to int, error: %v", err) - } - return num, nil -} - -// SecureInput ... -func SecureInput(input string) string { - if input != "" { - return "***" - } - return "" -} diff --git a/vendor/github.com/bitrise-io/go-steputils/stepconf/stepconf.go b/vendor/github.com/bitrise-io/go-steputils/stepconf/stepconf.go new file mode 100644 index 0000000..da06ab3 --- /dev/null +++ b/vendor/github.com/bitrise-io/go-steputils/stepconf/stepconf.go @@ -0,0 +1,572 @@ +package stepconf + +import ( + "errors" + "fmt" + "os" + "reflect" + "regexp" + "strconv" + "strings" + + "github.com/bitrise-io/go-utils/colorstring" + "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, + } +} + +// Parse ... +func (p EnvParser) Parse(conf interface{}) error { + c := reflect.ValueOf(conf) + if c.Kind() != reflect.Ptr { + return ErrNotStructPtr + } + c = c.Elem() + if c.Kind() != reflect.Struct { + return ErrNotStructPtr + } + t := c.Type() + + var errs []*ParseError + for i := 0; i < c.NumField(); i++ { + tag, ok := t.Field(i).Tag.Lookup("env") + if !ok { + continue + } + key, constraint := parseTag(tag) + value := p.envProvider.Getenv(key) + + if err := setField(c.Field(i), value, constraint); err != nil { + errs = append(errs, &ParseError{t.Field(i).Name, value, err}) + } + } + if len(errs) > 0 { + errorString := "failed to parse config:" + for _, err := range errs { + errorString += fmt.Sprintf("\n- %s", err) + } + + errorString += fmt.Sprintf("\n\n%s", toString(conf)) + return errors.New(errorString) + } + + return nil +} + +var defaultEnvParser *EnvParser + +func getDefaultEnvParser() EnvParser { + if defaultEnvParser == nil { + parser := NewDefaultEnvParser() + defaultEnvParser = &parser + } + 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) +} + +func setField(field reflect.Value, value, constraint string) error { + if err := validateConstraint(value, constraint); err != nil { + return err + } + + if value == "" { + return nil + } + + if field.Kind() == reflect.Ptr { + // If field is a pointer type, then set its value to be a pointer to a new zero value, matching field underlying type. + var dePtrdType = field.Type().Elem() // get the type field can point to + var newPtrType = reflect.New(dePtrdType) // create new ptr address for type with non-nil zero value + field.Set(newPtrType) // assign value to pointer + field = field.Elem() + } + + switch field.Kind() { + case reflect.String: + field.SetString(value) + case reflect.Bool: + b, err := parseutil.ParseBool(value) + if err != nil { + return errors.New("can't convert to bool") + } + field.SetBool(b) + case reflect.Int: + n, err := strconv.ParseInt(value, 10, 32) + if err != nil { + return errors.New("can't convert to int") + } + field.SetInt(n) + case reflect.Float64: + value = strings.TrimSpace(value) + f, err := strconv.ParseFloat(value, 64) + if err != nil { + return errors.New("can't convert to float") + } + field.SetFloat(f) + case reflect.Slice: + if constraint == multilineConstraintName { + field.Set(reflect.ValueOf(strings.Split(value, "\n"))) + } else { + field.Set(reflect.ValueOf(strings.Split(value, "|"))) + } + default: + return fmt.Errorf("type is not supported (%s)", field.Kind()) + } + return nil +} + +func validateConstraint(value, constraint string) error { + switch constraint { + case "": + break + case "required": + if value == "" { + return errors.New("required variable is not present") + } + case "file", "dir": + if err := checkPath(value, constraint == "dir"); err != nil { + return err + } + // TODO: use FindStringSubmatch to distinguish no match and match for empty string. + case regexp.MustCompile(`^opt\[.*\]$`).FindString(constraint): + if !contains(value, constraint) { + // TODO: print only the value options, not the whole string. + return fmt.Errorf("value is not in value options (%s)", constraint) + } + case regexp.MustCompile(rangeRegex).FindString(constraint): + if err := ValidateRangeFields(value, constraint); err != nil { + return err + } + case multilineConstraintName: + break + default: + return fmt.Errorf("invalid constraint (%s)", constraint) + } + return nil +} + +//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) + if err != nil { + return err + } + min, err := parseValueStr(constraintMin) + if err != nil { + return fmt.Errorf("failed to parse min value %s: %s", constraintMin, err) + } + max, err := parseValueStr(constraintMax) + if err != nil { + return fmt.Errorf("failed to parse max value %s: %s", constraintMax, err) + } + value, err := parseValueStr(valueStr) + if err != nil { + return fmt.Errorf("failed to parse value %s: %s", valueStr, err) + } + isMinInclusiveBool, err := isMinInclusive(constraintMinBr) + if err != nil { + return err + } + isMaxInclusiveBool, err := isMaxInclusive(constraintMaxBr) + if err != nil { + return err + } + + if err := validateRangeFieldValues(min, max, isMinInclusiveBool, isMaxInclusiveBool, value); err != nil { + return err + } + if err := validateRangeFieldTypes(min, max, value); err != nil { + return err + } + + return nil +} + +func isMinInclusive(bracket string) (bool, error) { + switch bracket { + case "[": + return true, nil + case "]": + return false, nil + default: + return false, fmt.Errorf("invalid string found for bracket: %s", bracket) + } +} + +func isMaxInclusive(bracket string) (bool, error) { + switch bracket { + case "[": + return false, nil + case "]": + return true, nil + default: + return false, fmt.Errorf("invalid string found for bracket: %s", bracket) + } +} + +func validateRangeFieldValues(min interface{}, max interface{}, minInclusive bool, maxInclusive bool, value interface{}) error { + if value == nil { + return fmt.Errorf("value is not present") + } + var err error + var valueFloat float64 + if valueFloat, err = getFloatValue(value); err != nil { + return err + } + + var minErr error + var minFloat float64 + if min != nil { + if minFloat, err = getFloatValue(min); err != nil { + return err + } + minErr = validateRangeMinFieldValue(minFloat, valueFloat, minInclusive) + } + + var maxErr error + var maxFloat float64 + if max != nil { + var err error + if maxFloat, err = getFloatValue(max); err != nil { + return err + } + maxErr = validateRangeMaxFieldValue(maxFloat, valueFloat, maxInclusive) + } + + if min != nil && max != nil { + if minFloat > maxFloat { + return fmt.Errorf("constraint logic is wrong, minimum value %f is bigger than maximum %f", minFloat, maxFloat) + } + if minFloat == maxFloat { + return fmt.Errorf("minimum value %f is equal to maximum %f, for this case use optional value", minFloat, maxFloat) + } + } + + if min == nil { + return maxErr + } else if max == nil { + return minErr + } + if minErr != nil || maxErr != nil { + return fmt.Errorf("value %f is out of range %f-%f", value, minFloat, maxFloat) + } + return nil +} + +func validateRangeFieldTypes(min interface{}, max interface{}, value interface{}) error { + if value == nil { + return fmt.Errorf("value cannot be nil") + } + var minType string + var maxType string + var valueType string + var err error + + if valueType, err = getTypeOf(value); err != nil { + return err + } + if min != nil { + if minType, err = getTypeOf(min); err != nil { + return err + } + } + if max != nil { + if maxType, err = getTypeOf(max); err != nil { + return err + } + } + + if maxType != "" && minType != "" && !hasSameContent(minType, maxType, valueType) { + return fmt.Errorf("invalid constraint and value combination, minimum is %s, maximum is %s, value is %s, but they should be the same", minType, maxType, valueType) + } + + if maxType != "" && !hasSameContent(maxType, valueType) { + return fmt.Errorf("invalid constraint and value combination, maximum is %s, value is %s, but they should be the same", maxType, valueType) + } + + if minType != "" && !hasSameContent(minType, valueType) { + return fmt.Errorf("invalid constraint and value combination, minimum is %s, value is %s, but they should be the same", minType, valueType) + } + return nil +} + +func hasSameContent(strs ...string) bool { + length := len(strs) + if length == 1 { + return true + } + firstItem := strs[0] + for i := 1; i < length; i++ { + if strings.Compare(firstItem, strs[i]) != 0 { + return false + } + } + return true +} + +func getTypeOf(v interface{}) (string, error) { + switch v.(type) { + case int64: + return "int64", nil + case float64: + return "float64", nil + default: + return "unknown", fmt.Errorf("could not find type for %v", v) + } +} + +func parseValueStr(value string) (interface{}, error) { + var err error + var parsedInt int64 + var parsedFloat float64 + if parsedInt, err = strconv.ParseInt(value, 10, 64); err != nil { + // Could be float + if parsedFloat, err = strconv.ParseFloat(value, 64); err != nil { + // It is invalid. + return nil, fmt.Errorf("value %s is could not be parsed", value) + } + return parsedFloat, nil + } + return parsedInt, nil +} + +func getFloatValue(value interface{}) (float64, error) { + switch i := value.(type) { + case int64: + return float64(i), nil + case float64: + return i, nil + case string: + var parsedValue interface{} + var err error + if parsedValue, err = parseValueStr(i); err != nil { + return 0, err + } + return getFloatValue(parsedValue) + default: + return 0, fmt.Errorf("not supported type %T", value) + } +} + +func validateRangeMinFieldValue(min float64, value float64, inclusive bool) error { + if inclusive && min > value { + return fmt.Errorf("value %f is out of range, less than minimum %f", value, min) + } else if !inclusive && min >= value { + return fmt.Errorf("value %f is out of range, greater or equal than maximum %f", value, min) + } + return nil +} + +func validateRangeMaxFieldValue(max float64, value float64, inclusive bool) error { + if inclusive && max < value { + return fmt.Errorf("value %f is out of range, greater than maximum %f", value, max) + + } else if !inclusive && max <= value { + return fmt.Errorf("value %f is out of range, greater or equal than maximum %f", value, max) + } + 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) { + regex := regexp.MustCompile(rangeRegex) + groups := regex.FindStringSubmatch(value) + if len(groups) < 1 { + return "", "", "", "", fmt.Errorf("value in value options is malformed (%s)", value) + } + + groupMap := getRegexGroupMap(groups, regex) + minStr := groupMap[rangeMinimumGroupName] + maxStr := groupMap[rangeMaximumGroupName] + minBr := groupMap[rangeMinBracketGroupName] + maxBr := groupMap[rangeMaxBracketGroupName] + if minStr == "" && maxStr == "" { + return "", "", "", "", fmt.Errorf("constraint contains no limits") + } + return minStr, maxStr, minBr, maxBr, nil +} + +func getRegexGroupMap(groups []string, regex *regexp.Regexp) map[string]string { + result := make(map[string]string) + for i, value := range regex.SubexpNames() { + if i != 0 && value != "" { + result[value] = groups[i] + } + } + return result +} + +func checkPath(path string, dir bool) error { + file, err := os.Stat(path) + if err != nil { + // TODO: check case when file exist but os.Stat fails. + return os.ErrNotExist + } + if dir && !file.IsDir() { + return errors.New("not a directory") + } + return nil +} + +// contains reports whether s is within the value options, where value options +// are parsed from opt, which format's is opt[item1,item2,item3]. If an option +// contains commas, it should be single quoted (eg. opt[item1,'item2,item3']). +func contains(s, opt string) bool { + opt = strings.TrimSuffix(strings.TrimPrefix(opt, "opt["), "]") + var valueOpts []string + if strings.Contains(opt, "'") { + // The single quotes separate the options with comma and without comma + // Eg. "a,b,'c,d',e" will results "a,b," "c,d" and ",e" strings. + for _, s := range strings.Split(opt, "'") { + switch { + case s == "," || s == "": + case !strings.HasPrefix(s, ",") && !strings.HasSuffix(s, ","): + // If a string doesn't starts nor ends with a comma it means it's an option which + // contains comma, so we just append it to valueOpts as it is. Eg. "c,d" from above. + valueOpts = append(valueOpts, s) + default: + // If a string starts or ends with comma it means that it contains options without comma. + // So we split the string at commas to get the options. Eg. "a,b," and ",e" from above. + valueOpts = append(valueOpts, strings.Split(strings.Trim(s, ","), ",")...) + } + } + } else { + valueOpts = strings.Split(opt, ",") + } + for _, valOpt := range valueOpts { + if valOpt == s { + return true + } + } + return false +} diff --git a/vendor/github.com/bitrise-io/go-utils/parseutil/parseutil.go b/vendor/github.com/bitrise-io/go-utils/parseutil/parseutil.go new file mode 100644 index 0000000..08cec36 --- /dev/null +++ b/vendor/github.com/bitrise-io/go-utils/parseutil/parseutil.go @@ -0,0 +1,95 @@ +package parseutil + +import ( + "errors" + "fmt" + "strconv" + "strings" + + "github.com/bitrise-io/go-utils/pointers" +) + +// ParseBool ... +func ParseBool(userInputStr string) (bool, error) { + if userInputStr == "" { + return false, errors.New("No string to parse") + } + userInputStr = strings.TrimSpace(userInputStr) + + lowercased := strings.ToLower(userInputStr) + if lowercased == "yes" || lowercased == "y" { + return true, nil + } + if lowercased == "no" || lowercased == "n" { + return false, nil + } + return strconv.ParseBool(lowercased) +} + +// CastToString ... +func CastToString(value interface{}) string { + casted, ok := value.(string) + + if !ok { + castedStr := fmt.Sprintf("%v", value) + casted = castedStr + } + + return casted +} + +// CastToStringPtr ... +func CastToStringPtr(value interface{}) *string { + castedValue := CastToString(value) + return pointers.NewStringPtr(castedValue) +} + +// CastToBool ... +func CastToBool(value interface{}) (bool, bool) { + casted, ok := value.(bool) + + if !ok { + castedStr := CastToString(value) + + castedBool, err := ParseBool(castedStr) + if err != nil { + return false, false + } + + casted = castedBool + } + + return casted, true +} + +// CastToBoolPtr ... +func CastToBoolPtr(value interface{}) (*bool, bool) { + castedValue, ok := CastToBool(value) + if !ok { + return nil, false + } + return pointers.NewBoolPtr(castedValue), true +} + +// CastToMapStringInterface ... +func CastToMapStringInterface(value interface{}) (map[string]interface{}, bool) { + castedValue, ok := value.(map[interface{}]interface{}) + desiredMap := map[string]interface{}{} + for key, value := range castedValue { + keyStr, ok := key.(string) + if !ok { + return map[string]interface{}{}, false + } + desiredMap[keyStr] = value + } + return desiredMap, ok +} + +// CastToMapStringInterfacePtr ... +func CastToMapStringInterfacePtr(value interface{}) (*map[string]interface{}, bool) { + casted, ok := CastToMapStringInterface(value) + if !ok { + return nil, false + } + return pointers.NewMapStringInterfacePtr(casted), true +} diff --git a/vendor/github.com/bitrise-io/go-utils/pathutil/glob.go b/vendor/github.com/bitrise-io/go-utils/pathutil/glob.go new file mode 100644 index 0000000..232dd51 --- /dev/null +++ b/vendor/github.com/bitrise-io/go-utils/pathutil/glob.go @@ -0,0 +1,13 @@ +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 new file mode 100644 index 0000000..0bfd0fc --- /dev/null +++ b/vendor/github.com/bitrise-io/go-utils/pathutil/path_filter.go @@ -0,0 +1,143 @@ +package pathutil + +import ( + "errors" + "io/ioutil" + "os" + "path/filepath" + "regexp" + "strings" +) + +// FilterPaths ... +func FilterPaths(fileList []string, filters ...FilterFunc) ([]string, error) { + var filtered []string + + for _, pth := range fileList { + allowed := true + for _, filter := range filters { + if allows, err := filter(pth); err != nil { + return []string{}, err + } else if !allows { + allowed = false + break + } + } + if allowed { + filtered = append(filtered, pth) + } + } + + return filtered, nil +} + +// FilterFunc ... +type FilterFunc func(string) (bool, error) + +// BaseFilter ... +func BaseFilter(base string, allowed bool) FilterFunc { + return func(pth string) (bool, error) { + b := filepath.Base(pth) + return allowed == strings.EqualFold(base, b), nil + } +} + +// ExtensionFilter ... +func ExtensionFilter(ext string, allowed bool) FilterFunc { + return func(pth string) (bool, error) { + e := filepath.Ext(pth) + return allowed == strings.EqualFold(ext, e), nil + } +} + +// RegexpFilter ... +func RegexpFilter(pattern string, allowed bool) FilterFunc { + return func(pth string) (bool, error) { + re := regexp.MustCompile(pattern) + found := re.FindString(pth) != "" + return allowed == found, nil + } +} + +// ComponentFilter ... +func ComponentFilter(component string, allowed bool) FilterFunc { + return func(pth string) (bool, error) { + found := false + pathComponents := strings.Split(pth, string(filepath.Separator)) + for _, c := range pathComponents { + if c == component { + found = true + } + } + return allowed == found, nil + } +} + +// ComponentWithExtensionFilter ... +func ComponentWithExtensionFilter(ext string, allowed bool) FilterFunc { + return func(pth string) (bool, error) { + found := false + pathComponents := strings.Split(pth, string(filepath.Separator)) + for _, c := range pathComponents { + e := filepath.Ext(c) + if e == ext { + found = true + } + } + return allowed == found, nil + } +} + +// IsDirectoryFilter ... +func IsDirectoryFilter(allowed bool) FilterFunc { + return func(pth string) (bool, error) { + fileInf, err := os.Lstat(pth) + if err != nil { + return false, err + } + if fileInf == nil { + return false, errors.New("no file info available") + } + return allowed == fileInf.IsDir(), nil + } +} + +// InDirectoryFilter ... +func InDirectoryFilter(dir string, allowed bool) FilterFunc { + return func(pth string) (bool, error) { + in := filepath.Dir(pth) == dir + return allowed == in, nil + } +} + +// DirectoryContainsFileFilter returns a FilterFunc that checks if a directory contains a file +func DirectoryContainsFileFilter(fileName string) FilterFunc { + return func(pth string) (bool, error) { + isDir, err := IsDirectoryFilter(true)(pth) + if err != nil { + return false, err + } + if !isDir { + return false, nil + } + + absPath := filepath.Join(pth, fileName) + if _, err := os.Lstat(absPath); err != nil { + if !os.IsNotExist(err) { + return false, err + } + return false, nil + } + return true, nil + } +} + +// FileContainsFilter ... +func FileContainsFilter(pth, str string) (bool, error) { + bytes, err := ioutil.ReadFile(pth) + if err != nil { + return false, err + } + + return strings.Contains(string(bytes), str), nil +} 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 a88ff5f..db577e3 100644 --- a/vendor/github.com/bitrise-io/go-utils/pathutil/pathutil.go +++ b/vendor/github.com/bitrise-io/go-utils/pathutil/pathutil.go @@ -184,3 +184,55 @@ func NormalizedOSTempDirPath(tmpDirNamePrefix string) (retPth string, err error) 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 + } + + 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) +} + +// 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...) +} 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 new file mode 100644 index 0000000..4bed6bf --- /dev/null +++ b/vendor/github.com/bitrise-io/go-utils/pathutil/sortable_path.go @@ -0,0 +1,88 @@ +package pathutil + +import ( + "os" + "path/filepath" + "sort" + "strings" +) + +// SortablePath ... +type SortablePath struct { + Pth string + AbsPth string + Components []string +} + +// NewSortablePath ... +func NewSortablePath(pth string) (SortablePath, error) { + absPth, err := AbsPath(pth) + if err != nil { + return SortablePath{}, err + } + + components := strings.Split(absPth, string(os.PathSeparator)) + fixedComponents := []string{} + for _, comp := range components { + if comp != "" { + fixedComponents = append(fixedComponents, comp) + } + } + + return SortablePath{ + Pth: pth, + AbsPth: absPth, + Components: fixedComponents, + }, nil +} + +// BySortablePathComponents .. +type BySortablePathComponents []SortablePath + +func (s BySortablePathComponents) Len() int { + return len(s) +} +func (s BySortablePathComponents) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} +func (s BySortablePathComponents) Less(i, j int) bool { + path1 := s[i] + path2 := s[j] + + d1 := len(path1.Components) + d2 := len(path2.Components) + + if d1 < d2 { + return true + } else if d1 > d2 { + return false + } + + // if same component size, + // do alphabetic sort based on the last component + base1 := filepath.Base(path1.AbsPth) + base2 := filepath.Base(path2.AbsPth) + + return base1 < base2 +} + +// SortPathsByComponents ... +func SortPathsByComponents(paths []string) ([]string, error) { + sortableFiles := []SortablePath{} + for _, pth := range paths { + sortable, err := NewSortablePath(pth) + if err != nil { + return []string{}, err + } + sortableFiles = append(sortableFiles, sortable) + } + + sort.Sort(BySortablePathComponents(sortableFiles)) + + sortedFiles := []string{} + for _, pth := range sortableFiles { + sortedFiles = append(sortedFiles, pth.Pth) + } + + return sortedFiles, nil +} diff --git a/vendor/github.com/bitrise-io/go-utils/pointers/pointers.go b/vendor/github.com/bitrise-io/go-utils/pointers/pointers.go new file mode 100644 index 0000000..e26647d --- /dev/null +++ b/vendor/github.com/bitrise-io/go-utils/pointers/pointers.go @@ -0,0 +1,98 @@ +package pointers + +import "time" + +// NewBoolPtr ... +func NewBoolPtr(val bool) *bool { + ptrValue := new(bool) + *ptrValue = val + return ptrValue +} + +// NewStringPtr ... +func NewStringPtr(val string) *string { + ptrValue := new(string) + *ptrValue = val + return ptrValue +} + +// NewTimePtr ... +func NewTimePtr(val time.Time) *time.Time { + ptrValue := new(time.Time) + *ptrValue = val + return ptrValue +} + +// NewIntPtr ... +func NewIntPtr(val int) *int { + ptrValue := new(int) + *ptrValue = val + return ptrValue +} + +// NewInt64Ptr ... +func NewInt64Ptr(val int64) *int64 { + ptrValue := new(int64) + *ptrValue = val + return ptrValue +} + +// NewMapStringInterfacePtr ... +func NewMapStringInterfacePtr(val map[string]interface{}) *map[string]interface{} { + ptrValue := new(map[string]interface{}) + *ptrValue = map[string]interface{}{} + for key, value := range val { + (*ptrValue)[key] = value + } + return ptrValue +} + +// ------------------------------------------------------ +// --- Safe Getters + +// Bool ... +func Bool(val *bool) bool { + return BoolWithDefault(val, false) +} + +// BoolWithDefault ... +func BoolWithDefault(val *bool, defaultValue bool) bool { + if val == nil { + return defaultValue + } + return *val +} + +// String ... +func String(val *string) string { + return StringWithDefault(val, "") +} + +// StringWithDefault ... +func StringWithDefault(val *string, defaultValue string) string { + if val == nil { + return defaultValue + } + return *val +} + +// TimeWithDefault ... +func TimeWithDefault(val *time.Time, defaultValue time.Time) time.Time { + if val == nil { + return defaultValue + } + return *val +} + +// Int ... +func Int(val *int) int { + return IntWithDefault(val, 0) +} + +// IntWithDefault ... +func IntWithDefault(val *int, defaultValue int) int { + if val == nil { + return defaultValue + } + return *val +} diff --git a/vendor/github.com/hashicorp/go-retryablehttp/.travis.yml b/vendor/github.com/hashicorp/go-retryablehttp/.travis.yml new file mode 100644 index 0000000..c4fb6d6 --- /dev/null +++ b/vendor/github.com/hashicorp/go-retryablehttp/.travis.yml @@ -0,0 +1,12 @@ +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 8943bec..30357c7 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/README.md +++ b/vendor/github.com/hashicorp/go-retryablehttp/README.md @@ -26,7 +26,6 @@ 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 adbdd92..f1ccd3d 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/client.go +++ b/vendor/github.com/hashicorp/go-retryablehttp/client.go @@ -35,12 +35,11 @@ import ( "net/url" "os" "regexp" - "strconv" "strings" "sync" "time" - cleanhttp "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/go-cleanhttp" ) var ( @@ -277,16 +276,12 @@ type Logger interface { Printf(string, ...interface{}) } -// 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. +// LeveledLogger interface implements the basic methods that a logger library needs type LeveledLogger interface { - Error(msg string, keysAndValues ...interface{}) - Info(msg string, keysAndValues ...interface{}) - Debug(msg string, keysAndValues ...interface{}) - Warn(msg string, keysAndValues ...interface{}) + Error(string, ...interface{}) + Info(string, ...interface{}) + Debug(string, ...interface{}) + Warn(string, ...interface{}) } // hookLogger adapts an LeveledLogger to Logger for use by the existing hook functions @@ -362,7 +357,6 @@ type Client struct { ErrorHandler ErrorHandler loggerInit sync.Once - clientInit sync.Once } // NewClient creates a new Client with default settings. @@ -404,39 +398,21 @@ 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, v + return false, nil } // Don't retry if the error was due to an invalid protocol scheme. if schemeErrorRe.MatchString(v.Error()) { - return false, v + return false, nil } // Don't retry if the error was due to TLS cert verification failure. if _, ok := v.Err.(x509.UnknownAuthorityError); ok { - return false, v + return false, nil } } @@ -444,19 +420,12 @@ func baseRetryPolicy(resp *http.Response, err error) (bool, error) { 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, fmt.Errorf("unexpected HTTP status %s", resp.Status) + return true, nil } return false, nil @@ -465,21 +434,7 @@ func baseRetryPolicy(resp *http.Response, err error) (bool, error) { // 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 { @@ -535,31 +490,25 @@ 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) { - c.clientInit.Do(func() { - if c.HTTPClient == nil { - c.HTTPClient = cleanhttp.DefaultPooledClient() - } - }) + if c.HTTPClient == nil { + c.HTTPClient = cleanhttp.DefaultPooledClient() + } logger := c.logger() if logger != nil { switch v := logger.(type) { - case LeveledLogger: - v.Debug("performing request", "method", req.Method, "url", req.URL) case Logger: v.Printf("[DEBUG] %s %s", req.Method, req.URL) + case LeveledLogger: + v.Debug("performing request", "method", req.Method, "url", req.URL) } } var resp *http.Response - var attempt int - var shouldRetry bool - var doErr, checkErr error + var err error for i := 0; ; i++ { - attempt++ - var code int // HTTP response code // Always rewind the request body when non-nil. @@ -578,30 +527,30 @@ func (c *Client) Do(req *Request) (*http.Response, error) { if c.RequestLogHook != nil { switch v := logger.(type) { - case LeveledLogger: - c.RequestLogHook(hookLogger{v}, req.Request, i) case Logger: c.RequestLogHook(v, req.Request, i) + case LeveledLogger: + c.RequestLogHook(hookLogger{v}, req.Request, i) default: c.RequestLogHook(nil, req.Request, i) } } // Attempt the request - resp, doErr = c.HTTPClient.Do(req.Request) + resp, err = c.HTTPClient.Do(req.Request) if resp != nil { code = resp.StatusCode } // Check if we should continue with retries. - shouldRetry, checkErr = c.CheckRetry(req.Context(), resp, doErr) + checkOK, checkErr := c.CheckRetry(req.Context(), resp, err) - if doErr != nil { + if err != nil { switch v := logger.(type) { - case LeveledLogger: - 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) + 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) } } else { // Call this here to maintain the behavior of logging all requests, @@ -609,18 +558,23 @@ 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 LeveledLogger: - c.ResponseLogHook(hookLogger{v}, resp) case Logger: c.ResponseLogHook(v, resp) + case LeveledLogger: + c.ResponseLogHook(hookLogger{v}, resp) default: c.ResponseLogHook(nil, resp) } } } - if !shouldRetry { - break + // Now decide if we should continue. + if !checkOK { + if checkErr != nil { + err = checkErr + } + c.HTTPClient.CloseIdleConnections() + return resp, err } // We do this before drainBody because there's no need for the I/O if @@ -631,7 +585,7 @@ func (c *Client) Do(req *Request) (*http.Response, error) { } // We're going to retry, consume any response to reuse the connection. - if doErr == nil { + if err == nil && resp != nil { c.drainBody(resp.Body) } @@ -642,10 +596,10 @@ func (c *Client) Do(req *Request) (*http.Response, error) { } if logger != nil { switch v := logger.(type) { - 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) + case LeveledLogger: + v.Debug("retrying request", "request", desc, "timeout", wait, "remaining", remain) } } select { @@ -654,44 +608,21 @@ 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 { - return c.ErrorHandler(resp, err, attempt) + c.HTTPClient.CloseIdleConnections() + return c.ErrorHandler(resp, err, c.RetryMax+1) } // By default, we close the response body and return an error without // returning the response if resp != nil { - c.drainBody(resp.Body) + resp.Body.Close() } - - // 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) + c.HTTPClient.CloseIdleConnections() + return nil, fmt.Errorf("%s %s giving up after %d attempts", + req.Method, req.URL, c.RetryMax+1) } // Try to read the response body so we can reuse this connection. @@ -701,10 +632,10 @@ func (c *Client) drainBody(body io.ReadCloser) { if err != nil { if c.logger() != nil { switch v := c.logger().(type) { - case LeveledLogger: - v.Error("error reading response body", "error", err) case Logger: v.Printf("[ERR] error reading response body: %v", err) + case LeveledLogger: + v.Error("error reading response body", "error", err) } } } diff --git a/vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go b/vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go index 8f3ee35..b841b4c 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go +++ b/vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go @@ -1,9 +1,7 @@ package retryablehttp import ( - "errors" "net/http" - "net/url" "sync" ) @@ -41,12 +39,5 @@ func (rt *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { } // Execute the request. - 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 + return rt.Client.Do(retryableReq) } diff --git a/vendor/github.com/pkg/errors/.gitignore b/vendor/github.com/pkg/errors/.gitignore deleted file mode 100644 index daf913b..0000000 --- a/vendor/github.com/pkg/errors/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml deleted file mode 100644 index 9159de0..0000000 --- a/vendor/github.com/pkg/errors/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: go -go_import_path: github.com/pkg/errors -go: - - 1.11.x - - 1.12.x - - 1.13.x - - tip - -script: - - make check diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE deleted file mode 100644 index 835ba3e..0000000 --- a/vendor/github.com/pkg/errors/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2015, Dave Cheney -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pkg/errors/Makefile b/vendor/github.com/pkg/errors/Makefile deleted file mode 100644 index ce9d7cd..0000000 --- a/vendor/github.com/pkg/errors/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -PKGS := github.com/pkg/errors -SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS)) -GO := go - -check: test vet gofmt misspell unconvert staticcheck ineffassign unparam - -test: - $(GO) test $(PKGS) - -vet: | test - $(GO) vet $(PKGS) - -staticcheck: - $(GO) get honnef.co/go/tools/cmd/staticcheck - staticcheck -checks all $(PKGS) - -misspell: - $(GO) get github.com/client9/misspell/cmd/misspell - misspell \ - -locale GB \ - -error \ - *.md *.go - -unconvert: - $(GO) get github.com/mdempsky/unconvert - unconvert -v $(PKGS) - -ineffassign: - $(GO) get github.com/gordonklaus/ineffassign - find $(SRCDIRS) -name '*.go' | xargs ineffassign - -pedantic: check errcheck - -unparam: - $(GO) get mvdan.cc/unparam - unparam ./... - -errcheck: - $(GO) get github.com/kisielk/errcheck - errcheck $(PKGS) - -gofmt: - @echo Checking code is gofmted - @test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)" diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md deleted file mode 100644 index 54dfdcb..0000000 --- a/vendor/github.com/pkg/errors/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge) - -Package errors provides simple error handling primitives. - -`go get github.com/pkg/errors` - -The traditional error handling idiom in Go is roughly akin to -```go -if err != nil { - return err -} -``` -which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. - -## Adding context to an error - -The errors.Wrap function returns a new error that adds context to the original error. For example -```go -_, err := ioutil.ReadAll(r) -if err != nil { - return errors.Wrap(err, "read failed") -} -``` -## Retrieving the cause of an error - -Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. -```go -type causer interface { - Cause() error -} -``` -`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: -```go -switch err := errors.Cause(err).(type) { -case *MyError: - // handle specifically -default: - // unknown error -} -``` - -[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). - -## Roadmap - -With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows: - -- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible) -- 1.0. Final release. - -## Contributing - -Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports. - -Before sending a PR, please discuss your change by raising an issue. - -## License - -BSD-2-Clause diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml deleted file mode 100644 index a932ead..0000000 --- a/vendor/github.com/pkg/errors/appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -version: build-{build}.{branch} - -clone_folder: C:\gopath\src\github.com\pkg\errors -shallow_clone: true # for startup speed - -environment: - GOPATH: C:\gopath - -platform: - - x64 - -# http://www.appveyor.com/docs/installed-software -install: - # some helpful output for debugging builds - - go version - - go env - # pre-installed MinGW at C:\MinGW is 32bit only - # but MSYS2 at C:\msys64 has mingw64 - - set PATH=C:\msys64\mingw64\bin;%PATH% - - gcc --version - - g++ --version - -build_script: - - go install -v ./... - -test_script: - - set PATH=C:\gopath\bin;%PATH% - - go test -v ./... - -#artifacts: -# - path: '%GOPATH%\bin\*.exe' -deploy: off diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go deleted file mode 100644 index 161aea2..0000000 --- a/vendor/github.com/pkg/errors/errors.go +++ /dev/null @@ -1,288 +0,0 @@ -// Package errors provides simple error handling primitives. -// -// The traditional error handling idiom in Go is roughly akin to -// -// if err != nil { -// return err -// } -// -// which when applied recursively up the call stack results in error reports -// without context or debugging information. The errors package allows -// programmers to add context to the failure path in their code in a way -// that does not destroy the original value of the error. -// -// Adding context to an error -// -// The errors.Wrap function returns a new error that adds context to the -// original error by recording a stack trace at the point Wrap is called, -// together with the supplied message. For example -// -// _, err := ioutil.ReadAll(r) -// if err != nil { -// return errors.Wrap(err, "read failed") -// } -// -// If additional control is required, the errors.WithStack and -// errors.WithMessage functions destructure errors.Wrap into its component -// operations: annotating an error with a stack trace and with a message, -// respectively. -// -// Retrieving the cause of an error -// -// Using errors.Wrap constructs a stack of errors, adding context to the -// preceding error. Depending on the nature of the error it may be necessary -// to reverse the operation of errors.Wrap to retrieve the original error -// for inspection. Any error value which implements this interface -// -// type causer interface { -// Cause() error -// } -// -// can be inspected by errors.Cause. errors.Cause will recursively retrieve -// the topmost error that does not implement causer, which is assumed to be -// the original cause. For example: -// -// switch err := errors.Cause(err).(type) { -// case *MyError: -// // handle specifically -// default: -// // unknown error -// } -// -// Although the causer interface is not exported by this package, it is -// considered a part of its stable public interface. -// -// Formatted printing of errors -// -// All error values returned from this package implement fmt.Formatter and can -// be formatted by the fmt package. The following verbs are supported: -// -// %s print the error. If the error has a Cause it will be -// printed recursively. -// %v see %s -// %+v extended format. Each Frame of the error's StackTrace will -// be printed in detail. -// -// Retrieving the stack trace of an error or wrapper -// -// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are -// invoked. This information can be retrieved with the following interface: -// -// type stackTracer interface { -// StackTrace() errors.StackTrace -// } -// -// The returned errors.StackTrace type is defined as -// -// type StackTrace []Frame -// -// The Frame type represents a call site in the stack trace. Frame supports -// the fmt.Formatter interface that can be used for printing information about -// the stack trace of this error. For example: -// -// if err, ok := err.(stackTracer); ok { -// for _, f := range err.StackTrace() { -// fmt.Printf("%+s:%d\n", f, f) -// } -// } -// -// Although the stackTracer interface is not exported by this package, it is -// considered a part of its stable public interface. -// -// See the documentation for Frame.Format for more details. -package errors - -import ( - "fmt" - "io" -) - -// New returns an error with the supplied message. -// New also records the stack trace at the point it was called. -func New(message string) error { - return &fundamental{ - msg: message, - stack: callers(), - } -} - -// Errorf formats according to a format specifier and returns the string -// as a value that satisfies error. -// Errorf also records the stack trace at the point it was called. -func Errorf(format string, args ...interface{}) error { - return &fundamental{ - msg: fmt.Sprintf(format, args...), - stack: callers(), - } -} - -// fundamental is an error that has a message and a stack, but no caller. -type fundamental struct { - msg string - *stack -} - -func (f *fundamental) Error() string { return f.msg } - -func (f *fundamental) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - if s.Flag('+') { - io.WriteString(s, f.msg) - f.stack.Format(s, verb) - return - } - fallthrough - case 's': - io.WriteString(s, f.msg) - case 'q': - fmt.Fprintf(s, "%q", f.msg) - } -} - -// WithStack annotates err with a stack trace at the point WithStack was called. -// If err is nil, WithStack returns nil. -func WithStack(err error) error { - if err == nil { - return nil - } - return &withStack{ - err, - callers(), - } -} - -type withStack struct { - error - *stack -} - -func (w *withStack) Cause() error { return w.error } - -// Unwrap provides compatibility for Go 1.13 error chains. -func (w *withStack) Unwrap() error { return w.error } - -func (w *withStack) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - if s.Flag('+') { - fmt.Fprintf(s, "%+v", w.Cause()) - w.stack.Format(s, verb) - return - } - fallthrough - case 's': - io.WriteString(s, w.Error()) - case 'q': - fmt.Fprintf(s, "%q", w.Error()) - } -} - -// Wrap returns an error annotating err with a stack trace -// at the point Wrap is called, and the supplied message. -// If err is nil, Wrap returns nil. -func Wrap(err error, message string) error { - if err == nil { - return nil - } - err = &withMessage{ - cause: err, - msg: message, - } - return &withStack{ - err, - callers(), - } -} - -// Wrapf returns an error annotating err with a stack trace -// at the point Wrapf is called, and the format specifier. -// If err is nil, Wrapf returns nil. -func Wrapf(err error, format string, args ...interface{}) error { - if err == nil { - return nil - } - err = &withMessage{ - cause: err, - msg: fmt.Sprintf(format, args...), - } - return &withStack{ - err, - callers(), - } -} - -// WithMessage annotates err with a new message. -// If err is nil, WithMessage returns nil. -func WithMessage(err error, message string) error { - if err == nil { - return nil - } - return &withMessage{ - cause: err, - msg: message, - } -} - -// WithMessagef annotates err with the format specifier. -// If err is nil, WithMessagef returns nil. -func WithMessagef(err error, format string, args ...interface{}) error { - if err == nil { - return nil - } - return &withMessage{ - cause: err, - msg: fmt.Sprintf(format, args...), - } -} - -type withMessage struct { - cause error - msg string -} - -func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } -func (w *withMessage) Cause() error { return w.cause } - -// Unwrap provides compatibility for Go 1.13 error chains. -func (w *withMessage) Unwrap() error { return w.cause } - -func (w *withMessage) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - if s.Flag('+') { - fmt.Fprintf(s, "%+v\n", w.Cause()) - io.WriteString(s, w.msg) - return - } - fallthrough - case 's', 'q': - io.WriteString(s, w.Error()) - } -} - -// Cause returns the underlying cause of the error, if possible. -// An error value has a cause if it implements the following -// interface: -// -// type causer interface { -// Cause() error -// } -// -// If the error does not implement Cause, the original error will -// be returned. If the error is nil, nil will be returned without further -// investigation. -func Cause(err error) error { - type causer interface { - Cause() error - } - - for err != nil { - cause, ok := err.(causer) - if !ok { - break - } - err = cause.Cause() - } - return err -} diff --git a/vendor/github.com/pkg/errors/go113.go b/vendor/github.com/pkg/errors/go113.go deleted file mode 100644 index be0d10d..0000000 --- a/vendor/github.com/pkg/errors/go113.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build go1.13 - -package errors - -import ( - stderrors "errors" -) - -// Is reports whether any error in err's chain matches target. -// -// The chain consists of err itself followed by the sequence of errors obtained by -// repeatedly calling Unwrap. -// -// An error is considered to match a target if it is equal to that target or if -// it implements a method Is(error) bool such that Is(target) returns true. -func Is(err, target error) bool { return stderrors.Is(err, target) } - -// As finds the first error in err's chain that matches target, and if so, sets -// target to that error value and returns true. -// -// The chain consists of err itself followed by the sequence of errors obtained by -// repeatedly calling Unwrap. -// -// An error matches target if the error's concrete value is assignable to the value -// pointed to by target, or if the error has a method As(interface{}) bool such that -// As(target) returns true. In the latter case, the As method is responsible for -// setting target. -// -// As will panic if target is not a non-nil pointer to either a type that implements -// error, or to any interface type. As returns false if err is nil. -func As(err error, target interface{}) bool { return stderrors.As(err, target) } - -// Unwrap returns the result of calling the Unwrap method on err, if err's -// type contains an Unwrap method returning error. -// Otherwise, Unwrap returns nil. -func Unwrap(err error) error { - return stderrors.Unwrap(err) -} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go deleted file mode 100644 index 779a834..0000000 --- a/vendor/github.com/pkg/errors/stack.go +++ /dev/null @@ -1,177 +0,0 @@ -package errors - -import ( - "fmt" - "io" - "path" - "runtime" - "strconv" - "strings" -) - -// Frame represents a program counter inside a stack frame. -// For historical reasons if Frame is interpreted as a uintptr -// its value represents the program counter + 1. -type Frame uintptr - -// pc returns the program counter for this frame; -// multiple frames may have the same PC value. -func (f Frame) pc() uintptr { return uintptr(f) - 1 } - -// file returns the full path to the file that contains the -// function for this Frame's pc. -func (f Frame) file() string { - fn := runtime.FuncForPC(f.pc()) - if fn == nil { - return "unknown" - } - file, _ := fn.FileLine(f.pc()) - return file -} - -// line returns the line number of source code of the -// function for this Frame's pc. -func (f Frame) line() int { - fn := runtime.FuncForPC(f.pc()) - if fn == nil { - return 0 - } - _, line := fn.FileLine(f.pc()) - return line -} - -// name returns the name of this function, if known. -func (f Frame) name() string { - fn := runtime.FuncForPC(f.pc()) - if fn == nil { - return "unknown" - } - return fn.Name() -} - -// Format formats the frame according to the fmt.Formatter interface. -// -// %s source file -// %d source line -// %n function name -// %v equivalent to %s:%d -// -// Format accepts flags that alter the printing of some verbs, as follows: -// -// %+s function name and path of source file relative to the compile time -// GOPATH separated by \n\t (\n\t) -// %+v equivalent to %+s:%d -func (f Frame) Format(s fmt.State, verb rune) { - switch verb { - case 's': - switch { - case s.Flag('+'): - io.WriteString(s, f.name()) - io.WriteString(s, "\n\t") - io.WriteString(s, f.file()) - default: - io.WriteString(s, path.Base(f.file())) - } - case 'd': - io.WriteString(s, strconv.Itoa(f.line())) - case 'n': - io.WriteString(s, funcname(f.name())) - case 'v': - f.Format(s, 's') - io.WriteString(s, ":") - f.Format(s, 'd') - } -} - -// MarshalText formats a stacktrace Frame as a text string. The output is the -// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs. -func (f Frame) MarshalText() ([]byte, error) { - name := f.name() - if name == "unknown" { - return []byte(name), nil - } - return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil -} - -// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). -type StackTrace []Frame - -// Format formats the stack of Frames according to the fmt.Formatter interface. -// -// %s lists source files for each Frame in the stack -// %v lists the source file and line number for each Frame in the stack -// -// Format accepts flags that alter the printing of some verbs, as follows: -// -// %+v Prints filename, function, and line number for each Frame in the stack. -func (st StackTrace) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - switch { - case s.Flag('+'): - for _, f := range st { - io.WriteString(s, "\n") - f.Format(s, verb) - } - case s.Flag('#'): - fmt.Fprintf(s, "%#v", []Frame(st)) - default: - st.formatSlice(s, verb) - } - case 's': - st.formatSlice(s, verb) - } -} - -// formatSlice will format this StackTrace into the given buffer as a slice of -// Frame, only valid when called with '%s' or '%v'. -func (st StackTrace) formatSlice(s fmt.State, verb rune) { - io.WriteString(s, "[") - for i, f := range st { - if i > 0 { - io.WriteString(s, " ") - } - f.Format(s, verb) - } - io.WriteString(s, "]") -} - -// stack represents a stack of program counters. -type stack []uintptr - -func (s *stack) Format(st fmt.State, verb rune) { - switch verb { - case 'v': - switch { - case st.Flag('+'): - for _, pc := range *s { - f := Frame(pc) - fmt.Fprintf(st, "\n%+v", f) - } - } - } -} - -func (s *stack) StackTrace() StackTrace { - f := make([]Frame, len(*s)) - for i := 0; i < len(f); i++ { - f[i] = Frame((*s)[i]) - } - return f -} - -func callers() *stack { - const depth = 32 - var pcs [depth]uintptr - n := runtime.Callers(3, pcs[:]) - var st stack = pcs[0:n] - return &st -} - -// funcname removes the path prefix component of a function's name reported by func.Name(). -func funcname(name string) string { - i := strings.LastIndex(name, "/") - name = name[i+1:] - i = strings.Index(name, ".") - return name[i+1:] -} diff --git a/vendor/modules.txt b/vendor/modules.txt index ab3b47b..5d3f3bb 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,30 +1,28 @@ -# github.com/bitrise-io/go-android v0.0.0-20210301151701-791fb4b5216b +# github.com/bitrise-io/go-android v0.0.0-20210527143215-3ad22ad02e2e ## explicit github.com/bitrise-io/go-android/sdk github.com/bitrise-io/go-android/sdkcomponent github.com/bitrise-io/go-android/sdkmanager -# github.com/bitrise-io/go-steputils v0.0.0-20210507072936-92fde382fb33 +# github.com/bitrise-io/go-steputils v0.0.0-20210527075147-910ce7a105a1 ## explicit -github.com/bitrise-io/go-steputils/input +github.com/bitrise-io/go-steputils/stepconf github.com/bitrise-io/go-steputils/tools -# github.com/bitrise-io/go-utils v0.0.0-20210507100250-37de47dfa6ce +# github.com/bitrise-io/go-utils v0.0.0-20210520073355-367fa34178f5 ## explicit github.com/bitrise-io/go-utils/colorstring github.com/bitrise-io/go-utils/command github.com/bitrise-io/go-utils/fileutil github.com/bitrise-io/go-utils/log +github.com/bitrise-io/go-utils/parseutil github.com/bitrise-io/go-utils/pathutil +github.com/bitrise-io/go-utils/pointers github.com/bitrise-io/go-utils/retry github.com/bitrise-io/go-utils/sliceutil # github.com/hashicorp/go-cleanhttp v0.5.2 ## explicit github.com/hashicorp/go-cleanhttp -# github.com/hashicorp/go-retryablehttp v0.7.0 -## explicit +# github.com/hashicorp/go-retryablehttp v0.6.6 github.com/hashicorp/go-retryablehttp # github.com/hashicorp/go-version v1.3.0 ## explicit github.com/hashicorp/go-version -# github.com/pkg/errors v0.9.1 -## explicit -github.com/pkg/errors