mirror of
https://github.com/containers/podman.git
synced 2025-06-18 15:39:08 +08:00
vendor github.com/containers/image/v5@v5.2.0
See release notes: https://github.com/containers/image/releases/tag/v5.2.0 Fixes: #4877 Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
2
go.mod
2
go.mod
@ -12,7 +12,7 @@ require (
|
||||
github.com/containernetworking/plugins v0.8.5
|
||||
github.com/containers/buildah v1.13.1
|
||||
github.com/containers/conmon v2.0.10+incompatible
|
||||
github.com/containers/image/v5 v5.1.0
|
||||
github.com/containers/image/v5 v5.2.0
|
||||
github.com/containers/psgo v1.4.0
|
||||
github.com/containers/storage v1.15.8
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
|
||||
|
8
go.sum
8
go.sum
@ -30,6 +30,8 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
|
||||
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
||||
@ -91,6 +93,8 @@ github.com/containers/image/v5 v5.0.0 h1:arnXgbt1ucsC/ndtSpiQY87rA0UjhF+/xQnPzqd
|
||||
github.com/containers/image/v5 v5.0.0/go.mod h1:MgiLzCfIeo8lrHi+4Lb8HP+rh513sm0Mlk6RrhjFOLY=
|
||||
github.com/containers/image/v5 v5.1.0 h1:5FjAvPJniamuNNIQHkh4PnsL+n+xzs6Aonzaz5dqTEo=
|
||||
github.com/containers/image/v5 v5.1.0/go.mod h1:BKlMD34WxRo1ruGHHEOrPQP0Qci7SWoPwU6fS7arsCU=
|
||||
github.com/containers/image/v5 v5.2.0 h1:DowY5OII5x9Pb6Pt76vnHU79BgG4/jdwhZjeAj2R+t8=
|
||||
github.com/containers/image/v5 v5.2.0/go.mod h1:IAub4gDGvXoxaIAdNy4e3FbVTDPVNMv9F0UfVVFbYCU=
|
||||
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
|
||||
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
|
||||
github.com/containers/ocicrypt v0.0.0-20190930154801-b87a4a69c741 h1:8tQkOcednLJtUcZgK7sPglscXtxvMOnFOa6wd09VWLM=
|
||||
@ -370,6 +374,8 @@ github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618 h1:7InQ7/zrOh6Sl
|
||||
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0=
|
||||
github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c h1:xa+eQWKuJ9MbB9FBL/eoNvDFvveAkz2LQoz8PzX7Q/4=
|
||||
github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c/go.mod h1:GhAqVMEWnTcW2dxoD/SO3n2enrgWl3y6Dnx4m59GvcA=
|
||||
github.com/mtrmac/gpgme v0.1.1 h1:a5ISnvahzTzBH0m/klhehN68N+9+/jLwhpPFtH3oPAQ=
|
||||
github.com/mtrmac/gpgme v0.1.1/go.mod h1:GYYHnGSuS7HK3zVS2n3y73y0okK/BeKzwnn5jgiVFNI=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
@ -544,6 +550,8 @@ github.com/vbauerster/mpb v3.4.0+incompatible h1:mfiiYw87ARaeRW6x5gWwYRUawxaW1tL
|
||||
github.com/vbauerster/mpb v3.4.0+incompatible/go.mod h1:zAHG26FUhVKETRu+MWqYXcI70POlC6N8up9p1dID7SU=
|
||||
github.com/vbauerster/mpb/v4 v4.11.1 h1:ZOYQSVHgmeanXsbyC44aDg76tBGCS/54Rk8VkL8dJGA=
|
||||
github.com/vbauerster/mpb/v4 v4.11.1/go.mod h1:vMLa1J/ZKC83G2lB/52XpqT+ZZtFG4aZOdKhmpRL1uM=
|
||||
github.com/vbauerster/mpb/v4 v4.11.2 h1:ynkUoKzi65DZ1UsQPx7sgi/KN6G9f7br+Us2nKm35AM=
|
||||
github.com/vbauerster/mpb/v4 v4.11.2/go.mod h1:jIuIRCltGJUnm6DCyPVkwjlLUk4nHTH+m4eD14CdFF0=
|
||||
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
||||
github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM=
|
||||
github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
||||
|
21
vendor/github.com/acarl005/stripansi/LICENSE
generated
vendored
Normal file
21
vendor/github.com/acarl005/stripansi/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Andrew Carlson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
30
vendor/github.com/acarl005/stripansi/README.md
generated
vendored
Normal file
30
vendor/github.com/acarl005/stripansi/README.md
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
Strip ANSI
|
||||
==========
|
||||
|
||||
This Go package removes ANSI escape codes from strings.
|
||||
|
||||
Ideally, we would prevent these from appearing in any text we want to process.
|
||||
However, sometimes this can't be helped, and we need to be able to deal with that noise.
|
||||
This will use a regexp to remove those unwanted escape codes.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
$ go get -u github.com/acarl005/stripansi
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/acarl005/stripansi"
|
||||
)
|
||||
|
||||
func main() {
|
||||
msg := "\x1b[38;5;140m foo\x1b[0m bar"
|
||||
cleanMsg := stripansi.Strip(msg)
|
||||
fmt.Println(cleanMsg) // " foo bar"
|
||||
}
|
||||
```
|
13
vendor/github.com/acarl005/stripansi/stripansi.go
generated
vendored
Normal file
13
vendor/github.com/acarl005/stripansi/stripansi.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
package stripansi
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
)
|
||||
|
||||
const ansi = "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))"
|
||||
|
||||
var re = regexp.MustCompile(ansi)
|
||||
|
||||
func Strip(str string) string {
|
||||
return re.ReplaceAllString(str, "")
|
||||
}
|
4
vendor/github.com/containers/image/v5/copy/copy.go
generated
vendored
4
vendor/github.com/containers/image/v5/copy/copy.go
generated
vendored
@ -709,7 +709,7 @@ func checkImageDestinationForCurrentRuntime(ctx context.Context, sys *types.Syst
|
||||
wantedOS = sys.OSChoice
|
||||
}
|
||||
if wantedOS != c.OS {
|
||||
return fmt.Errorf("Image operating system mismatch: image uses %q, expecting %q", c.OS, wantedOS)
|
||||
logrus.Infof("Image operating system mismatch: image uses %q, expecting %q", c.OS, wantedOS)
|
||||
}
|
||||
|
||||
wantedArch := runtime.GOARCH
|
||||
@ -717,7 +717,7 @@ func checkImageDestinationForCurrentRuntime(ctx context.Context, sys *types.Syst
|
||||
wantedArch = sys.ArchitectureChoice
|
||||
}
|
||||
if wantedArch != c.Architecture {
|
||||
return fmt.Errorf("Image architecture mismatch: image uses %q, expecting %q", c.Architecture, wantedArch)
|
||||
logrus.Infof("Image architecture mismatch: image uses %q, expecting %q", c.Architecture, wantedArch)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
21
vendor/github.com/containers/image/v5/directory/directory_dest.go
generated
vendored
21
vendor/github.com/containers/image/v5/directory/directory_dest.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
@ -142,8 +143,11 @@ func (d *dirImageDestination) PutBlob(ctx context.Context, stream io.Reader, inp
|
||||
return types.BlobInfo{}, err
|
||||
}
|
||||
succeeded := false
|
||||
explicitClosed := false
|
||||
defer func() {
|
||||
blobFile.Close()
|
||||
if !explicitClosed {
|
||||
blobFile.Close()
|
||||
}
|
||||
if !succeeded {
|
||||
os.Remove(blobFile.Name())
|
||||
}
|
||||
@ -164,10 +168,21 @@ func (d *dirImageDestination) PutBlob(ctx context.Context, stream io.Reader, inp
|
||||
if err := blobFile.Sync(); err != nil {
|
||||
return types.BlobInfo{}, err
|
||||
}
|
||||
if err := blobFile.Chmod(0644); err != nil {
|
||||
return types.BlobInfo{}, err
|
||||
|
||||
// On POSIX systems, blobFile was created with mode 0600, so we need to make it readable.
|
||||
// On Windows, the “permissions of newly created files” argument to syscall.Open is
|
||||
// ignored and the file is already readable; besides, blobFile.Chmod, i.e. syscall.Fchmod,
|
||||
// always fails on Windows.
|
||||
if runtime.GOOS != "windows" {
|
||||
if err := blobFile.Chmod(0644); err != nil {
|
||||
return types.BlobInfo{}, err
|
||||
}
|
||||
}
|
||||
|
||||
blobPath := d.ref.layerPath(computedDigest)
|
||||
// need to explicitly close the file, since a rename won't otherwise not work on Windows
|
||||
blobFile.Close()
|
||||
explicitClosed = true
|
||||
if err := os.Rename(blobFile.Name(), blobPath); err != nil {
|
||||
return types.BlobInfo{}, err
|
||||
}
|
||||
|
128
vendor/github.com/containers/image/v5/docker/docker_client.go
generated
vendored
128
vendor/github.com/containers/image/v5/docker/docker_client.go
generated
vendored
@ -6,7 +6,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@ -17,6 +16,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/internal/iolimits"
|
||||
"github.com/containers/image/v5/pkg/docker/config"
|
||||
"github.com/containers/image/v5/pkg/sysregistriesv2"
|
||||
"github.com/containers/image/v5/pkg/tlsclientconfig"
|
||||
@ -45,6 +45,10 @@ const (
|
||||
|
||||
extensionSignatureSchemaVersion = 2 // extensionSignature.Version
|
||||
extensionSignatureTypeAtomic = "atomic" // extensionSignature.Type
|
||||
|
||||
backoffNumIterations = 5
|
||||
backoffInitialDelay = 2 * time.Second
|
||||
backoffMaxDelay = 60 * time.Second
|
||||
)
|
||||
|
||||
var systemPerHostCertDirPaths = [2]string{"/etc/containers/certs.d", "/etc/docker/certs.d"}
|
||||
@ -277,7 +281,7 @@ func CheckAuth(ctx context.Context, sys *types.SystemContext, username, password
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return httpResponseToError(resp)
|
||||
return httpResponseToError(resp, "")
|
||||
}
|
||||
|
||||
// SearchResult holds the information of each matching image
|
||||
@ -351,7 +355,7 @@ func SearchRegistry(ctx context.Context, sys *types.SystemContext, registry, ima
|
||||
} else {
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
logrus.Debugf("error getting search results from v1 endpoint %q: %v", registry, httpResponseToError(resp))
|
||||
logrus.Debugf("error getting search results from v1 endpoint %q: %v", registry, httpResponseToError(resp, ""))
|
||||
} else {
|
||||
if err := json.NewDecoder(resp.Body).Decode(v1Res); err != nil {
|
||||
return nil, err
|
||||
@ -368,7 +372,7 @@ func SearchRegistry(ctx context.Context, sys *types.SystemContext, registry, ima
|
||||
} else {
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
logrus.Errorf("error getting search results from v2 endpoint %q: %v", registry, httpResponseToError(resp))
|
||||
logrus.Errorf("error getting search results from v2 endpoint %q: %v", registry, httpResponseToError(resp, ""))
|
||||
} else {
|
||||
if err := json.NewDecoder(resp.Body).Decode(v2Res); err != nil {
|
||||
return nil, err
|
||||
@ -400,74 +404,64 @@ func (c *dockerClient) makeRequest(ctx context.Context, method, path string, hea
|
||||
return c.makeRequestToResolvedURL(ctx, method, url, headers, stream, -1, auth, extraScope)
|
||||
}
|
||||
|
||||
// parseRetryAfter determines the delay required by the "Retry-After" header in res and returns it,
|
||||
// silently falling back to fallbackDelay if the header is missing or invalid.
|
||||
func parseRetryAfter(res *http.Response, fallbackDelay time.Duration) time.Duration {
|
||||
after := res.Header.Get("Retry-After")
|
||||
if after == "" {
|
||||
return fallbackDelay
|
||||
}
|
||||
logrus.Debugf("Detected 'Retry-After' header %q", after)
|
||||
// First, check if we have a numerical value.
|
||||
if num, err := strconv.ParseInt(after, 10, 64); err == nil {
|
||||
return time.Duration(num) * time.Second
|
||||
}
|
||||
// Second, check if we have an HTTP date.
|
||||
// If the delta between the date and now is positive, use it.
|
||||
// Otherwise, fall back to using the default exponential back off.
|
||||
if t, err := http.ParseTime(after); err == nil {
|
||||
delta := time.Until(t)
|
||||
if delta > 0 {
|
||||
return delta
|
||||
}
|
||||
logrus.Debugf("Retry-After date in the past, ignoring it")
|
||||
return fallbackDelay
|
||||
}
|
||||
// If the header contents are bogus, fall back to using the default exponential back off.
|
||||
logrus.Debugf("Invalid Retry-After format, ignoring it")
|
||||
return fallbackDelay
|
||||
}
|
||||
|
||||
// makeRequestToResolvedURL creates and executes a http.Request with the specified parameters, adding authentication and TLS options for the Docker client.
|
||||
// streamLen, if not -1, specifies the length of the data expected on stream.
|
||||
// makeRequest should generally be preferred.
|
||||
// In case of an http 429 status code in the response, it performs an exponential back off starting at 2 seconds for at most 5 iterations.
|
||||
// If the `Retry-After` header is set in the response, the specified value or date is
|
||||
// If the stream is non-nil, no back off will be performed.
|
||||
// In case of an HTTP 429 status code in the response, it may automatically retry a few times.
|
||||
// TODO(runcom): too many arguments here, use a struct
|
||||
func (c *dockerClient) makeRequestToResolvedURL(ctx context.Context, method, url string, headers map[string][]string, stream io.Reader, streamLen int64, auth sendAuth, extraScope *authScope) (*http.Response, error) {
|
||||
var (
|
||||
res *http.Response
|
||||
err error
|
||||
delay int64
|
||||
)
|
||||
delay = 2
|
||||
const numIterations = 5
|
||||
const maxDelay = 60
|
||||
delay := backoffInitialDelay
|
||||
attempts := 0
|
||||
for {
|
||||
res, err := c.makeRequestToResolvedURLOnce(ctx, method, url, headers, stream, streamLen, auth, extraScope)
|
||||
attempts++
|
||||
if res == nil || res.StatusCode != http.StatusTooManyRequests || // Only retry on StatusTooManyRequests, success or other failure is returned to caller immediately
|
||||
stream != nil || // We can't retry with a body (which is not restartable in the general case)
|
||||
attempts == backoffNumIterations {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// math.Min() only supports float64, so have an anonymous func to avoid
|
||||
// casting.
|
||||
min := func(a int64, b int64) int64 {
|
||||
if a < b {
|
||||
return a
|
||||
delay = parseRetryAfter(res, delay)
|
||||
if delay > backoffMaxDelay {
|
||||
delay = backoffMaxDelay
|
||||
}
|
||||
return b
|
||||
logrus.Debugf("Too many requests to %s: sleeping for %f seconds before next attempt", url, delay.Seconds())
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
case <-time.After(delay):
|
||||
// Nothing
|
||||
}
|
||||
delay = delay * 2 // exponential back off
|
||||
}
|
||||
|
||||
nextDelay := func(r *http.Response, delay int64) int64 {
|
||||
after := res.Header.Get("Retry-After")
|
||||
if after == "" {
|
||||
return min(delay, maxDelay)
|
||||
}
|
||||
logrus.Debugf("detected 'Retry-After' header %q", after)
|
||||
// First check if we have a numerical value.
|
||||
if num, err := strconv.ParseInt(after, 10, 64); err == nil {
|
||||
return min(num, maxDelay)
|
||||
}
|
||||
// Secondly check if we have an http date.
|
||||
// If the delta between the date and now is positive, use it.
|
||||
// Otherwise, fall back to using the default exponential back off.
|
||||
if t, err := http.ParseTime(after); err == nil {
|
||||
delta := int64(time.Until(t).Seconds())
|
||||
if delta > 0 {
|
||||
return min(delta, maxDelay)
|
||||
}
|
||||
logrus.Debugf("negative date: falling back to using %d seconds", delay)
|
||||
return min(delay, maxDelay)
|
||||
}
|
||||
// If the header contains bogus, fall back to using the default
|
||||
// exponential back off.
|
||||
logrus.Debugf("invalid format: falling back to using %d seconds", delay)
|
||||
return min(delay, maxDelay)
|
||||
}
|
||||
|
||||
for i := 0; i < numIterations; i++ {
|
||||
res, err = c.makeRequestToResolvedURLOnce(ctx, method, url, headers, stream, streamLen, auth, extraScope)
|
||||
if stream == nil && res != nil && res.StatusCode == http.StatusTooManyRequests {
|
||||
if i < numIterations-1 {
|
||||
logrus.Errorf("HEADER %v", res.Header)
|
||||
delay = nextDelay(res, delay) // compute next delay - does NOT exceed maxDelay
|
||||
logrus.Debugf("too many request to %s: sleeping for %d seconds before next attempt", url, delay)
|
||||
time.Sleep(time.Duration(delay) * time.Second)
|
||||
delay = delay * 2 // exponential back off
|
||||
}
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
// makeRequestToResolvedURLOnce creates and executes a http.Request with the specified parameters, adding authentication and TLS options for the Docker client.
|
||||
@ -597,7 +591,7 @@ func (c *dockerClient) getBearerToken(ctx context.Context, challenge challenge,
|
||||
default:
|
||||
return nil, errors.Errorf("unexpected http code: %d (%s), URL: %s", res.StatusCode, http.StatusText(res.StatusCode), authReq.URL)
|
||||
}
|
||||
tokenBlob, err := ioutil.ReadAll(res.Body)
|
||||
tokenBlob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxAuthTokenBodySize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -627,7 +621,7 @@ func (c *dockerClient) detectPropertiesHelper(ctx context.Context) error {
|
||||
defer resp.Body.Close()
|
||||
logrus.Debugf("Ping %s status %d", url, resp.StatusCode)
|
||||
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusUnauthorized {
|
||||
return httpResponseToError(resp)
|
||||
return httpResponseToError(resp, "")
|
||||
}
|
||||
c.challenges = parseAuthHeader(resp.Header)
|
||||
c.scheme = scheme
|
||||
@ -690,7 +684,7 @@ func (c *dockerClient) getExtensionsSignatures(ctx context.Context, ref dockerRe
|
||||
return nil, errors.Wrapf(clientLib.HandleErrorResponse(res), "Error downloading signatures for %s in %s", manifestDigest, ref.ref.Name())
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxSignatureListBodySize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
2
vendor/github.com/containers/image/v5/docker/docker_image.go
generated
vendored
2
vendor/github.com/containers/image/v5/docker/docker_image.go
generated
vendored
@ -70,7 +70,7 @@ func GetRepositoryTags(ctx context.Context, sys *types.SystemContext, ref types.
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if err := httpResponseToError(res); err != nil {
|
||||
if err := httpResponseToError(res, "Error fetching tags list"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
11
vendor/github.com/containers/image/v5/docker/docker_image_dest.go
generated
vendored
11
vendor/github.com/containers/image/v5/docker/docker_image_dest.go
generated
vendored
@ -15,6 +15,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/internal/iolimits"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/blobinfocache/none"
|
||||
"github.com/containers/image/v5/types"
|
||||
@ -58,14 +59,16 @@ func (d *dockerImageDestination) Close() error {
|
||||
}
|
||||
|
||||
func (d *dockerImageDestination) SupportedManifestMIMETypes() []string {
|
||||
return []string{
|
||||
mimeTypes := []string{
|
||||
imgspecv1.MediaTypeImageManifest,
|
||||
manifest.DockerV2Schema2MediaType,
|
||||
imgspecv1.MediaTypeImageIndex,
|
||||
manifest.DockerV2ListMediaType,
|
||||
manifest.DockerV2Schema1SignedMediaType,
|
||||
manifest.DockerV2Schema1MediaType,
|
||||
}
|
||||
if d.c.sys == nil || !d.c.sys.DockerDisableDestSchema1MIMETypes {
|
||||
mimeTypes = append(mimeTypes, manifest.DockerV2Schema1SignedMediaType, manifest.DockerV2Schema1MediaType)
|
||||
}
|
||||
return mimeTypes
|
||||
}
|
||||
|
||||
// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures.
|
||||
@ -620,7 +623,7 @@ sigExists:
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxErrorBodySize)
|
||||
if err == nil {
|
||||
logrus.Debugf("Error body %s", string(body))
|
||||
}
|
||||
|
111
vendor/github.com/containers/image/v5/docker/docker_image_src.go
generated
vendored
111
vendor/github.com/containers/image/v5/docker/docker_image_src.go
generated
vendored
@ -10,8 +10,10 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/internal/iolimits"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/sysregistriesv2"
|
||||
"github.com/containers/image/v5/types"
|
||||
@ -53,43 +55,77 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerRef
|
||||
// non-mirror original location last; this both transparently handles the case
|
||||
// of no mirrors configured, and ensures we return the error encountered when
|
||||
// acessing the upstream location if all endpoints fail.
|
||||
manifestLoadErr := errors.New("Internal error: newImageSource returned without trying any endpoint")
|
||||
pullSources, err := registry.PullSourcesFromReference(ref.ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, pullSource := range pullSources {
|
||||
logrus.Debugf("Trying to pull %q", pullSource.Reference)
|
||||
dockerRef, err := newReference(pullSource.Reference)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
endpointSys := sys
|
||||
// sys.DockerAuthConfig does not explicitly specify a registry; we must not blindly send the credentials intended for the primary endpoint to mirrors.
|
||||
if endpointSys != nil && endpointSys.DockerAuthConfig != nil && reference.Domain(dockerRef.ref) != primaryDomain {
|
||||
copy := *endpointSys
|
||||
copy.DockerAuthConfig = nil
|
||||
endpointSys = ©
|
||||
}
|
||||
|
||||
client, err := newDockerClientFromRef(endpointSys, dockerRef, false, "pull")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.tlsClientConfig.InsecureSkipVerify = pullSource.Endpoint.Insecure
|
||||
|
||||
testImageSource := &dockerImageSource{
|
||||
ref: dockerRef,
|
||||
c: client,
|
||||
}
|
||||
|
||||
manifestLoadErr = testImageSource.ensureManifestIsLoaded(ctx)
|
||||
if manifestLoadErr == nil {
|
||||
return testImageSource, nil
|
||||
}
|
||||
type attempt struct {
|
||||
ref reference.Named
|
||||
err error
|
||||
}
|
||||
return nil, manifestLoadErr
|
||||
attempts := []attempt{}
|
||||
for _, pullSource := range pullSources {
|
||||
logrus.Debugf("Trying to access %q", pullSource.Reference)
|
||||
s, err := newImageSourceAttempt(ctx, sys, pullSource, primaryDomain)
|
||||
if err == nil {
|
||||
return s, nil
|
||||
}
|
||||
logrus.Debugf("Accessing %q failed: %v", pullSource.Reference, err)
|
||||
attempts = append(attempts, attempt{
|
||||
ref: pullSource.Reference,
|
||||
err: err,
|
||||
})
|
||||
}
|
||||
switch len(attempts) {
|
||||
case 0:
|
||||
return nil, errors.New("Internal error: newImageSource returned without trying any endpoint")
|
||||
case 1:
|
||||
return nil, attempts[0].err // If no mirrors are used, perfectly preserve the error type and add no noise.
|
||||
default:
|
||||
// Don’t just build a string, try to preserve the typed error.
|
||||
primary := &attempts[len(attempts)-1]
|
||||
extras := []string{}
|
||||
for i := 0; i < len(attempts)-1; i++ {
|
||||
// This is difficult to fit into a single-line string, when the error can contain arbitrary strings including any metacharacters we decide to use.
|
||||
// The paired [] at least have some chance of being unambiguous.
|
||||
extras = append(extras, fmt.Sprintf("[%s: %v]", attempts[i].ref.String(), attempts[i].err))
|
||||
}
|
||||
return nil, errors.Wrapf(primary.err, "(Mirrors also failed: %s): %s", strings.Join(extras, "\n"), primary.ref.String())
|
||||
}
|
||||
}
|
||||
|
||||
// newImageSourceAttempt is an internal helper for newImageSource. Everyone else must call newImageSource.
|
||||
// Given a pullSource and primaryDomain, return a dockerImageSource if it is reachable.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func newImageSourceAttempt(ctx context.Context, sys *types.SystemContext, pullSource sysregistriesv2.PullSource, primaryDomain string) (*dockerImageSource, error) {
|
||||
ref, err := newReference(pullSource.Reference)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
endpointSys := sys
|
||||
// sys.DockerAuthConfig does not explicitly specify a registry; we must not blindly send the credentials intended for the primary endpoint to mirrors.
|
||||
if endpointSys != nil && endpointSys.DockerAuthConfig != nil && reference.Domain(ref.ref) != primaryDomain {
|
||||
copy := *endpointSys
|
||||
copy.DockerAuthConfig = nil
|
||||
endpointSys = ©
|
||||
}
|
||||
|
||||
client, err := newDockerClientFromRef(endpointSys, ref, false, "pull")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.tlsClientConfig.InsecureSkipVerify = pullSource.Endpoint.Insecure
|
||||
|
||||
s := &dockerImageSource{
|
||||
ref: ref,
|
||||
c: client,
|
||||
}
|
||||
|
||||
if err := s.ensureManifestIsLoaded(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Reference returns the reference used to set up this source, _as specified by the user_
|
||||
@ -156,7 +192,8 @@ func (s *dockerImageSource) fetchManifest(ctx context.Context, tagOrDigest strin
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, "", errors.Wrapf(client.HandleErrorResponse(res), "Error reading manifest %s in %s", tagOrDigest, s.ref.ref.Name())
|
||||
}
|
||||
manblob, err := ioutil.ReadAll(res.Body)
|
||||
|
||||
manblob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxManifestBodySize)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@ -239,7 +276,7 @@ func (s *dockerImageSource) GetBlob(ctx context.Context, info types.BlobInfo, ca
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := httpResponseToError(res); err != nil {
|
||||
if err := httpResponseToError(res, "Error fetching blob"); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
cache.RecordKnownLocation(s.ref.Transport(), bicTransportScope(s.ref), info.Digest, newBICLocationReference(s.ref))
|
||||
@ -342,7 +379,7 @@ func (s *dockerImageSource) getOneSignature(ctx context.Context, url *url.URL) (
|
||||
} else if res.StatusCode != http.StatusOK {
|
||||
return nil, false, errors.Errorf("Error reading signature from %s: status %d (%s)", url.String(), res.StatusCode, http.StatusText(res.StatusCode))
|
||||
}
|
||||
sig, err := ioutil.ReadAll(res.Body)
|
||||
sig, err := iolimits.ReadAtMost(res.Body, iolimits.MaxSignatureBodySize)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
@ -401,7 +438,7 @@ func deleteImage(ctx context.Context, sys *types.SystemContext, ref dockerRefere
|
||||
return err
|
||||
}
|
||||
defer get.Body.Close()
|
||||
manifestBody, err := ioutil.ReadAll(get.Body)
|
||||
manifestBody, err := iolimits.ReadAtMost(get.Body, iolimits.MaxManifestBodySize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -424,7 +461,7 @@ func deleteImage(ctx context.Context, sys *types.SystemContext, ref dockerRefere
|
||||
}
|
||||
defer delete.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(delete.Body)
|
||||
body, err := iolimits.ReadAtMost(delete.Body, iolimits.MaxErrorBodySize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
11
vendor/github.com/containers/image/v5/docker/errors.go
generated
vendored
11
vendor/github.com/containers/image/v5/docker/errors.go
generated
vendored
@ -14,7 +14,7 @@ var (
|
||||
// docker V1 registry.
|
||||
ErrV1NotSupported = errors.New("can't talk to a V1 docker registry")
|
||||
// ErrTooManyRequests is returned when the status code returned is 429
|
||||
ErrTooManyRequests = errors.New("too many request to registry")
|
||||
ErrTooManyRequests = errors.New("too many requests to registry")
|
||||
)
|
||||
|
||||
// ErrUnauthorizedForCredentials is returned when the status code returned is 401
|
||||
@ -26,9 +26,9 @@ func (e ErrUnauthorizedForCredentials) Error() string {
|
||||
return fmt.Sprintf("unable to retrieve auth token: invalid username/password: %s", e.Err.Error())
|
||||
}
|
||||
|
||||
// httpResponseToError translates the https.Response into an error. It returns
|
||||
// httpResponseToError translates the https.Response into an error, possibly prefixing it with the supplied context. It returns
|
||||
// nil if the response is not considered an error.
|
||||
func httpResponseToError(res *http.Response) error {
|
||||
func httpResponseToError(res *http.Response, context string) error {
|
||||
switch res.StatusCode {
|
||||
case http.StatusOK:
|
||||
return nil
|
||||
@ -38,6 +38,9 @@ func httpResponseToError(res *http.Response) error {
|
||||
err := client.HandleErrorResponse(res)
|
||||
return ErrUnauthorizedForCredentials{Err: err}
|
||||
default:
|
||||
return perrors.Errorf("invalid status code from registry %d (%s)", res.StatusCode, http.StatusText(res.StatusCode))
|
||||
if context != "" {
|
||||
context = context + ": "
|
||||
}
|
||||
return perrors.Errorf("%sinvalid status code from registry %d (%s)", context, res.StatusCode, http.StatusText(res.StatusCode))
|
||||
}
|
||||
}
|
||||
|
3
vendor/github.com/containers/image/v5/docker/tarfile/dest.go
generated
vendored
3
vendor/github.com/containers/image/v5/docker/tarfile/dest.go
generated
vendored
@ -13,6 +13,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/internal/iolimits"
|
||||
"github.com/containers/image/v5/internal/tmpdir"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
@ -143,7 +144,7 @@ func (d *Destination) PutBlob(ctx context.Context, stream io.Reader, inputInfo t
|
||||
}
|
||||
|
||||
if isConfig {
|
||||
buf, err := ioutil.ReadAll(stream)
|
||||
buf, err := iolimits.ReadAtMost(stream, iolimits.MaxConfigBodySize)
|
||||
if err != nil {
|
||||
return types.BlobInfo{}, errors.Wrap(err, "Error reading Config file stream")
|
||||
}
|
||||
|
9
vendor/github.com/containers/image/v5/docker/tarfile/src.go
generated
vendored
9
vendor/github.com/containers/image/v5/docker/tarfile/src.go
generated
vendored
@ -11,6 +11,7 @@ import (
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
"github.com/containers/image/v5/internal/iolimits"
|
||||
"github.com/containers/image/v5/internal/tmpdir"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/compression"
|
||||
@ -203,13 +204,13 @@ func findTarComponent(inputFile io.Reader, path string) (*tar.Reader, *tar.Heade
|
||||
}
|
||||
|
||||
// readTarComponent returns full contents of componentPath.
|
||||
func (s *Source) readTarComponent(path string) ([]byte, error) {
|
||||
func (s *Source) readTarComponent(path string, limit int) ([]byte, error) {
|
||||
file, err := s.openTarComponent(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error loading tar component %s", path)
|
||||
}
|
||||
defer file.Close()
|
||||
bytes, err := ioutil.ReadAll(file)
|
||||
bytes, err := iolimits.ReadAtMost(file, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -240,7 +241,7 @@ func (s *Source) ensureCachedDataIsPresentPrivate() error {
|
||||
}
|
||||
|
||||
// Read and parse config.
|
||||
configBytes, err := s.readTarComponent(tarManifest[0].Config)
|
||||
configBytes, err := s.readTarComponent(tarManifest[0].Config, iolimits.MaxConfigBodySize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -266,7 +267,7 @@ func (s *Source) ensureCachedDataIsPresentPrivate() error {
|
||||
// loadTarManifest loads and decodes the manifest.json.
|
||||
func (s *Source) loadTarManifest() ([]ManifestItem, error) {
|
||||
// FIXME? Do we need to deal with the legacy format?
|
||||
bytes, err := s.readTarComponent(manifestFileName)
|
||||
bytes, err := s.readTarComponent(manifestFileName, iolimits.MaxTarFileManifestSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
4
vendor/github.com/containers/image/v5/image/docker_schema2.go
generated
vendored
4
vendor/github.com/containers/image/v5/image/docker_schema2.go
generated
vendored
@ -7,10 +7,10 @@ import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/internal/iolimits"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/blobinfocache/none"
|
||||
"github.com/containers/image/v5/types"
|
||||
@ -102,7 +102,7 @@ func (m *manifestSchema2) ConfigBlob(ctx context.Context) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer stream.Close()
|
||||
blob, err := ioutil.ReadAll(stream)
|
||||
blob, err := iolimits.ReadAtMost(stream, iolimits.MaxConfigBodySize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
4
vendor/github.com/containers/image/v5/image/oci.go
generated
vendored
4
vendor/github.com/containers/image/v5/image/oci.go
generated
vendored
@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/internal/iolimits"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/blobinfocache/none"
|
||||
"github.com/containers/image/v5/types"
|
||||
@ -67,7 +67,7 @@ func (m *manifestOCI1) ConfigBlob(ctx context.Context) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer stream.Close()
|
||||
blob, err := ioutil.ReadAll(stream)
|
||||
blob, err := iolimits.ReadAtMost(stream, iolimits.MaxConfigBodySize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
60
vendor/github.com/containers/image/v5/internal/iolimits/iolimits.go
generated
vendored
Normal file
60
vendor/github.com/containers/image/v5/internal/iolimits/iolimits.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
package iolimits
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// All constants below are intended to be used as limits for `ReadAtMost`. The
|
||||
// immediate use-case for limiting the size of in-memory copied data is to
|
||||
// protect against OOM DOS attacks as described inCVE-2020-1702. Instead of
|
||||
// copying data until running out of memory, we error out after hitting the
|
||||
// specified limit.
|
||||
const (
|
||||
// megaByte denotes one megabyte and is intended to be used as a limit in
|
||||
// `ReadAtMost`.
|
||||
megaByte = 1 << 20
|
||||
// MaxManifestBodySize is the maximum allowed size of a manifest. The limit
|
||||
// of 4 MB aligns with the one of a Docker registry:
|
||||
// https://github.com/docker/distribution/blob/a8371794149d1d95f1e846744b05c87f2f825e5a/registry/handlers/manifests.go#L30
|
||||
MaxManifestBodySize = 4 * megaByte
|
||||
// MaxAuthTokenBodySize is the maximum allowed size of an auth token.
|
||||
// The limit of 1 MB is considered to be greatly sufficient.
|
||||
MaxAuthTokenBodySize = megaByte
|
||||
// MaxSignatureListBodySize is the maximum allowed size of a signature list.
|
||||
// The limit of 4 MB is considered to be greatly sufficient.
|
||||
MaxSignatureListBodySize = 4 * megaByte
|
||||
// MaxSignatureBodySize is the maximum allowed size of a signature.
|
||||
// The limit of 4 MB is considered to be greatly sufficient.
|
||||
MaxSignatureBodySize = 4 * megaByte
|
||||
// MaxErrorBodySize is the maximum allowed size of an error-response body.
|
||||
// The limit of 1 MB is considered to be greatly sufficient.
|
||||
MaxErrorBodySize = megaByte
|
||||
// MaxConfigBodySize is the maximum allowed size of a config blob.
|
||||
// The limit of 4 MB is considered to be greatly sufficient.
|
||||
MaxConfigBodySize = 4 * megaByte
|
||||
// MaxOpenShiftStatusBody is the maximum allowed size of an OpenShift status body.
|
||||
// The limit of 4 MB is considered to be greatly sufficient.
|
||||
MaxOpenShiftStatusBody = 4 * megaByte
|
||||
// MaxTarFileManifestSize is the maximum allowed size of a (docker save)-like manifest (which may contain multiple images)
|
||||
// The limit of 1 MB is considered to be greatly sufficient.
|
||||
MaxTarFileManifestSize = megaByte
|
||||
)
|
||||
|
||||
// ReadAtMost reads from reader and errors out if the specified limit (in bytes) is exceeded.
|
||||
func ReadAtMost(reader io.Reader, limit int) ([]byte, error) {
|
||||
limitedReader := io.LimitReader(reader, int64(limit+1))
|
||||
|
||||
res, err := ioutil.ReadAll(limitedReader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(res) > limit {
|
||||
return nil, errors.Errorf("exceeded maximum allowed size of %d bytes", limit)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
4
vendor/github.com/containers/image/v5/openshift/openshift.go
generated
vendored
4
vendor/github.com/containers/image/v5/openshift/openshift.go
generated
vendored
@ -7,13 +7,13 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v5/docker"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/internal/iolimits"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/image/v5/version"
|
||||
@ -102,7 +102,7 @@ func (c *openshiftClient) doRequest(ctx context.Context, method, path string, re
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxOpenShiftStatusBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
4
vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
generated
vendored
4
vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
generated
vendored
@ -139,7 +139,7 @@ func (m *gpgmeSigningMechanism) Sign(input []byte, keyIdentity string) ([]byte,
|
||||
}
|
||||
|
||||
// Verify parses unverifiedSignature and returns the content and the signer's identity
|
||||
func (m gpgmeSigningMechanism) Verify(unverifiedSignature []byte) (contents []byte, keyIdentity string, err error) {
|
||||
func (m *gpgmeSigningMechanism) Verify(unverifiedSignature []byte) (contents []byte, keyIdentity string, err error) {
|
||||
signedBuffer := bytes.Buffer{}
|
||||
signedData, err := gpgme.NewDataWriter(&signedBuffer)
|
||||
if err != nil {
|
||||
@ -170,6 +170,6 @@ func (m gpgmeSigningMechanism) Verify(unverifiedSignature []byte) (contents []by
|
||||
// WARNING: The short key identifier (which correponds to "Key ID" for OpenPGP keys)
|
||||
// is NOT the same as a "key identity" used in other calls ot this interface, and
|
||||
// the values may have no recognizable relationship if the public key is not available.
|
||||
func (m gpgmeSigningMechanism) UntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error) {
|
||||
func (m *gpgmeSigningMechanism) UntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error) {
|
||||
return gpgUntrustedSignatureContents(untrustedSignature)
|
||||
}
|
||||
|
2
vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
generated
vendored
2
vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
generated
vendored
@ -154,6 +154,6 @@ func (m *openpgpSigningMechanism) Verify(unverifiedSignature []byte) (contents [
|
||||
// WARNING: The short key identifier (which correponds to "Key ID" for OpenPGP keys)
|
||||
// is NOT the same as a "key identity" used in other calls ot this interface, and
|
||||
// the values may have no recognizable relationship if the public key is not available.
|
||||
func (m openpgpSigningMechanism) UntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error) {
|
||||
func (m *openpgpSigningMechanism) UntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error) {
|
||||
return gpgUntrustedSignatureContents(untrustedSignature)
|
||||
}
|
||||
|
2
vendor/github.com/containers/image/v5/types/types.go
generated
vendored
2
vendor/github.com/containers/image/v5/types/types.go
generated
vendored
@ -547,6 +547,8 @@ type SystemContext struct {
|
||||
// Note that this field is used mainly to integrate containers/image into projectatomic/docker
|
||||
// in order to not break any existing docker's integration tests.
|
||||
DockerDisableV1Ping bool
|
||||
// If true, dockerImageDestination.SupportedManifestMIMETypes will omit the Schema1 media types from the supported list
|
||||
DockerDisableDestSchema1MIMETypes bool
|
||||
// Directory to use for OSTree temporary files
|
||||
OSTreeTmpDirPath string
|
||||
|
||||
|
2
vendor/github.com/containers/image/v5/version/version.go
generated
vendored
2
vendor/github.com/containers/image/v5/version/version.go
generated
vendored
@ -6,7 +6,7 @@ const (
|
||||
// VersionMajor is for an API incompatible changes
|
||||
VersionMajor = 5
|
||||
// VersionMinor is for functionality in a backwards-compatible manner
|
||||
VersionMinor = 1
|
||||
VersionMinor = 2
|
||||
// VersionPatch is for backwards-compatible bug fixes
|
||||
VersionPatch = 0
|
||||
|
||||
|
40
vendor/github.com/mtrmac/gpgme/.appveyor.yml
generated
vendored
Normal file
40
vendor/github.com/mtrmac/gpgme/.appveyor.yml
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
version: 0.{build}
|
||||
platform: x86
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
clone_folder: c:\gopath\src\github.com\proglottis\gpgme
|
||||
|
||||
environment:
|
||||
GOPATH: c:\gopath
|
||||
GOROOT: C:\go-x86
|
||||
CGO_LDFLAGS: -LC:\gpg\lib
|
||||
CGO_CFLAGS: -IC:\gpg\include
|
||||
GPG_DIR: C:\gpg
|
||||
|
||||
install:
|
||||
- nuget install 7ZipCLI -ExcludeVersion
|
||||
- set PATH=%appveyor_build_folder%\7ZipCLI\tools;%PATH%
|
||||
- appveyor DownloadFile https://www.gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.1.20_20170403.exe -FileName gnupg-w32-2.1.20_20170403.exe
|
||||
- 7z x -o%GPG_DIR% gnupg-w32-2.1.20_20170403.exe
|
||||
- copy "%GPG_DIR%\lib\libgpg-error.imp" "%GPG_DIR%\lib\libgpg-error.a"
|
||||
- copy "%GPG_DIR%\lib\libassuan.imp" "%GPG_DIR%\lib\libassuan.a"
|
||||
- copy "%GPG_DIR%\lib\libgpgme.imp" "%GPG_DIR%\lib\libgpgme.a"
|
||||
- set PATH=%GOPATH%\bin;%GOROOT%\bin;%GPG_DIR%\bin;C:\MinGW\bin;%PATH%
|
||||
- C:\cygwin\bin\sed -i 's/"GPG_AGENT_INFO"/"GPG_AGENT_INFO="/;s/C.unsetenv(v)/C.putenv(v)/' %APPVEYOR_BUILD_FOLDER%\gpgme.go
|
||||
|
||||
test_script:
|
||||
- go test -v github.com/proglottis/gpgme
|
||||
|
||||
|
||||
build_script:
|
||||
- go build -o example_decrypt.exe -i %APPVEYOR_BUILD_FOLDER%\examples\decrypt.go
|
||||
- go build -o example_encrypt.exe -i %APPVEYOR_BUILD_FOLDER%\examples\encrypt.go
|
||||
|
||||
artifacts:
|
||||
- path: example_decrypt.exe
|
||||
name: decrypt example binary
|
||||
- path: example_encrypt.exe
|
||||
name: encrypt example binary
|
32
vendor/github.com/mtrmac/gpgme/.travis.yml
generated
vendored
Normal file
32
vendor/github.com/mtrmac/gpgme/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
language: go
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
- windows
|
||||
dist: xenial
|
||||
sudo: false
|
||||
|
||||
go:
|
||||
- 1.11
|
||||
- 1.12
|
||||
- 1.13
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libgpgme11-dev
|
||||
homebrew:
|
||||
packages:
|
||||
- gnupg
|
||||
- gnupg@1.4
|
||||
- gpgme
|
||||
update: true
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- os: windows
|
||||
|
||||
before_install:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then choco install msys2; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then choco install gpg4win; fi
|
18
vendor/github.com/mtrmac/gpgme/data.go
generated
vendored
18
vendor/github.com/mtrmac/gpgme/data.go
generated
vendored
@ -50,25 +50,25 @@ func gogpgme_writefunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t {
|
||||
}
|
||||
|
||||
//export gogpgme_seekfunc
|
||||
func gogpgme_seekfunc(handle unsafe.Pointer, offset C.off_t, whence C.int) C.off_t {
|
||||
func gogpgme_seekfunc(handle unsafe.Pointer, offset C.gpgme_off_t, whence C.int) C.gpgme_off_t {
|
||||
d := callbackLookup(uintptr(handle)).(*Data)
|
||||
n, err := d.s.Seek(int64(offset), int(whence))
|
||||
if err != nil {
|
||||
C.gpgme_err_set_errno(C.EIO)
|
||||
return -1
|
||||
}
|
||||
return C.off_t(n)
|
||||
return C.gpgme_off_t(n)
|
||||
}
|
||||
|
||||
// The Data buffer used to communicate with GPGME
|
||||
type Data struct {
|
||||
dh C.gpgme_data_t
|
||||
dh C.gpgme_data_t // WARNING: Call runtime.KeepAlive(d) after ANY passing of d.dh to C
|
||||
buf []byte
|
||||
cbs C.struct_gpgme_data_cbs
|
||||
r io.Reader
|
||||
w io.Writer
|
||||
s io.Seeker
|
||||
cbc uintptr
|
||||
cbc uintptr // WARNING: Call runtime.KeepAlive(d) after ANY use of d.cbc in C (typically via d.dh)
|
||||
}
|
||||
|
||||
func newData() *Data {
|
||||
@ -154,12 +154,14 @@ func (d *Data) Close() error {
|
||||
callbackDelete(d.cbc)
|
||||
}
|
||||
_, err := C.gpgme_data_release(d.dh)
|
||||
runtime.KeepAlive(d)
|
||||
d.dh = nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Data) Write(p []byte) (int, error) {
|
||||
n, err := C.gpgme_data_write(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
|
||||
runtime.KeepAlive(d)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -171,6 +173,7 @@ func (d *Data) Write(p []byte) (int, error) {
|
||||
|
||||
func (d *Data) Read(p []byte) (int, error) {
|
||||
n, err := C.gpgme_data_read(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
|
||||
runtime.KeepAlive(d)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -181,11 +184,14 @@ func (d *Data) Read(p []byte) (int, error) {
|
||||
}
|
||||
|
||||
func (d *Data) Seek(offset int64, whence int) (int64, error) {
|
||||
n, err := C.gpgme_data_seek(d.dh, C.off_t(offset), C.int(whence))
|
||||
n, err := C.gogpgme_data_seek(d.dh, C.gpgme_off_t(offset), C.int(whence))
|
||||
runtime.KeepAlive(d)
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
// Name returns the associated filename if any
|
||||
func (d *Data) Name() string {
|
||||
return C.GoString(C.gpgme_data_get_file_name(d.dh))
|
||||
res := C.GoString(C.gpgme_data_get_file_name(d.dh))
|
||||
runtime.KeepAlive(d)
|
||||
return res
|
||||
}
|
||||
|
3
vendor/github.com/mtrmac/gpgme/go.mod
generated
vendored
Normal file
3
vendor/github.com/mtrmac/gpgme/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module github.com/mtrmac/gpgme
|
||||
|
||||
go 1.11
|
22
vendor/github.com/mtrmac/gpgme/go_gpgme.c
generated
vendored
22
vendor/github.com/mtrmac/gpgme/go_gpgme.c
generated
vendored
@ -8,6 +8,28 @@ void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintpt
|
||||
gpgme_set_passphrase_cb(ctx, cb, (void *)handle);
|
||||
}
|
||||
|
||||
gpgme_off_t gogpgme_data_seek(gpgme_data_t dh, gpgme_off_t offset, int whence) {
|
||||
return gpgme_data_seek(dh, offset, whence);
|
||||
}
|
||||
|
||||
gpgme_error_t gogpgme_op_assuan_transact_ext(
|
||||
gpgme_ctx_t ctx,
|
||||
char* cmd,
|
||||
uintptr_t data_h,
|
||||
uintptr_t inquiry_h,
|
||||
uintptr_t status_h,
|
||||
gpgme_error_t *operr
|
||||
){
|
||||
return gpgme_op_assuan_transact_ext(
|
||||
ctx,
|
||||
cmd,
|
||||
(gpgme_assuan_data_cb_t) gogpgme_assuan_data_callback, (void *)data_h,
|
||||
(gpgme_assuan_inquire_cb_t) gogpgme_assuan_inquiry_callback, (void *)inquiry_h,
|
||||
(gpgme_assuan_status_cb_t) gogpgme_assuan_status_callback, (void *)status_h,
|
||||
operr
|
||||
);
|
||||
}
|
||||
|
||||
unsigned int key_revoked(gpgme_key_t k) {
|
||||
return k->revoked;
|
||||
}
|
||||
|
7
vendor/github.com/mtrmac/gpgme/go_gpgme.h
generated
vendored
7
vendor/github.com/mtrmac/gpgme/go_gpgme.h
generated
vendored
@ -12,6 +12,13 @@ extern off_t gogpgme_seekfunc(void *handle, off_t offset, int whence);
|
||||
extern gpgme_error_t gogpgme_passfunc(void *hook, char *uid_hint, char *passphrase_info, int prev_was_bad, int fd);
|
||||
extern gpgme_error_t gogpgme_data_new_from_cbs(gpgme_data_t *dh, gpgme_data_cbs_t cbs, uintptr_t handle);
|
||||
extern void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintptr_t handle);
|
||||
extern gpgme_off_t gogpgme_data_seek(gpgme_data_t dh, gpgme_off_t offset, int whence);
|
||||
|
||||
extern gpgme_error_t gogpgme_op_assuan_transact_ext(gpgme_ctx_t ctx, char *cmd, uintptr_t data_h, uintptr_t inquiry_h , uintptr_t status_h, gpgme_error_t *operr);
|
||||
|
||||
extern gpgme_error_t gogpgme_assuan_data_callback(void *opaque, void* data, size_t datalen );
|
||||
extern gpgme_error_t gogpgme_assuan_inquiry_callback(void *opaque, char* name, char* args);
|
||||
extern gpgme_error_t gogpgme_assuan_status_callback(void *opaque, char* status, char* args);
|
||||
|
||||
extern unsigned int key_revoked(gpgme_key_t k);
|
||||
extern unsigned int key_expired(gpgme_key_t k);
|
||||
|
346
vendor/github.com/mtrmac/gpgme/gpgme.go
generated
vendored
346
vendor/github.com/mtrmac/gpgme/gpgme.go
generated
vendored
@ -7,7 +7,6 @@ package gpgme
|
||||
// #include <gpgme.h>
|
||||
// #include "go_gpgme.h"
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
@ -48,9 +47,8 @@ const (
|
||||
ProtocolAssuan Protocol = C.GPGME_PROTOCOL_ASSUAN
|
||||
ProtocolG13 Protocol = C.GPGME_PROTOCOL_G13
|
||||
ProtocolUIServer Protocol = C.GPGME_PROTOCOL_UISERVER
|
||||
// ProtocolSpawn Protocol = C.GPGME_PROTOCOL_SPAWN // Unavailable in 1.4.3
|
||||
ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT
|
||||
ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN
|
||||
ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT
|
||||
ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN
|
||||
)
|
||||
|
||||
type PinEntryMode int
|
||||
@ -70,7 +68,6 @@ const (
|
||||
EncryptNoEncryptTo EncryptFlag = C.GPGME_ENCRYPT_NO_ENCRYPT_TO
|
||||
EncryptPrepare EncryptFlag = C.GPGME_ENCRYPT_PREPARE
|
||||
EncryptExceptSign EncryptFlag = C.GPGME_ENCRYPT_EXPECT_SIGN
|
||||
// EncryptNoCompress EncryptFlag = C.GPGME_ENCRYPT_NO_COMPRESS // Unavailable in 1.4.3
|
||||
)
|
||||
|
||||
type HashAlgo int
|
||||
@ -84,7 +81,6 @@ const (
|
||||
KeyListModeExtern KeyListMode = C.GPGME_KEYLIST_MODE_EXTERN
|
||||
KeyListModeSigs KeyListMode = C.GPGME_KEYLIST_MODE_SIGS
|
||||
KeyListModeSigNotations KeyListMode = C.GPGME_KEYLIST_MODE_SIG_NOTATIONS
|
||||
// KeyListModeWithSecret KeyListMode = C.GPGME_KEYLIST_MODE_WITH_SECRET // Unavailable in 1.4.3
|
||||
KeyListModeEphemeral KeyListMode = C.GPGME_KEYLIST_MODE_EPHEMERAL
|
||||
KeyListModeModeValidate KeyListMode = C.GPGME_KEYLIST_MODE_VALIDATE
|
||||
)
|
||||
@ -168,39 +164,60 @@ func EngineCheckVersion(p Protocol) error {
|
||||
}
|
||||
|
||||
type EngineInfo struct {
|
||||
info C.gpgme_engine_info_t
|
||||
next *EngineInfo
|
||||
protocol Protocol
|
||||
fileName string
|
||||
homeDir string
|
||||
version string
|
||||
requiredVersion string
|
||||
}
|
||||
|
||||
func copyEngineInfo(info C.gpgme_engine_info_t) *EngineInfo {
|
||||
res := &EngineInfo{
|
||||
next: nil,
|
||||
protocol: Protocol(info.protocol),
|
||||
fileName: C.GoString(info.file_name),
|
||||
homeDir: C.GoString(info.home_dir),
|
||||
version: C.GoString(info.version),
|
||||
requiredVersion: C.GoString(info.req_version),
|
||||
}
|
||||
if info.next != nil {
|
||||
res.next = copyEngineInfo(info.next)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (e *EngineInfo) Next() *EngineInfo {
|
||||
if e.info.next == nil {
|
||||
return nil
|
||||
}
|
||||
return &EngineInfo{info: e.info.next}
|
||||
return e.next
|
||||
}
|
||||
|
||||
func (e *EngineInfo) Protocol() Protocol {
|
||||
return Protocol(e.info.protocol)
|
||||
return e.protocol
|
||||
}
|
||||
|
||||
func (e *EngineInfo) FileName() string {
|
||||
return C.GoString(e.info.file_name)
|
||||
return e.fileName
|
||||
}
|
||||
|
||||
func (e *EngineInfo) Version() string {
|
||||
return C.GoString(e.info.version)
|
||||
return e.version
|
||||
}
|
||||
|
||||
func (e *EngineInfo) RequiredVersion() string {
|
||||
return C.GoString(e.info.req_version)
|
||||
return e.requiredVersion
|
||||
}
|
||||
|
||||
func (e *EngineInfo) HomeDir() string {
|
||||
return C.GoString(e.info.home_dir)
|
||||
return e.homeDir
|
||||
}
|
||||
|
||||
func GetEngineInfo() (*EngineInfo, error) {
|
||||
info := &EngineInfo{}
|
||||
return info, handleError(C.gpgme_get_engine_info(&info.info))
|
||||
var cInfo C.gpgme_engine_info_t
|
||||
err := handleError(C.gpgme_get_engine_info(&cInfo))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return copyEngineInfo(cInfo), nil // It is up to the caller not to invalidate cInfo concurrently until this is done.
|
||||
}
|
||||
|
||||
func SetEngineInfo(proto Protocol, fileName, homeDir string) error {
|
||||
@ -261,9 +278,9 @@ type Context struct {
|
||||
KeyError error
|
||||
|
||||
callback Callback
|
||||
cbc uintptr
|
||||
cbc uintptr // WARNING: Call runtime.KeepAlive(c) after ANY use of c.cbc in C (typically via c.ctx)
|
||||
|
||||
ctx C.gpgme_ctx_t
|
||||
ctx C.gpgme_ctx_t // WARNING: Call runtime.KeepAlive(c) after ANY passing of c.ctx to C
|
||||
}
|
||||
|
||||
func New() (*Context, error) {
|
||||
@ -281,49 +298,68 @@ func (c *Context) Release() {
|
||||
callbackDelete(c.cbc)
|
||||
}
|
||||
C.gpgme_release(c.ctx)
|
||||
runtime.KeepAlive(c)
|
||||
c.ctx = nil
|
||||
}
|
||||
|
||||
func (c *Context) SetArmor(yes bool) {
|
||||
C.gpgme_set_armor(c.ctx, cbool(yes))
|
||||
runtime.KeepAlive(c)
|
||||
}
|
||||
|
||||
func (c *Context) Armor() bool {
|
||||
return C.gpgme_get_armor(c.ctx) != 0
|
||||
res := C.gpgme_get_armor(c.ctx) != 0
|
||||
runtime.KeepAlive(c)
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *Context) SetTextMode(yes bool) {
|
||||
C.gpgme_set_textmode(c.ctx, cbool(yes))
|
||||
runtime.KeepAlive(c)
|
||||
}
|
||||
|
||||
func (c *Context) TextMode() bool {
|
||||
return C.gpgme_get_textmode(c.ctx) != 0
|
||||
res := C.gpgme_get_textmode(c.ctx) != 0
|
||||
runtime.KeepAlive(c)
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *Context) SetProtocol(p Protocol) error {
|
||||
return handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
|
||||
err := handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) Protocol() Protocol {
|
||||
return Protocol(C.gpgme_get_protocol(c.ctx))
|
||||
res := Protocol(C.gpgme_get_protocol(c.ctx))
|
||||
runtime.KeepAlive(c)
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *Context) SetKeyListMode(m KeyListMode) error {
|
||||
return handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
|
||||
err := handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) KeyListMode() KeyListMode {
|
||||
return KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
|
||||
res := KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
|
||||
runtime.KeepAlive(c)
|
||||
return res
|
||||
}
|
||||
|
||||
// Unavailable in 1.3.2:
|
||||
// func (c *Context) SetPinEntryMode(m PinEntryMode) error {
|
||||
// return handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
|
||||
// err := handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
|
||||
// runtime.KeepAlive(c)
|
||||
// return err
|
||||
// }
|
||||
|
||||
// Unavailable in 1.3.2:
|
||||
// func (c *Context) PinEntryMode() PinEntryMode {
|
||||
// return PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
|
||||
// res := PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
|
||||
// runtime.KeepAlive(c)
|
||||
// return res
|
||||
// }
|
||||
|
||||
func (c *Context) SetCallback(callback Callback) error {
|
||||
@ -340,11 +376,17 @@ func (c *Context) SetCallback(callback Callback) error {
|
||||
c.cbc = 0
|
||||
_, err = C.gogpgme_set_passphrase_cb(c.ctx, nil, 0)
|
||||
}
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) EngineInfo() *EngineInfo {
|
||||
return &EngineInfo{info: C.gpgme_ctx_get_engine_info(c.ctx)}
|
||||
cInfo := C.gpgme_ctx_get_engine_info(c.ctx)
|
||||
runtime.KeepAlive(c)
|
||||
// NOTE: c must be live as long as we are accessing cInfo.
|
||||
res := copyEngineInfo(cInfo)
|
||||
runtime.KeepAlive(c) // for accesses to cInfo
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error {
|
||||
@ -357,19 +399,23 @@ func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error
|
||||
chome = C.CString(homeDir)
|
||||
defer C.free(unsafe.Pointer(chome))
|
||||
}
|
||||
return handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
|
||||
err := handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) KeyListStart(pattern string, secretOnly bool) error {
|
||||
cpattern := C.CString(pattern)
|
||||
defer C.free(unsafe.Pointer(cpattern))
|
||||
err := C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly))
|
||||
return handleError(err)
|
||||
err := handleError(C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly)))
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) KeyListNext() bool {
|
||||
c.Key = newKey()
|
||||
err := handleError(C.gpgme_op_keylist_next(c.ctx, &c.Key.k))
|
||||
runtime.KeepAlive(c) // implies runtime.KeepAlive(c.Key)
|
||||
if err != nil {
|
||||
if e, ok := err.(Error); ok && e.Code() == ErrorEOF {
|
||||
c.KeyError = nil
|
||||
@ -383,7 +429,9 @@ func (c *Context) KeyListNext() bool {
|
||||
}
|
||||
|
||||
func (c *Context) KeyListEnd() error {
|
||||
return handleError(C.gpgme_op_keylist_end(c.ctx))
|
||||
err := handleError(C.gpgme_op_keylist_end(c.ctx))
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
|
||||
@ -391,7 +439,11 @@ func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
|
||||
cfpr := C.CString(fingerprint)
|
||||
defer C.free(unsafe.Pointer(cfpr))
|
||||
err := handleError(C.gpgme_get_key(c.ctx, cfpr, &key.k, cbool(secret)))
|
||||
if e, ok := err.(Error); key.k == nil && ok && e.Code() == ErrorEOF {
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(key)
|
||||
keyKIsNil := key.k == nil
|
||||
runtime.KeepAlive(key)
|
||||
if e, ok := err.(Error); keyKIsNil && ok && e.Code() == ErrorEOF {
|
||||
return nil, fmt.Errorf("key %q not found", fingerprint)
|
||||
}
|
||||
if err != nil {
|
||||
@ -401,11 +453,19 @@ func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
|
||||
}
|
||||
|
||||
func (c *Context) Decrypt(ciphertext, plaintext *Data) error {
|
||||
return handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
|
||||
err := handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(ciphertext)
|
||||
runtime.KeepAlive(plaintext)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) DecryptVerify(ciphertext, plaintext *Data) error {
|
||||
return handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
|
||||
err := handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(ciphertext)
|
||||
runtime.KeepAlive(plaintext)
|
||||
return err
|
||||
}
|
||||
|
||||
type Signature struct {
|
||||
@ -432,10 +492,20 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err
|
||||
plainPtr = plain.dh
|
||||
}
|
||||
err := handleError(C.gpgme_op_verify(c.ctx, sig.dh, signedTextPtr, plainPtr))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(sig)
|
||||
if signedText != nil {
|
||||
runtime.KeepAlive(signedText)
|
||||
}
|
||||
if plain != nil {
|
||||
runtime.KeepAlive(plain)
|
||||
}
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
res := C.gpgme_op_verify_result(c.ctx)
|
||||
runtime.KeepAlive(c)
|
||||
// NOTE: c must be live as long as we are accessing res.
|
||||
sigs := []Signature{}
|
||||
for s := res.signatures; s != nil; s = s.next {
|
||||
sig := Signature{
|
||||
@ -455,7 +525,9 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err
|
||||
}
|
||||
sigs = append(sigs, sig)
|
||||
}
|
||||
return C.GoString(res.file_name), sigs, nil
|
||||
fileName := C.GoString(res.file_name)
|
||||
runtime.KeepAlive(c) // for all accesses to res above
|
||||
return fileName, sigs, nil
|
||||
}
|
||||
|
||||
func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphertext *Data) error {
|
||||
@ -467,18 +539,116 @@ func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphe
|
||||
*ptr = recipients[i].k
|
||||
}
|
||||
err := C.gpgme_op_encrypt(c.ctx, (*C.gpgme_key_t)(recp), C.gpgme_encrypt_flags_t(flags), plaintext.dh, ciphertext.dh)
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(recipients)
|
||||
runtime.KeepAlive(plaintext)
|
||||
runtime.KeepAlive(ciphertext)
|
||||
return handleError(err)
|
||||
}
|
||||
|
||||
func (c *Context) Sign(signers []*Key, plain, sig *Data, mode SigMode) error {
|
||||
C.gpgme_signers_clear(c.ctx)
|
||||
runtime.KeepAlive(c)
|
||||
for _, k := range signers {
|
||||
if err := handleError(C.gpgme_signers_add(c.ctx, k.k)); err != nil {
|
||||
err := handleError(C.gpgme_signers_add(c.ctx, k.k))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(k)
|
||||
if err != nil {
|
||||
C.gpgme_signers_clear(c.ctx)
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
|
||||
err := handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(plain)
|
||||
runtime.KeepAlive(sig)
|
||||
return err
|
||||
}
|
||||
|
||||
type AssuanDataCallback func(data []byte) error
|
||||
type AssuanInquireCallback func(name, args string) error
|
||||
type AssuanStatusCallback func(status, args string) error
|
||||
|
||||
// AssuanSend sends a raw Assuan command to gpg-agent
|
||||
func (c *Context) AssuanSend(
|
||||
cmd string,
|
||||
data AssuanDataCallback,
|
||||
inquiry AssuanInquireCallback,
|
||||
status AssuanStatusCallback,
|
||||
) error {
|
||||
var operr C.gpgme_error_t
|
||||
|
||||
dataPtr := callbackAdd(&data)
|
||||
inquiryPtr := callbackAdd(&inquiry)
|
||||
statusPtr := callbackAdd(&status)
|
||||
cmdCStr := C.CString(cmd)
|
||||
defer C.free(unsafe.Pointer(cmdCStr))
|
||||
err := C.gogpgme_op_assuan_transact_ext(
|
||||
c.ctx,
|
||||
cmdCStr,
|
||||
C.uintptr_t(dataPtr),
|
||||
C.uintptr_t(inquiryPtr),
|
||||
C.uintptr_t(statusPtr),
|
||||
&operr,
|
||||
)
|
||||
runtime.KeepAlive(c)
|
||||
|
||||
if handleError(operr) != nil {
|
||||
return handleError(operr)
|
||||
}
|
||||
return handleError(err)
|
||||
}
|
||||
|
||||
//export gogpgme_assuan_data_callback
|
||||
func gogpgme_assuan_data_callback(handle unsafe.Pointer, data unsafe.Pointer, datalen C.size_t) C.gpgme_error_t {
|
||||
c := callbackLookup(uintptr(handle)).(*AssuanDataCallback)
|
||||
if *c == nil {
|
||||
return 0
|
||||
}
|
||||
(*c)(C.GoBytes(data, C.int(datalen)))
|
||||
return 0
|
||||
}
|
||||
|
||||
//export gogpgme_assuan_inquiry_callback
|
||||
func gogpgme_assuan_inquiry_callback(handle unsafe.Pointer, cName *C.char, cArgs *C.char) C.gpgme_error_t {
|
||||
name := C.GoString(cName)
|
||||
args := C.GoString(cArgs)
|
||||
c := callbackLookup(uintptr(handle)).(*AssuanInquireCallback)
|
||||
if *c == nil {
|
||||
return 0
|
||||
}
|
||||
(*c)(name, args)
|
||||
return 0
|
||||
}
|
||||
|
||||
//export gogpgme_assuan_status_callback
|
||||
func gogpgme_assuan_status_callback(handle unsafe.Pointer, cStatus *C.char, cArgs *C.char) C.gpgme_error_t {
|
||||
status := C.GoString(cStatus)
|
||||
args := C.GoString(cArgs)
|
||||
c := callbackLookup(uintptr(handle)).(*AssuanStatusCallback)
|
||||
if *c == nil {
|
||||
return 0
|
||||
}
|
||||
(*c)(status, args)
|
||||
return 0
|
||||
}
|
||||
|
||||
// ExportModeFlags defines how keys are exported from Export
|
||||
type ExportModeFlags uint
|
||||
|
||||
const (
|
||||
ExportModeExtern ExportModeFlags = C.GPGME_EXPORT_MODE_EXTERN
|
||||
ExportModeMinimal ExportModeFlags = C.GPGME_EXPORT_MODE_MINIMAL
|
||||
)
|
||||
|
||||
func (c *Context) Export(pattern string, mode ExportModeFlags, data *Data) error {
|
||||
pat := C.CString(pattern)
|
||||
defer C.free(unsafe.Pointer(pat))
|
||||
err := handleError(C.gpgme_op_export(c.ctx, pat, C.gpgme_export_mode_t(mode), data.dh))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// ImportStatusFlags describes the type of ImportStatus.Status. The C API in gpgme.h simply uses "unsigned".
|
||||
@ -517,10 +687,14 @@ type ImportResult struct {
|
||||
|
||||
func (c *Context) Import(keyData *Data) (*ImportResult, error) {
|
||||
err := handleError(C.gpgme_op_import(c.ctx, keyData.dh))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(keyData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := C.gpgme_op_import_result(c.ctx)
|
||||
runtime.KeepAlive(c)
|
||||
// NOTE: c must be live as long as we are accessing res.
|
||||
imports := []ImportStatus{}
|
||||
for s := res.imports; s != nil; s = s.next {
|
||||
imports = append(imports, ImportStatus{
|
||||
@ -529,7 +703,7 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) {
|
||||
Status: ImportStatusFlags(s.status),
|
||||
})
|
||||
}
|
||||
return &ImportResult{
|
||||
importResult := &ImportResult{
|
||||
Considered: int(res.considered),
|
||||
NoUserID: int(res.no_user_id),
|
||||
Imported: int(res.imported),
|
||||
@ -544,11 +718,13 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) {
|
||||
SecretUnchanged: int(res.secret_unchanged),
|
||||
NotImported: int(res.not_imported),
|
||||
Imports: imports,
|
||||
}, nil
|
||||
}
|
||||
runtime.KeepAlive(c) // for all accesses to res above
|
||||
return importResult, nil
|
||||
}
|
||||
|
||||
type Key struct {
|
||||
k C.gpgme_key_t
|
||||
k C.gpgme_key_t // WARNING: Call Runtime.KeepAlive(k) after ANY passing of k.k to C
|
||||
}
|
||||
|
||||
func newKey() *Key {
|
||||
@ -559,85 +735,122 @@ func newKey() *Key {
|
||||
|
||||
func (k *Key) Release() {
|
||||
C.gpgme_key_release(k.k)
|
||||
runtime.KeepAlive(k)
|
||||
k.k = nil
|
||||
}
|
||||
|
||||
func (k *Key) Revoked() bool {
|
||||
return C.key_revoked(k.k) != 0
|
||||
res := C.key_revoked(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) Expired() bool {
|
||||
return C.key_expired(k.k) != 0
|
||||
res := C.key_expired(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) Disabled() bool {
|
||||
return C.key_disabled(k.k) != 0
|
||||
res := C.key_disabled(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) Invalid() bool {
|
||||
return C.key_invalid(k.k) != 0
|
||||
res := C.key_invalid(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) CanEncrypt() bool {
|
||||
return C.key_can_encrypt(k.k) != 0
|
||||
res := C.key_can_encrypt(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) CanSign() bool {
|
||||
return C.key_can_sign(k.k) != 0
|
||||
res := C.key_can_sign(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) CanCertify() bool {
|
||||
return C.key_can_certify(k.k) != 0
|
||||
res := C.key_can_certify(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) Secret() bool {
|
||||
return C.key_secret(k.k) != 0
|
||||
res := C.key_secret(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) CanAuthenticate() bool {
|
||||
return C.key_can_authenticate(k.k) != 0
|
||||
res := C.key_can_authenticate(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) IsQualified() bool {
|
||||
return C.key_is_qualified(k.k) != 0
|
||||
res := C.key_is_qualified(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) Protocol() Protocol {
|
||||
return Protocol(k.k.protocol)
|
||||
res := Protocol(k.k.protocol)
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) IssuerSerial() string {
|
||||
return C.GoString(k.k.issuer_serial)
|
||||
res := C.GoString(k.k.issuer_serial)
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) IssuerName() string {
|
||||
return C.GoString(k.k.issuer_name)
|
||||
res := C.GoString(k.k.issuer_name)
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) ChainID() string {
|
||||
return C.GoString(k.k.chain_id)
|
||||
res := C.GoString(k.k.chain_id)
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) OwnerTrust() Validity {
|
||||
return Validity(k.k.owner_trust)
|
||||
res := Validity(k.k.owner_trust)
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) SubKeys() *SubKey {
|
||||
if k.k.subkeys == nil {
|
||||
subKeys := k.k.subkeys
|
||||
runtime.KeepAlive(k)
|
||||
if subKeys == nil {
|
||||
return nil
|
||||
}
|
||||
return &SubKey{k: k.k.subkeys, parent: k}
|
||||
return &SubKey{k: subKeys, parent: k} // The parent: k reference ensures subKeys remains valid
|
||||
}
|
||||
|
||||
func (k *Key) UserIDs() *UserID {
|
||||
if k.k.uids == nil {
|
||||
uids := k.k.uids
|
||||
runtime.KeepAlive(k)
|
||||
if uids == nil {
|
||||
return nil
|
||||
}
|
||||
return &UserID{u: k.k.uids, parent: k}
|
||||
return &UserID{u: uids, parent: k} // The parent: k reference ensures uids remains valid
|
||||
}
|
||||
|
||||
func (k *Key) KeyListMode() KeyListMode {
|
||||
return KeyListMode(k.k.keylist_mode)
|
||||
res := KeyListMode(k.k.keylist_mode)
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
type SubKey struct {
|
||||
@ -737,12 +950,3 @@ func (u *UserID) Comment() string {
|
||||
func (u *UserID) Email() string {
|
||||
return C.GoString(u.u.email)
|
||||
}
|
||||
|
||||
// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG.
|
||||
// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved
|
||||
// - and cgo can't be used in tests. So, provide this helper for test initialization.
|
||||
func unsetenvGPGAgentInfo() {
|
||||
v := C.CString("GPG_AGENT_INFO")
|
||||
defer C.free(unsafe.Pointer(v))
|
||||
C.unsetenv(v)
|
||||
}
|
||||
|
18
vendor/github.com/mtrmac/gpgme/unset_agent_info.go
generated
vendored
Normal file
18
vendor/github.com/mtrmac/gpgme/unset_agent_info.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
// +build !windows
|
||||
|
||||
package gpgme
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG.
|
||||
// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved
|
||||
// - and cgo can't be used in tests. So, provide this helper for test initialization.
|
||||
func unsetenvGPGAgentInfo() {
|
||||
v := C.CString("GPG_AGENT_INFO")
|
||||
defer C.free(unsafe.Pointer(v))
|
||||
C.unsetenv(v)
|
||||
}
|
14
vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
generated
vendored
Normal file
14
vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package gpgme
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// unsetenv is not available in mingw
|
||||
func unsetenvGPGAgentInfo() {
|
||||
v := C.CString("GPG_AGENT_INFO=")
|
||||
defer C.free(unsafe.Pointer(v))
|
||||
C.putenv(v)
|
||||
}
|
7
vendor/github.com/vbauerster/mpb/v4/bar_option.go
generated
vendored
7
vendor/github.com/vbauerster/mpb/v4/bar_option.go
generated
vendored
@ -10,11 +10,10 @@ import (
|
||||
// BarOption is a function option which changes the default behavior of a bar.
|
||||
type BarOption func(*bState)
|
||||
|
||||
type mergeWrapper interface {
|
||||
MergeUnwrap() []decor.Decorator
|
||||
}
|
||||
|
||||
func (s *bState) addDecorators(dest *[]decor.Decorator, decorators ...decor.Decorator) {
|
||||
type mergeWrapper interface {
|
||||
MergeUnwrap() []decor.Decorator
|
||||
}
|
||||
for _, decorator := range decorators {
|
||||
if mw, ok := decorator.(mergeWrapper); ok {
|
||||
*dest = append(*dest, mw.MergeUnwrap()...)
|
||||
|
27
vendor/github.com/vbauerster/mpb/v4/decor/decorator.go
generated
vendored
27
vendor/github.com/vbauerster/mpb/v4/decor/decorator.go
generated
vendored
@ -4,6 +4,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/acarl005/stripansi"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -117,25 +119,29 @@ var (
|
||||
// W represents width and C represents bit set of width related config.
|
||||
// A decorator should embed WC, to enable width synchronization.
|
||||
type WC struct {
|
||||
W int
|
||||
C int
|
||||
dynFormat string
|
||||
staticFormat string
|
||||
wsync chan int
|
||||
W int
|
||||
C int
|
||||
dynFormat string
|
||||
wsync chan int
|
||||
}
|
||||
|
||||
// FormatMsg formats final message according to WC.W and WC.C.
|
||||
// Should be called by any Decorator implementation.
|
||||
func (wc *WC) FormatMsg(msg string) string {
|
||||
var format string
|
||||
runeCount := utf8.RuneCountInString(stripansi.Strip(msg))
|
||||
ansiCount := utf8.RuneCountInString(msg) - runeCount
|
||||
if (wc.C & DSyncWidth) != 0 {
|
||||
wc.wsync <- utf8.RuneCountInString(msg)
|
||||
max := <-wc.wsync
|
||||
if (wc.C & DextraSpace) != 0 {
|
||||
max++
|
||||
runeCount++
|
||||
}
|
||||
return fmt.Sprintf(fmt.Sprintf(wc.dynFormat, max), msg)
|
||||
wc.wsync <- runeCount
|
||||
max := <-wc.wsync
|
||||
format = fmt.Sprintf(wc.dynFormat, ansiCount+max)
|
||||
} else {
|
||||
format = fmt.Sprintf(wc.dynFormat, ansiCount+wc.W)
|
||||
}
|
||||
return fmt.Sprintf(wc.staticFormat, msg)
|
||||
return fmt.Sprintf(format, msg)
|
||||
}
|
||||
|
||||
// Init initializes width related config.
|
||||
@ -145,7 +151,6 @@ func (wc *WC) Init() WC {
|
||||
wc.dynFormat += "-"
|
||||
}
|
||||
wc.dynFormat += "%ds"
|
||||
wc.staticFormat = fmt.Sprintf(wc.dynFormat, wc.W)
|
||||
if (wc.C & DSyncWidth) != 0 {
|
||||
// it's deliberate choice to override wsync on each Init() call,
|
||||
// this way globals like WCSyncSpace can be reused
|
||||
|
49
vendor/github.com/vbauerster/mpb/v4/decor/merge.go
generated
vendored
49
vendor/github.com/vbauerster/mpb/v4/decor/merge.go
generated
vendored
@ -2,6 +2,7 @@ package decor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
@ -28,10 +29,7 @@ func Merge(decorator Decorator, placeholders ...WC) Decorator {
|
||||
if (wc.C & DSyncWidth) == 0 {
|
||||
return decorator
|
||||
}
|
||||
md.placeHolders[i] = &placeHolderDecorator{
|
||||
WC: wc.Init(),
|
||||
wch: make(chan int),
|
||||
}
|
||||
md.placeHolders[i] = &placeHolderDecorator{wc.Init()}
|
||||
}
|
||||
return md
|
||||
}
|
||||
@ -69,29 +67,40 @@ func (d *mergeDecorator) Base() Decorator {
|
||||
func (d *mergeDecorator) Decor(st *Statistics) string {
|
||||
msg := d.Decorator.Decor(st)
|
||||
msgLen := utf8.RuneCountInString(msg)
|
||||
|
||||
var space int
|
||||
for _, ph := range d.placeHolders {
|
||||
space += <-ph.wch
|
||||
}
|
||||
|
||||
d.wc.wsync <- msgLen - space
|
||||
|
||||
max := <-d.wc.wsync
|
||||
if (d.wc.C & DextraSpace) != 0 {
|
||||
max++
|
||||
msgLen++
|
||||
}
|
||||
return fmt.Sprintf(fmt.Sprintf(d.wc.dynFormat, max+space), msg)
|
||||
|
||||
var total int
|
||||
max := utf8.RuneCountInString(d.placeHolders[0].FormatMsg(""))
|
||||
total += max
|
||||
pw := (msgLen - max) / len(d.placeHolders)
|
||||
rem := (msgLen - max) % len(d.placeHolders)
|
||||
|
||||
var diff int
|
||||
for i := 1; i < len(d.placeHolders); i++ {
|
||||
ph := d.placeHolders[i]
|
||||
width := pw - diff
|
||||
if (ph.WC.C & DextraSpace) != 0 {
|
||||
width--
|
||||
if width < 0 {
|
||||
width = 0
|
||||
}
|
||||
}
|
||||
max = utf8.RuneCountInString(ph.FormatMsg(strings.Repeat(" ", width)))
|
||||
total += max
|
||||
diff = max - pw
|
||||
}
|
||||
|
||||
d.wc.wsync <- pw + rem
|
||||
max = <-d.wc.wsync
|
||||
return fmt.Sprintf(fmt.Sprintf(d.wc.dynFormat, max+total), msg)
|
||||
}
|
||||
|
||||
type placeHolderDecorator struct {
|
||||
WC
|
||||
wch chan int
|
||||
}
|
||||
|
||||
func (d *placeHolderDecorator) Decor(st *Statistics) string {
|
||||
go func() {
|
||||
d.wch <- utf8.RuneCountInString(d.FormatMsg(""))
|
||||
}()
|
||||
func (d *placeHolderDecorator) Decor(_ *Statistics) string {
|
||||
return ""
|
||||
}
|
||||
|
1
vendor/github.com/vbauerster/mpb/v4/go.mod
generated
vendored
1
vendor/github.com/vbauerster/mpb/v4/go.mod
generated
vendored
@ -2,6 +2,7 @@ module github.com/vbauerster/mpb/v4
|
||||
|
||||
require (
|
||||
github.com/VividCortex/ewma v1.1.1
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
||||
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708
|
||||
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056 // indirect
|
||||
)
|
||||
|
2
vendor/github.com/vbauerster/mpb/v4/go.sum
generated
vendored
2
vendor/github.com/vbauerster/mpb/v4/go.sum
generated
vendored
@ -1,5 +1,7 @@
|
||||
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
|
||||
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708 h1:pXVtWnwHkrWD9ru3sDxY/qFK/bfc0egRovX91EjWjf4=
|
||||
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
|
8
vendor/github.com/vbauerster/mpb/v4/proxyreader.go
generated
vendored
8
vendor/github.com/vbauerster/mpb/v4/proxyreader.go
generated
vendored
@ -18,9 +18,7 @@ func (prox *proxyReader) Read(p []byte) (n int, err error) {
|
||||
prox.iT = time.Now()
|
||||
}
|
||||
if err == io.EOF {
|
||||
go func() {
|
||||
prox.bar.SetTotal(0, true)
|
||||
}()
|
||||
go prox.bar.SetTotal(0, true)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -37,9 +35,7 @@ func (prox *proxyWriterTo) WriteTo(w io.Writer) (n int64, err error) {
|
||||
prox.iT = time.Now()
|
||||
}
|
||||
if err == io.EOF {
|
||||
go func() {
|
||||
prox.bar.SetTotal(0, true)
|
||||
}()
|
||||
go prox.bar.SetTotal(0, true)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
9
vendor/modules.txt
vendored
9
vendor/modules.txt
vendored
@ -29,6 +29,8 @@ github.com/Microsoft/hcsshim/internal/wclayer
|
||||
github.com/Microsoft/hcsshim/osversion
|
||||
# github.com/VividCortex/ewma v1.1.1
|
||||
github.com/VividCortex/ewma
|
||||
# github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
||||
github.com/acarl005/stripansi
|
||||
# github.com/beorn7/perks v1.0.1
|
||||
github.com/beorn7/perks/quantile
|
||||
# github.com/blang/semver v3.5.1+incompatible
|
||||
@ -80,7 +82,7 @@ github.com/containers/common/pkg/cgroups
|
||||
github.com/containers/common/pkg/unshare
|
||||
# github.com/containers/conmon v2.0.10+incompatible
|
||||
github.com/containers/conmon/runner/config
|
||||
# github.com/containers/image/v5 v5.1.0
|
||||
# github.com/containers/image/v5 v5.2.0
|
||||
github.com/containers/image/v5/copy
|
||||
github.com/containers/image/v5/directory
|
||||
github.com/containers/image/v5/directory/explicitfilepath
|
||||
@ -91,6 +93,7 @@ github.com/containers/image/v5/docker/policyconfiguration
|
||||
github.com/containers/image/v5/docker/reference
|
||||
github.com/containers/image/v5/docker/tarfile
|
||||
github.com/containers/image/v5/image
|
||||
github.com/containers/image/v5/internal/iolimits
|
||||
github.com/containers/image/v5/internal/pkg/keyctl
|
||||
github.com/containers/image/v5/internal/tmpdir
|
||||
github.com/containers/image/v5/manifest
|
||||
@ -337,7 +340,7 @@ github.com/modern-go/reflect2
|
||||
github.com/morikuni/aec
|
||||
# github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618
|
||||
github.com/mrunalp/fileutils
|
||||
# github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c
|
||||
# github.com/mtrmac/gpgme v0.1.1
|
||||
github.com/mtrmac/gpgme
|
||||
# github.com/onsi/ginkgo v1.11.0
|
||||
github.com/onsi/ginkgo
|
||||
@ -510,7 +513,7 @@ github.com/varlink/go/varlink/idl
|
||||
github.com/vbatts/tar-split/archive/tar
|
||||
github.com/vbatts/tar-split/tar/asm
|
||||
github.com/vbatts/tar-split/tar/storage
|
||||
# github.com/vbauerster/mpb/v4 v4.11.1
|
||||
# github.com/vbauerster/mpb/v4 v4.11.2
|
||||
github.com/vbauerster/mpb/v4
|
||||
github.com/vbauerster/mpb/v4/cwriter
|
||||
github.com/vbauerster/mpb/v4/decor
|
||||
|
Reference in New Issue
Block a user