From d3b1275ac5c915b8b0ebce2e42770a053513184f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliv=C3=A9r=20Falvai?= Date: Tue, 23 Jul 2024 16:15:12 +0200 Subject: [PATCH] Fix file size upload param (#204) * Fix file size upload param * Fix vendor * Fix? * Query file size only once * Revert unintentional change --- go.mod | 1 + go.sum | 2 + report/api/api.go | 11 +- uploaders/aabuploader.go | 10 +- uploaders/apkuploader.go | 10 +- uploaders/common.go | 44 ++-- uploaders/common_test.go | 14 +- uploaders/fileuploader.go | 15 +- uploaders/ipauploader.go | 10 +- uploaders/utils.go | 23 +-- uploaders/xcarchiveuploader.go | 10 +- .../docker/go-units/CONTRIBUTING.md | 67 ++++++ vendor/github.com/docker/go-units/LICENSE | 191 ++++++++++++++++++ vendor/github.com/docker/go-units/MAINTAINERS | 46 +++++ vendor/github.com/docker/go-units/README.md | 16 ++ vendor/github.com/docker/go-units/circle.yml | 11 + vendor/github.com/docker/go-units/duration.go | 35 ++++ vendor/github.com/docker/go-units/size.go | 154 ++++++++++++++ vendor/github.com/docker/go-units/ulimit.go | 123 +++++++++++ vendor/modules.txt | 3 + 20 files changed, 729 insertions(+), 67 deletions(-) create mode 100644 vendor/github.com/docker/go-units/CONTRIBUTING.md create mode 100644 vendor/github.com/docker/go-units/LICENSE create mode 100644 vendor/github.com/docker/go-units/MAINTAINERS create mode 100644 vendor/github.com/docker/go-units/README.md create mode 100644 vendor/github.com/docker/go-units/circle.yml create mode 100644 vendor/github.com/docker/go-units/duration.go create mode 100644 vendor/github.com/docker/go-units/size.go create mode 100644 vendor/github.com/docker/go-units/ulimit.go diff --git a/go.mod b/go.mod index 46cb50f1..77294332 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.22 github.com/bitrise-io/go-xcode v1.0.18 github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.44 + github.com/docker/go-units v0.5.0 github.com/google/go-cmp v0.6.0 github.com/gorilla/mux v1.8.0 github.com/hashicorp/go-retryablehttp v0.7.7 diff --git a/go.sum b/go.sum index 395a8936..2e77434b 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= diff --git a/report/api/api.go b/report/api/api.go index eacb3a94..0ba6c178 100644 --- a/report/api/api.go +++ b/report/api/api.go @@ -7,6 +7,7 @@ import ( "io" "net/http" "net/http/httputil" + "os" "github.com/bitrise-io/go-utils/retry" "github.com/bitrise-io/go-utils/v2/log" @@ -79,7 +80,15 @@ func (t *TestReportClient) CreateReport(params CreateReportParameters) (CreateRe // UploadAsset ... func (t *TestReportClient) UploadAsset(url, path, contentType string) error { - return uploaders.UploadArtifact(url, path, contentType) + fileInfo, err := os.Stat(path) + if err != nil { + return err + } + artifact := uploaders.ArtifactArgs { + Path: path, + FileSize: fileInfo.Size(), + } + return uploaders.UploadArtifact(url, artifact, contentType) } // FinishReport ... diff --git a/uploaders/aabuploader.go b/uploaders/aabuploader.go index 7bde816c..e28ad366 100644 --- a/uploaders/aabuploader.go +++ b/uploaders/aabuploader.go @@ -57,7 +57,7 @@ func DeployAAB(item deployment.DeployableItem, artifacts []string, buildURL, tok info := androidartifact.ParseArtifactPath(pth) aabInfoMap := map[string]interface{}{ - "file_size_bytes": fmt.Sprintf("%f", fileSize), + "file_size_bytes": fmt.Sprintf("%d", fileSize), "app_info": appInfo, "module": info.Module, "product_flavour": info.ProductFlavour, @@ -83,12 +83,16 @@ func DeployAAB(item deployment.DeployableItem, artifacts []string, buildURL, tok // --- const AABContentType = "application/octet-stream aab" - uploadURL, artifactID, err := createArtifact(buildURL, token, pth, "android-apk", AABContentType) + artifact := ArtifactArgs { + Path: pth, + FileSize: fileSize, + } + uploadURL, artifactID, err := createArtifact(buildURL, token, artifact, "android-apk", AABContentType) if err != nil { return ArtifactURLs{}, fmt.Errorf("failed to create apk artifact: %s %w", pth, err) } - if err := UploadArtifact(uploadURL, pth, AABContentType); err != nil { + if err := UploadArtifact(uploadURL, artifact, AABContentType); err != nil { return ArtifactURLs{}, fmt.Errorf("failed to upload apk artifact, error: %s", err) } diff --git a/uploaders/apkuploader.go b/uploaders/apkuploader.go index a8951d94..6482281c 100644 --- a/uploaders/apkuploader.go +++ b/uploaders/apkuploader.go @@ -48,7 +48,7 @@ func DeployAPK(item deployment.DeployableItem, artifacts []string, buildURL, tok info := androidartifact.ParseArtifactPath(pth) apkInfoMap := map[string]interface{}{ - "file_size_bytes": fmt.Sprintf("%f", fileSize), + "file_size_bytes": fmt.Sprintf("%d", fileSize), "app_info": appInfo, "module": info.Module, "product_flavour": info.ProductFlavour, @@ -67,12 +67,16 @@ func DeployAPK(item deployment.DeployableItem, artifacts []string, buildURL, tok // --- const APKContentType = "application/vnd.android.package-archive" - uploadURL, artifactID, err := createArtifact(buildURL, token, pth, "android-apk", APKContentType) + artifact := ArtifactArgs { + Path: pth, + FileSize: fileSize, + } + uploadURL, artifactID, err := createArtifact(buildURL, token, artifact, "android-apk", APKContentType) if err != nil { return ArtifactURLs{}, fmt.Errorf("failed to create apk artifact: %s %w", pth, err) } - if err := UploadArtifact(uploadURL, pth, APKContentType); err != nil { + if err := UploadArtifact(uploadURL, artifact, APKContentType); err != nil { return ArtifactURLs{}, fmt.Errorf("failed to upload apk artifact, error: %s", err) } diff --git a/uploaders/common.go b/uploaders/common.go index cb0ee4c3..e689f99f 100644 --- a/uploaders/common.go +++ b/uploaders/common.go @@ -15,20 +15,20 @@ import ( "time" "github.com/bitrise-steplib/steps-deploy-to-bitrise-io/deployment" + + "github.com/docker/go-units" "github.com/bitrise-io/go-utils/log" "github.com/bitrise-io/go-utils/retry" "github.com/bitrise-io/go-utils/urlutil" ) -// ArtifactURLs ... type ArtifactURLs struct { PublicInstallPageURL string PermanentDownloadURL string DetailsPageURL string } -// AppDeploymentMetaData ... type AppDeploymentMetaData struct { ArtifactInfo map[string]interface{} NotifyUserGroups string @@ -36,22 +36,16 @@ type AppDeploymentMetaData struct { IsEnablePublicPage bool } -func createArtifact(buildURL, token, artifactPth, artifactType, contentType string) (string, string, error) { +type ArtifactArgs struct { + Path string + FileSize int64 // bytes +} + +func createArtifact(buildURL, token string, artifact ArtifactArgs, artifactType, contentType string) (string, string, error) { // create form data - artifactName := filepath.Base(artifactPth) - fileSize, err := fileSizeInBytes(artifactPth) - if err != nil { - return "", "", fmt.Errorf("failed to get file size, error: %s", err) - } + artifactName := filepath.Base(artifact.Path) - megaBytes := fileSize / 1024.0 / 1024.0 - roundedMegaBytes := int(roundPlus(megaBytes, 2)) - - if roundedMegaBytes < 1 { - log.Printf("file size: %dB", int(fileSize)) - } else { - log.Printf("file size: %dMB", roundedMegaBytes) - } + log.Printf("file size: %s", units.BytesSize(float64(artifact.FileSize))) if strings.TrimSpace(token) == "" { return "", "", fmt.Errorf("provided API token is empty") @@ -62,7 +56,7 @@ func createArtifact(buildURL, token, artifactPth, artifactType, contentType stri "title": {artifactName}, "filename": {artifactName}, "artifact_type": {artifactType}, - "file_size_bytes": {fmt.Sprintf("%d", int(fileSize))}, + "file_size_bytes": {fmt.Sprintf("%d", artifact.FileSize)}, "content_type": {contentType}, } // --- @@ -137,14 +131,13 @@ func createArtifact(buildURL, token, artifactPth, artifactType, contentType stri return artifactResponse.UploadURL, fmt.Sprintf("%d", artifactResponse.ID), nil } -// UploadArtifact ... -func UploadArtifact(uploadURL, artifactPth, contentType string) error { +func UploadArtifact(uploadURL string, artifact ArtifactArgs, contentType string) error { netClient := &http.Client{ Timeout: 10 * time.Minute, } return retry.Times(3).Wait(5).Try(func(attempt uint) error { - file, err := os.Open(artifactPth) + file, err := os.Open(artifact.Path) if err != nil { return fmt.Errorf("failed to open artifact, error: %s", err) } @@ -154,14 +147,9 @@ func UploadArtifact(uploadURL, artifactPth, contentType string) error { } }() - fileInfo, err := file.Stat() - if err != nil { - return fmt.Errorf("failed to get file info for %s, error: %s", artifactPth, err) - } - // Initializes request body to nil to send a Content-Length of 0: https://github.com/golang/go/issues/20257#issuecomment-299509391 var reqBody io.Reader - if fileInfo.Size() > 0 { + if artifact.FileSize > 0 { reqBody = io.NopCloser(file) } @@ -174,8 +162,8 @@ func UploadArtifact(uploadURL, artifactPth, contentType string) error { request.Header.Add("Content-Type", contentType) } - request.Header.Add("X-Upload-Content-Length", strconv.FormatInt(fileInfo.Size(), 10)) // header used by Google Cloud Storage signed URLs - request.ContentLength = fileInfo.Size() + request.Header.Add("X-Upload-Content-Length", strconv.FormatInt(artifact.FileSize, 10)) // header used by Google Cloud Storage signed URLs + request.ContentLength = artifact.FileSize ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) defer cancel() diff --git a/uploaders/common_test.go b/uploaders/common_test.go index d33961a1..2bfcf3c1 100644 --- a/uploaders/common_test.go +++ b/uploaders/common_test.go @@ -1,16 +1,18 @@ package uploaders import ( - "os" - "io" "image" "image/png" + "io" "math/rand" "net/http" "net/http/httptest" + "os" "path/filepath" "strconv" "testing" + + "github.com/stretchr/testify/require" ) func Test_uploadArtifact(t *testing.T) { @@ -90,7 +92,13 @@ func Test_uploadArtifact(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := UploadArtifact(tt.uploadURL, tt.artifactPth, tt.contentType); (err != nil) != tt.wantErr { + fileInfo, err := os.Stat(tt.artifactPth) + require.NoError(t, err) + artifact := ArtifactArgs { + Path: tt.artifactPth, + FileSize: fileInfo.Size(), + } + if err := UploadArtifact(tt.uploadURL, artifact, tt.contentType); (err != nil) != tt.wantErr { t.Errorf("UploadArtifact() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/uploaders/fileuploader.go b/uploaders/fileuploader.go index db6527aa..a655e5b3 100644 --- a/uploaders/fileuploader.go +++ b/uploaders/fileuploader.go @@ -8,13 +8,20 @@ import ( // DeployFile ... func DeployFile(item deployment.DeployableItem, buildURL, token string) (ArtifactURLs, error) { - pth := item.Path - uploadURL, artifactID, err := createArtifact(buildURL, token, pth, "file", "") + fileSize, err := fileSizeInBytes(item.Path) if err != nil { - return ArtifactURLs{}, fmt.Errorf("failed to create file artifact: %s %w", pth, err) + return ArtifactURLs{}, fmt.Errorf("get file size: %s", err) + } + artifact := ArtifactArgs { + Path: item.Path, + FileSize: fileSize, + } + uploadURL, artifactID, err := createArtifact(buildURL, token, artifact, "file", "") + if err != nil { + return ArtifactURLs{}, fmt.Errorf("create file artifact: %s %w", artifact.Path, err) } - if err := UploadArtifact(uploadURL, pth, ""); err != nil { + if err := UploadArtifact(uploadURL, artifact, ""); err != nil { return ArtifactURLs{}, fmt.Errorf("failed to upload file artifact, error: %s", err) } diff --git a/uploaders/ipauploader.go b/uploaders/ipauploader.go index 39b5fbd1..8c528eca 100644 --- a/uploaders/ipauploader.go +++ b/uploaders/ipauploader.go @@ -32,7 +32,7 @@ func DeployIPA(item deployment.DeployableItem, buildURL, token, notifyUserGroups } ipaInfoMap := map[string]interface{}{ - "file_size_bytes": fmt.Sprintf("%f", fileSize), + "file_size_bytes": fmt.Sprintf("%d", fileSize), "app_info": appInfo, "provisioning_info": provisioningInfo, } @@ -40,12 +40,16 @@ func DeployIPA(item deployment.DeployableItem, buildURL, token, notifyUserGroups logger.Printf("ipa infos: %v", appInfo) const IPAContentType = "application/octet-stream ipa" - uploadURL, artifactID, err := createArtifact(buildURL, token, pth, "ios-ipa", IPAContentType) + artifact := ArtifactArgs { + Path: pth, + FileSize: fileSize, + } + uploadURL, artifactID, err := createArtifact(buildURL, token, artifact, "ios-ipa", IPAContentType) if err != nil { return ArtifactURLs{}, fmt.Errorf("failed to create ipa artifact from %s: %w", pth, err) } - if err := UploadArtifact(uploadURL, pth, IPAContentType); err != nil { + if err := UploadArtifact(uploadURL, artifact, IPAContentType); err != nil { return ArtifactURLs{}, fmt.Errorf("failed to upload ipa (%s): %w", pth, err) } diff --git a/uploaders/utils.go b/uploaders/utils.go index bc1aeeb5..65828797 100644 --- a/uploaders/utils.go +++ b/uploaders/utils.go @@ -1,28 +1,13 @@ package uploaders import ( - "fmt" - "math" - - "github.com/bitrise-io/go-utils/pathutil" + "os" ) -func round(f float64) float64 { - return math.Floor(f + .5) -} - -func roundPlus(f float64, places int) float64 { - shift := math.Pow(10, float64(places)) - return round(f*shift) / shift -} - -func fileSizeInBytes(pth string) (float64, error) { - info, exist, err := pathutil.PathCheckAndInfos(pth) +func fileSizeInBytes(pth string) (int64, error) { + finfo, err := os.Stat(pth) if err != nil { return 0, err } - if !exist { - return 0, fmt.Errorf("file not exist at: %s", pth) - } - return float64(info.Size()), nil + return finfo.Size(), nil } diff --git a/uploaders/xcarchiveuploader.go b/uploaders/xcarchiveuploader.go index eebce921..8e56c3ae 100644 --- a/uploaders/xcarchiveuploader.go +++ b/uploaders/xcarchiveuploader.go @@ -25,19 +25,23 @@ func DeployXcarchive(item deployment.DeployableItem, buildURL, token string) (Ar } xcarchiveInfoMap := map[string]interface{}{ - "file_size_bytes": fmt.Sprintf("%f", fileSize), + "file_size_bytes": fmt.Sprintf("%d", fileSize), "app_info": appInfo, "scheme": scheme, } logger.Printf("xcarchive infos: %v", appInfo) - uploadURL, artifactID, err := createArtifact(buildURL, token, pth, "ios-xcarchive", "") + artifact := ArtifactArgs { + Path: pth, + FileSize: fileSize, + } + uploadURL, artifactID, err := createArtifact(buildURL, token, artifact, "ios-xcarchive", "") if err != nil { return ArtifactURLs{}, fmt.Errorf("failed to create xcarchive artifact from %s %w", pth, err) } - if err := UploadArtifact(uploadURL, pth, ""); err != nil { + if err := UploadArtifact(uploadURL, artifact, ""); err != nil { return ArtifactURLs{}, fmt.Errorf("failed to upload xcarchive (%s): %w", pth, err) } diff --git a/vendor/github.com/docker/go-units/CONTRIBUTING.md b/vendor/github.com/docker/go-units/CONTRIBUTING.md new file mode 100644 index 00000000..9ea86d78 --- /dev/null +++ b/vendor/github.com/docker/go-units/CONTRIBUTING.md @@ -0,0 +1,67 @@ +# Contributing to go-units + +Want to hack on go-units? Awesome! Here are instructions to get you started. + +go-units is a part of the [Docker](https://www.docker.com) project, and follows +the same rules and principles. If you're already familiar with the way +Docker does things, you'll feel right at home. + +Otherwise, go read Docker's +[contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md), +[issue triaging](https://github.com/docker/docker/blob/master/project/ISSUE-TRIAGE.md), +[review process](https://github.com/docker/docker/blob/master/project/REVIEWING.md) and +[branches and tags](https://github.com/docker/docker/blob/master/project/BRANCHES-AND-TAGS.md). + +### Sign your work + +The sign-off is a simple line at the end of the explanation for the patch. Your +signature certifies that you wrote the patch or otherwise have the right to pass +it on as an open-source patch. The rules are pretty simple: if you can certify +the below (from [developercertificate.org](http://developercertificate.org/)): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +660 York Street, Suite 102, +San Francisco, CA 94110 USA + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +Then you just add a line to every git commit message: + + Signed-off-by: Joe Smith + +Use your real name (sorry, no pseudonyms or anonymous contributions.) + +If you set your `user.name` and `user.email` git configs, you can sign your +commit automatically with `git commit -s`. diff --git a/vendor/github.com/docker/go-units/LICENSE b/vendor/github.com/docker/go-units/LICENSE new file mode 100644 index 00000000..b55b37bc --- /dev/null +++ b/vendor/github.com/docker/go-units/LICENSE @@ -0,0 +1,191 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2015 Docker, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/docker/go-units/MAINTAINERS b/vendor/github.com/docker/go-units/MAINTAINERS new file mode 100644 index 00000000..4aac7c74 --- /dev/null +++ b/vendor/github.com/docker/go-units/MAINTAINERS @@ -0,0 +1,46 @@ +# go-units maintainers file +# +# This file describes who runs the docker/go-units project and how. +# This is a living document - if you see something out of date or missing, speak up! +# +# It is structured to be consumable by both humans and programs. +# To extract its contents programmatically, use any TOML-compliant parser. +# +# This file is compiled into the MAINTAINERS file in docker/opensource. +# +[Org] + [Org."Core maintainers"] + people = [ + "akihirosuda", + "dnephin", + "thajeztah", + "vdemeester", + ] + +[people] + +# A reference list of all people associated with the project. +# All other sections should refer to people by their canonical key +# in the people section. + + # ADD YOURSELF HERE IN ALPHABETICAL ORDER + + [people.akihirosuda] + Name = "Akihiro Suda" + Email = "akihiro.suda.cz@hco.ntt.co.jp" + GitHub = "AkihiroSuda" + + [people.dnephin] + Name = "Daniel Nephin" + Email = "dnephin@gmail.com" + GitHub = "dnephin" + + [people.thajeztah] + Name = "Sebastiaan van Stijn" + Email = "github@gone.nl" + GitHub = "thaJeztah" + + [people.vdemeester] + Name = "Vincent Demeester" + Email = "vincent@sbr.pm" + GitHub = "vdemeester" \ No newline at end of file diff --git a/vendor/github.com/docker/go-units/README.md b/vendor/github.com/docker/go-units/README.md new file mode 100644 index 00000000..4f70a4e1 --- /dev/null +++ b/vendor/github.com/docker/go-units/README.md @@ -0,0 +1,16 @@ +[![GoDoc](https://godoc.org/github.com/docker/go-units?status.svg)](https://godoc.org/github.com/docker/go-units) + +# Introduction + +go-units is a library to transform human friendly measurements into machine friendly values. + +## Usage + +See the [docs in godoc](https://godoc.org/github.com/docker/go-units) for examples and documentation. + +## Copyright and license + +Copyright © 2015 Docker, Inc. + +go-units is licensed under the Apache License, Version 2.0. +See [LICENSE](LICENSE) for the full text of the license. diff --git a/vendor/github.com/docker/go-units/circle.yml b/vendor/github.com/docker/go-units/circle.yml new file mode 100644 index 00000000..af9d6055 --- /dev/null +++ b/vendor/github.com/docker/go-units/circle.yml @@ -0,0 +1,11 @@ +dependencies: + post: + # install golint + - go get golang.org/x/lint/golint + +test: + pre: + # run analysis before tests + - go vet ./... + - test -z "$(golint ./... | tee /dev/stderr)" + - test -z "$(gofmt -s -l . | tee /dev/stderr)" diff --git a/vendor/github.com/docker/go-units/duration.go b/vendor/github.com/docker/go-units/duration.go new file mode 100644 index 00000000..48dd8744 --- /dev/null +++ b/vendor/github.com/docker/go-units/duration.go @@ -0,0 +1,35 @@ +// Package units provides helper function to parse and print size and time units +// in human-readable format. +package units + +import ( + "fmt" + "time" +) + +// HumanDuration returns a human-readable approximation of a duration +// (eg. "About a minute", "4 hours ago", etc.). +func HumanDuration(d time.Duration) string { + if seconds := int(d.Seconds()); seconds < 1 { + return "Less than a second" + } else if seconds == 1 { + return "1 second" + } else if seconds < 60 { + return fmt.Sprintf("%d seconds", seconds) + } else if minutes := int(d.Minutes()); minutes == 1 { + return "About a minute" + } else if minutes < 60 { + return fmt.Sprintf("%d minutes", minutes) + } else if hours := int(d.Hours() + 0.5); hours == 1 { + return "About an hour" + } else if hours < 48 { + return fmt.Sprintf("%d hours", hours) + } else if hours < 24*7*2 { + return fmt.Sprintf("%d days", hours/24) + } else if hours < 24*30*2 { + return fmt.Sprintf("%d weeks", hours/24/7) + } else if hours < 24*365*2 { + return fmt.Sprintf("%d months", hours/24/30) + } + return fmt.Sprintf("%d years", int(d.Hours())/24/365) +} diff --git a/vendor/github.com/docker/go-units/size.go b/vendor/github.com/docker/go-units/size.go new file mode 100644 index 00000000..c245a895 --- /dev/null +++ b/vendor/github.com/docker/go-units/size.go @@ -0,0 +1,154 @@ +package units + +import ( + "fmt" + "strconv" + "strings" +) + +// See: http://en.wikipedia.org/wiki/Binary_prefix +const ( + // Decimal + + KB = 1000 + MB = 1000 * KB + GB = 1000 * MB + TB = 1000 * GB + PB = 1000 * TB + + // Binary + + KiB = 1024 + MiB = 1024 * KiB + GiB = 1024 * MiB + TiB = 1024 * GiB + PiB = 1024 * TiB +) + +type unitMap map[byte]int64 + +var ( + decimalMap = unitMap{'k': KB, 'm': MB, 'g': GB, 't': TB, 'p': PB} + binaryMap = unitMap{'k': KiB, 'm': MiB, 'g': GiB, 't': TiB, 'p': PiB} +) + +var ( + decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"} + binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"} +) + +func getSizeAndUnit(size float64, base float64, _map []string) (float64, string) { + i := 0 + unitsLimit := len(_map) - 1 + for size >= base && i < unitsLimit { + size = size / base + i++ + } + return size, _map[i] +} + +// CustomSize returns a human-readable approximation of a size +// using custom format. +func CustomSize(format string, size float64, base float64, _map []string) string { + size, unit := getSizeAndUnit(size, base, _map) + return fmt.Sprintf(format, size, unit) +} + +// HumanSizeWithPrecision allows the size to be in any precision, +// instead of 4 digit precision used in units.HumanSize. +func HumanSizeWithPrecision(size float64, precision int) string { + size, unit := getSizeAndUnit(size, 1000.0, decimapAbbrs) + return fmt.Sprintf("%.*g%s", precision, size, unit) +} + +// HumanSize returns a human-readable approximation of a size +// capped at 4 valid numbers (eg. "2.746 MB", "796 KB"). +func HumanSize(size float64) string { + return HumanSizeWithPrecision(size, 4) +} + +// BytesSize returns a human-readable size in bytes, kibibytes, +// mebibytes, gibibytes, or tebibytes (eg. "44kiB", "17MiB"). +func BytesSize(size float64) string { + return CustomSize("%.4g%s", size, 1024.0, binaryAbbrs) +} + +// FromHumanSize returns an integer from a human-readable specification of a +// size using SI standard (eg. "44kB", "17MB"). +func FromHumanSize(size string) (int64, error) { + return parseSize(size, decimalMap) +} + +// RAMInBytes parses a human-readable string representing an amount of RAM +// in bytes, kibibytes, mebibytes, gibibytes, or tebibytes and +// returns the number of bytes, or -1 if the string is unparseable. +// Units are case-insensitive, and the 'b' suffix is optional. +func RAMInBytes(size string) (int64, error) { + return parseSize(size, binaryMap) +} + +// Parses the human-readable size string into the amount it represents. +func parseSize(sizeStr string, uMap unitMap) (int64, error) { + // TODO: rewrite to use strings.Cut if there's a space + // once Go < 1.18 is deprecated. + sep := strings.LastIndexAny(sizeStr, "01234567890. ") + if sep == -1 { + // There should be at least a digit. + return -1, fmt.Errorf("invalid size: '%s'", sizeStr) + } + var num, sfx string + if sizeStr[sep] != ' ' { + num = sizeStr[:sep+1] + sfx = sizeStr[sep+1:] + } else { + // Omit the space separator. + num = sizeStr[:sep] + sfx = sizeStr[sep+1:] + } + + size, err := strconv.ParseFloat(num, 64) + if err != nil { + return -1, err + } + // Backward compatibility: reject negative sizes. + if size < 0 { + return -1, fmt.Errorf("invalid size: '%s'", sizeStr) + } + + if len(sfx) == 0 { + return int64(size), nil + } + + // Process the suffix. + + if len(sfx) > 3 { // Too long. + goto badSuffix + } + sfx = strings.ToLower(sfx) + // Trivial case: b suffix. + if sfx[0] == 'b' { + if len(sfx) > 1 { // no extra characters allowed after b. + goto badSuffix + } + return int64(size), nil + } + // A suffix from the map. + if mul, ok := uMap[sfx[0]]; ok { + size *= float64(mul) + } else { + goto badSuffix + } + + // The suffix may have extra "b" or "ib" (e.g. KiB or MB). + switch { + case len(sfx) == 2 && sfx[1] != 'b': + goto badSuffix + case len(sfx) == 3 && sfx[1:] != "ib": + goto badSuffix + } + + return int64(size), nil + +badSuffix: + return -1, fmt.Errorf("invalid suffix: '%s'", sfx) +} diff --git a/vendor/github.com/docker/go-units/ulimit.go b/vendor/github.com/docker/go-units/ulimit.go new file mode 100644 index 00000000..fca0400c --- /dev/null +++ b/vendor/github.com/docker/go-units/ulimit.go @@ -0,0 +1,123 @@ +package units + +import ( + "fmt" + "strconv" + "strings" +) + +// Ulimit is a human friendly version of Rlimit. +type Ulimit struct { + Name string + Hard int64 + Soft int64 +} + +// Rlimit specifies the resource limits, such as max open files. +type Rlimit struct { + Type int `json:"type,omitempty"` + Hard uint64 `json:"hard,omitempty"` + Soft uint64 `json:"soft,omitempty"` +} + +const ( + // magic numbers for making the syscall + // some of these are defined in the syscall package, but not all. + // Also since Windows client doesn't get access to the syscall package, need to + // define these here + rlimitAs = 9 + rlimitCore = 4 + rlimitCPU = 0 + rlimitData = 2 + rlimitFsize = 1 + rlimitLocks = 10 + rlimitMemlock = 8 + rlimitMsgqueue = 12 + rlimitNice = 13 + rlimitNofile = 7 + rlimitNproc = 6 + rlimitRss = 5 + rlimitRtprio = 14 + rlimitRttime = 15 + rlimitSigpending = 11 + rlimitStack = 3 +) + +var ulimitNameMapping = map[string]int{ + //"as": rlimitAs, // Disabled since this doesn't seem usable with the way Docker inits a container. + "core": rlimitCore, + "cpu": rlimitCPU, + "data": rlimitData, + "fsize": rlimitFsize, + "locks": rlimitLocks, + "memlock": rlimitMemlock, + "msgqueue": rlimitMsgqueue, + "nice": rlimitNice, + "nofile": rlimitNofile, + "nproc": rlimitNproc, + "rss": rlimitRss, + "rtprio": rlimitRtprio, + "rttime": rlimitRttime, + "sigpending": rlimitSigpending, + "stack": rlimitStack, +} + +// ParseUlimit parses and returns a Ulimit from the specified string. +func ParseUlimit(val string) (*Ulimit, error) { + parts := strings.SplitN(val, "=", 2) + if len(parts) != 2 { + return nil, fmt.Errorf("invalid ulimit argument: %s", val) + } + + if _, exists := ulimitNameMapping[parts[0]]; !exists { + return nil, fmt.Errorf("invalid ulimit type: %s", parts[0]) + } + + var ( + soft int64 + hard = &soft // default to soft in case no hard was set + temp int64 + err error + ) + switch limitVals := strings.Split(parts[1], ":"); len(limitVals) { + case 2: + temp, err = strconv.ParseInt(limitVals[1], 10, 64) + if err != nil { + return nil, err + } + hard = &temp + fallthrough + case 1: + soft, err = strconv.ParseInt(limitVals[0], 10, 64) + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("too many limit value arguments - %s, can only have up to two, `soft[:hard]`", parts[1]) + } + + if *hard != -1 { + if soft == -1 { + return nil, fmt.Errorf("ulimit soft limit must be less than or equal to hard limit: soft: -1 (unlimited), hard: %d", *hard) + } + if soft > *hard { + return nil, fmt.Errorf("ulimit soft limit must be less than or equal to hard limit: %d > %d", soft, *hard) + } + } + + return &Ulimit{Name: parts[0], Soft: soft, Hard: *hard}, nil +} + +// GetRlimit returns the RLimit corresponding to Ulimit. +func (u *Ulimit) GetRlimit() (*Rlimit, error) { + t, exists := ulimitNameMapping[u.Name] + if !exists { + return nil, fmt.Errorf("invalid ulimit name %s", u.Name) + } + + return &Rlimit{Type: t, Soft: uint64(u.Soft), Hard: uint64(u.Hard)}, nil +} + +func (u *Ulimit) String() string { + return fmt.Sprintf("%s=%d:%d", u.Name, u.Soft, u.Hard) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 713edbc1..8f053245 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -72,6 +72,9 @@ github.com/bitrise-io/stepman/models # github.com/davecgh/go-spew v1.1.1 ## explicit github.com/davecgh/go-spew/spew +# github.com/docker/go-units v0.5.0 +## explicit +github.com/docker/go-units # github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa ## explicit github.com/fullsailor/pkcs7