diff --git a/go.mod b/go.mod index 0f88a68a0..f1feda0fb 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/blang/semver v3.5.0+incompatible // indirect github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 // indirect github.com/containernetworking/cni v0.7.0-rc2 - github.com/containers/image v2.0.0+incompatible + github.com/containers/image v2.0.1+incompatible github.com/containers/storage v1.12.15 github.com/cyphar/filepath-securejoin v0.2.1 github.com/docker/distribution v0.0.0-20170817175659-5f6282db7d65 @@ -44,7 +44,7 @@ require ( github.com/spf13/pflag v1.0.3 github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 github.com/ulikunitz/xz v0.5.5 // indirect - github.com/vbauerster/mpb v3.3.4+incompatible // indirect + github.com/vbauerster/mpb v3.4.0+incompatible // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.1.0 // indirect diff --git a/go.sum b/go.sum index 43c14babe..da4e791b7 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,8 @@ github.com/containernetworking/cni v0.7.0-rc2 h1:2GGDhbwdWPY53iT7LXy+LBP76Ch2D/h github.com/containernetworking/cni v0.7.0-rc2/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containers/image v2.0.0+incompatible h1:FTr6Br7jlIKNCKMjSOMbAxKp2keQ0//jzJaYNTVhauk= github.com/containers/image v2.0.0+incompatible/go.mod h1:8Vtij257IWSanUQKe1tAeNOm2sRVkSqQTVQ1IlwI3+M= +github.com/containers/image v2.0.1+incompatible h1:w39mlElA/aSFZ6moFa5N+A4MWu9c8hgdMiMMYnH94Hs= +github.com/containers/image v2.0.1+incompatible/go.mod h1:8Vtij257IWSanUQKe1tAeNOm2sRVkSqQTVQ1IlwI3+M= github.com/containers/storage v1.12.10-0.20190725063046-8038df61d6f6 h1:c7Fq9bbRl0Ua6swRHAH8rkrK2fSt6K+ZBrXHD50kDR4= github.com/containers/storage v1.12.10-0.20190725063046-8038df61d6f6/go.mod h1:QsZp4XMJjyPNNbQHZeyNW3OmhwsWviI+7S6iOcu6a4c= github.com/containers/storage v1.12.13 h1:GtaLCY8p1Drlk1Oew581jGvB137UaO+kpz0HII67T0A= @@ -169,6 +171,8 @@ github.com/vbatts/tar-split v0.11.1 h1:0Odu65rhcZ3JZaPHxl7tCI3V/C/Q9Zf82UFravl02 github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpcEPSzR8z6g= github.com/vbauerster/mpb v3.3.4+incompatible h1:DDIhnwmgTQIDZo+SWlEr5d6mJBxkOLBwCXPzunhEfJ4= github.com/vbauerster/mpb v3.3.4+incompatible/go.mod h1:zAHG26FUhVKETRu+MWqYXcI70POlC6N8up9p1dID7SU= +github.com/vbauerster/mpb v3.4.0+incompatible h1:mfiiYw87ARaeRW6x5gWwYRUawxaW1tLAD8IceomUCNw= +github.com/vbauerster/mpb v3.4.0+incompatible/go.mod h1:zAHG26FUhVKETRu+MWqYXcI70POlC6N8up9p1dID7SU= github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vrothberg/storage v0.0.0-20190724065215-a1e42fd78930 h1:/LeIxi2kj5UYTJR9W35t5Pq2gqz03ZNoTURchTH3vc0= diff --git a/ostree_tag.sh b/ostree_tag.sh index 16aa8af09..6a2f2e38b 100755 --- a/ostree_tag.sh +++ b/ostree_tag.sh @@ -1,6 +1,6 @@ #!/bin/bash if pkg-config ostree-1 2> /dev/null ; then - echo constainers_image_ostree + echo containers_image_ostree else echo containers_image_ostree_stub fi diff --git a/vendor/github.com/containers/image/copy/copy.go b/vendor/github.com/containers/image/copy/copy.go index 3ed8a2b82..f1b029f97 100644 --- a/vendor/github.com/containers/image/copy/copy.go +++ b/vendor/github.com/containers/image/copy/copy.go @@ -597,15 +597,32 @@ func (c *copier) createProgressBar(pool *mpb.Progress, info types.BlobInfo, kind prefix = prefix[:maxPrefixLen] } - bar := pool.AddBar(info.Size, - mpb.BarClearOnComplete(), - mpb.PrependDecorators( - decor.Name(prefix), - ), - mpb.AppendDecorators( - decor.OnComplete(decor.CountersKibiByte("%.1f / %.1f"), " "+onComplete), - ), - ) + // Use a normal progress bar when we know the size (i.e., size > 0). + // Otherwise, use a spinner to indicate that something's happening. + var bar *mpb.Bar + if info.Size > 0 { + bar = pool.AddBar(info.Size, + mpb.BarClearOnComplete(), + mpb.PrependDecorators( + decor.Name(prefix), + ), + mpb.AppendDecorators( + decor.OnComplete(decor.CountersKibiByte("%.1f / %.1f"), " "+onComplete), + ), + ) + } else { + bar = pool.AddSpinner(info.Size, + mpb.SpinnerOnLeft, + mpb.BarClearOnComplete(), + mpb.SpinnerStyle([]string{".", "..", "...", "....", ""}), + mpb.PrependDecorators( + decor.Name(prefix), + ), + mpb.AppendDecorators( + decor.OnComplete(decor.Name(""), " "+onComplete), + ), + ) + } if c.progressOutput == ioutil.Discard { c.Printf("Copying %s %s\n", kind, info.Digest) } diff --git a/vendor/github.com/containers/image/docker/docker_image_src.go b/vendor/github.com/containers/image/docker/docker_image_src.go index c43e6e7ca..6951f31e9 100644 --- a/vendor/github.com/containers/image/docker/docker_image_src.go +++ b/vendor/github.com/containers/image/docker/docker_image_src.go @@ -138,8 +138,9 @@ func (s *dockerImageSource) GetManifest(ctx context.Context, instanceDigest *dig func (s *dockerImageSource) fetchManifest(ctx context.Context, tagOrDigest string) ([]byte, string, error) { path := fmt.Sprintf(manifestPath, reference.Path(s.ref.ref), tagOrDigest) - headers := make(map[string][]string) - headers["Accept"] = manifest.DefaultRequestedManifestMIMETypes + headers := map[string][]string{ + "Accept": manifest.DefaultRequestedManifestMIMETypes, + } res, err := s.c.makeRequest(ctx, "GET", path, headers, nil, v2Auth, nil) if err != nil { return nil, "", err @@ -381,11 +382,9 @@ func deleteImage(ctx context.Context, sys *types.SystemContext, ref dockerRefere return err } - // When retrieving the digest from a registry >= 2.3 use the following header: - // "Accept": "application/vnd.docker.distribution.manifest.v2+json" - headers := make(map[string][]string) - headers["Accept"] = []string{manifest.DockerV2Schema2MediaType} - + headers := map[string][]string{ + "Accept": manifest.DefaultRequestedManifestMIMETypes, + } refTail, err := ref.tagOrDigest() if err != nil { return err diff --git a/vendor/github.com/containers/image/docker/tarfile/src.go b/vendor/github.com/containers/image/docker/tarfile/src.go index 03735f8a4..dd5d78fe8 100644 --- a/vendor/github.com/containers/image/docker/tarfile/src.go +++ b/vendor/github.com/containers/image/docker/tarfile/src.go @@ -15,24 +15,24 @@ import ( "github.com/containers/image/manifest" "github.com/containers/image/pkg/compression" "github.com/containers/image/types" - "github.com/opencontainers/go-digest" + digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" ) // Source is a partial implementation of types.ImageSource for reading from tarPath. type Source struct { tarPath string - removeTarPathOnClose bool // Remove temp file on close if true - cacheDataLock sync.Once // Atomic way to ensure that ensureCachedDataIsPresent is only invoked once + removeTarPathOnClose bool // Remove temp file on close if true // The following data is only available after ensureCachedDataIsPresent() succeeds - cacheDataResult error // The return value of ensureCachedDataIsPresent, since it should be as safe to cache as the side effects tarManifest *ManifestItem // nil if not available yet. configBytes []byte configDigest digest.Digest orderedDiffIDList []digest.Digest knownLayers map[digest.Digest]*layerInfo // Other state - generatedManifest []byte // Private cache for GetManifest(), nil if not set yet. + generatedManifest []byte // Private cache for GetManifest(), nil if not set yet. + cacheDataLock sync.Once // Private state for ensureCachedDataIsPresent to make it concurrency-safe + cacheDataResult error // Private state for ensureCachedDataIsPresent } type layerInfo struct { @@ -201,49 +201,52 @@ func (s *Source) readTarComponent(path string) ([]byte, error) { } // ensureCachedDataIsPresent loads data necessary for any of the public accessors. +// It is safe to call this from multi-threaded code. func (s *Source) ensureCachedDataIsPresent() error { s.cacheDataLock.Do(func() { - // Read and parse manifest.json - tarManifest, err := s.loadTarManifest() - if err != nil { - s.cacheDataResult = err - return - } - - // Check to make sure length is 1 - if len(tarManifest) != 1 { - s.cacheDataResult = errors.Errorf("Unexpected tar manifest.json: expected 1 item, got %d", len(tarManifest)) - return - } - - // Read and parse config. - configBytes, err := s.readTarComponent(tarManifest[0].Config) - if err != nil { - s.cacheDataResult = err - return - } - var parsedConfig manifest.Schema2Image // There's a lot of info there, but we only really care about layer DiffIDs. - if err := json.Unmarshal(configBytes, &parsedConfig); err != nil { - s.cacheDataResult = errors.Wrapf(err, "Error decoding tar config %s", tarManifest[0].Config) - return - } - - knownLayers, err := s.prepareLayerData(&tarManifest[0], &parsedConfig) - if err != nil { - s.cacheDataResult = err - return - } - - // Success; commit. - s.tarManifest = &tarManifest[0] - s.configBytes = configBytes - s.configDigest = digest.FromBytes(configBytes) - s.orderedDiffIDList = parsedConfig.RootFS.DiffIDs - s.knownLayers = knownLayers + s.cacheDataResult = s.ensureCachedDataIsPresentPrivate() }) return s.cacheDataResult } +// ensureCachedDataIsPresentPrivate is a private implementation detail of ensureCachedDataIsPresent. +// Call ensureCachedDataIsPresent instead. +func (s *Source) ensureCachedDataIsPresentPrivate() error { + // Read and parse manifest.json + tarManifest, err := s.loadTarManifest() + if err != nil { + return err + } + + // Check to make sure length is 1 + if len(tarManifest) != 1 { + return errors.Errorf("Unexpected tar manifest.json: expected 1 item, got %d", len(tarManifest)) + } + + // Read and parse config. + configBytes, err := s.readTarComponent(tarManifest[0].Config) + if err != nil { + return err + } + var parsedConfig manifest.Schema2Image // There's a lot of info there, but we only really care about layer DiffIDs. + if err := json.Unmarshal(configBytes, &parsedConfig); err != nil { + return errors.Wrapf(err, "Error decoding tar config %s", tarManifest[0].Config) + } + + knownLayers, err := s.prepareLayerData(&tarManifest[0], &parsedConfig) + if err != nil { + return err + } + + // Success; commit. + s.tarManifest = &tarManifest[0] + s.configBytes = configBytes + s.configDigest = digest.FromBytes(configBytes) + s.orderedDiffIDList = parsedConfig.RootFS.DiffIDs + s.knownLayers = knownLayers + return nil +} + // loadTarManifest loads and decodes the manifest.json. func (s *Source) loadTarManifest() ([]ManifestItem, error) { // FIXME? Do we need to deal with the legacy format? diff --git a/vendor/github.com/containers/image/manifest/docker_schema1.go b/vendor/github.com/containers/image/manifest/docker_schema1.go index 1ba65d5be..b76286b8f 100644 --- a/vendor/github.com/containers/image/manifest/docker_schema1.go +++ b/vendor/github.com/containers/image/manifest/docker_schema1.go @@ -226,6 +226,7 @@ func (m *Schema1) Inspect(_ func(types.BlobInfo) ([]byte, error)) (*types.ImageI } if s1.Config != nil { i.Labels = s1.Config.Labels + i.Env = s1.Config.Env } return i, nil } diff --git a/vendor/github.com/containers/image/manifest/docker_schema2.go b/vendor/github.com/containers/image/manifest/docker_schema2.go index 0671aed9f..76a80e5a6 100644 --- a/vendor/github.com/containers/image/manifest/docker_schema2.go +++ b/vendor/github.com/containers/image/manifest/docker_schema2.go @@ -241,6 +241,7 @@ func (m *Schema2) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*t } if s2.Config != nil { i.Labels = s2.Config.Labels + i.Env = s2.Config.Env } return i, nil } diff --git a/vendor/github.com/containers/image/manifest/oci.go b/vendor/github.com/containers/image/manifest/oci.go index 91705045b..dd65e0ba2 100644 --- a/vendor/github.com/containers/image/manifest/oci.go +++ b/vendor/github.com/containers/image/manifest/oci.go @@ -116,6 +116,7 @@ func (m *OCI1) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*type Architecture: v1.Architecture, Os: v1.OS, Layers: layerInfosToStrings(m.LayerInfos()), + Env: d1.Config.Env, } return i, nil } diff --git a/vendor/github.com/containers/image/ostree/ostree_dest.go b/vendor/github.com/containers/image/ostree/ostree_dest.go index d69f4fa33..06a905aed 100644 --- a/vendor/github.com/containers/image/ostree/ostree_dest.go +++ b/vendor/github.com/containers/image/ostree/ostree_dest.go @@ -1,4 +1,4 @@ -// +build !containers_image_ostree_stub +// +build containers_image_ostree package ostree @@ -218,7 +218,7 @@ func fixFiles(selinuxHnd *C.struct_selabel_handle, root string, dir string, user defer C.free(unsafe.Pointer(fullpathC)) res, err = C.lsetfilecon_raw(fullpathC, context) if int(res) < 0 { - return errors.Wrapf(err, "cannot setfilecon_raw %s", fullpath) + return errors.Wrapf(err, "cannot setfilecon_raw %s to %s", fullpath, C.GoString(context)) } } } diff --git a/vendor/github.com/containers/image/ostree/ostree_src.go b/vendor/github.com/containers/image/ostree/ostree_src.go index 35d852139..dc52ccb6e 100644 --- a/vendor/github.com/containers/image/ostree/ostree_src.go +++ b/vendor/github.com/containers/image/ostree/ostree_src.go @@ -1,4 +1,4 @@ -// +build !containers_image_ostree_stub +// +build containers_image_ostree package ostree diff --git a/vendor/github.com/containers/image/ostree/ostree_transport.go b/vendor/github.com/containers/image/ostree/ostree_transport.go index c9856530b..2e86623ac 100644 --- a/vendor/github.com/containers/image/ostree/ostree_transport.go +++ b/vendor/github.com/containers/image/ostree/ostree_transport.go @@ -1,4 +1,4 @@ -// +build !containers_image_ostree_stub +// +build containers_image_ostree package ostree diff --git a/vendor/github.com/containers/image/pkg/docker/config/config.go b/vendor/github.com/containers/image/pkg/docker/config/config.go index 57b548e26..2e6bb378f 100644 --- a/vendor/github.com/containers/image/pkg/docker/config/config.go +++ b/vendor/github.com/containers/image/pkg/docker/config/config.go @@ -56,6 +56,7 @@ func SetAuthentication(sys *types.SystemContext, registry, username, password st // If an entry is not found empty strings are returned for the username and password func GetAuthentication(sys *types.SystemContext, registry string) (string, string, error) { if sys != nil && sys.DockerAuthConfig != nil { + logrus.Debug("Returning credentials from DockerAuthConfig") return sys.DockerAuthConfig.Username, sys.DockerAuthConfig.Password, nil } @@ -76,12 +77,15 @@ func GetAuthentication(sys *types.SystemContext, registry string) (string, strin legacyFormat := path == dockerLegacyPath username, password, err := findAuthentication(registry, path, legacyFormat) if err != nil { + logrus.Debugf("Credentials not found") return "", "", err } if username != "" && password != "" { + logrus.Debugf("Returning credentials from %s", path) return username, password, nil } } + logrus.Debugf("Credentials not found") return "", "", nil } diff --git a/vendor/github.com/containers/image/pkg/sysregistriesv2/system_registries_v2.go b/vendor/github.com/containers/image/pkg/sysregistriesv2/system_registries_v2.go index 361e6fc60..0c13913ed 100644 --- a/vendor/github.com/containers/image/pkg/sysregistriesv2/system_registries_v2.go +++ b/vendor/github.com/containers/image/pkg/sysregistriesv2/system_registries_v2.go @@ -30,10 +30,10 @@ const builtinRegistriesConfPath = "/etc/containers/registries.conf" // Endpoint describes a remote location of a registry. type Endpoint struct { // The endpoint's remote location. - Location string `toml:"location"` + Location string `toml:"location,omitempty"` // If true, certs verification will be skipped and HTTP (non-TLS) // connections will be allowed. - Insecure bool `toml:"insecure"` + Insecure bool `toml:"insecure,omitempty"` } // rewriteReference will substitute the provided reference `prefix` to the @@ -56,22 +56,22 @@ func (e *Endpoint) rewriteReference(ref reference.Named, prefix string) (referen // Registry represents a registry. type Registry struct { - // A registry is an Endpoint too - Endpoint - // The registry's mirrors. - Mirrors []Endpoint `toml:"mirror"` - // If true, pulling from the registry will be blocked. - Blocked bool `toml:"blocked"` - // If true, mirrors will only be used for digest pulls. Pulling images by - // tag can potentially yield different images, depending on which endpoint - // we pull from. Forcing digest-pulls for mirrors avoids that issue. - MirrorByDigestOnly bool `toml:"mirror-by-digest-only"` // Prefix is used for matching images, and to translate one namespace to // another. If `Prefix="example.com/bar"`, `location="example.com/foo/bar"` // and we pull from "example.com/bar/myimage:latest", the image will // effectively be pulled from "example.com/foo/bar/myimage:latest". // If no Prefix is specified, it defaults to the specified location. Prefix string `toml:"prefix"` + // A registry is an Endpoint too + Endpoint + // The registry's mirrors. + Mirrors []Endpoint `toml:"mirror,omitempty"` + // If true, pulling from the registry will be blocked. + Blocked bool `toml:"blocked,omitempty"` + // If true, mirrors will only be used for digest pulls. Pulling images by + // tag can potentially yield different images, depending on which endpoint + // we pull from. Forcing digest-pulls for mirrors avoids that issue. + MirrorByDigestOnly bool `toml:"mirror-by-digest-only,omitempty"` } // PullSource consists of an Endpoint and a Reference. Note that the reference is diff --git a/vendor/github.com/containers/image/storage/storage_image.go b/vendor/github.com/containers/image/storage/storage_image.go index b39d2bcc0..946a85f7b 100644 --- a/vendor/github.com/containers/image/storage/storage_image.go +++ b/vendor/github.com/containers/image/storage/storage_image.go @@ -491,14 +491,21 @@ func (s *storageImageDestination) TryReusingBlob(ctx context.Context, blobinfo t // Does the blob correspond to a known DiffID which we already have available? // Because we must return the size, which is unknown for unavailable compressed blobs, the returned BlobInfo refers to the - // uncompressed layer, and that can happen only if canSubstitute. - if canSubstitute { + // uncompressed layer, and that can happen only if canSubstitute, or if the incoming manifest already specifies the size. + if canSubstitute || blobinfo.Size != -1 { if uncompressedDigest := cache.UncompressedDigest(blobinfo.Digest); uncompressedDigest != "" && uncompressedDigest != blobinfo.Digest { layers, err := s.imageRef.transport.store.LayersByUncompressedDigest(uncompressedDigest) if err != nil && errors.Cause(err) != storage.ErrLayerUnknown { return false, types.BlobInfo{}, errors.Wrapf(err, `Error looking for layers with digest %q`, uncompressedDigest) } if len(layers) > 0 { + if blobinfo.Size != -1 { + s.blobDiffIDs[blobinfo.Digest] = layers[0].UncompressedDigest + return true, blobinfo, nil + } + if !canSubstitute { + return false, types.BlobInfo{}, fmt.Errorf("Internal error: canSubstitute was expected to be true for blobInfo %v", blobinfo) + } s.blobDiffIDs[uncompressedDigest] = layers[0].UncompressedDigest return true, types.BlobInfo{ Digest: uncompressedDigest, @@ -627,7 +634,7 @@ func (s *storageImageDestination) Commit(ctx context.Context) error { if !ok { // Try to find the layer with contents matching that blobsum. layer := "" - layers, err2 := s.imageRef.transport.store.LayersByUncompressedDigest(blob.Digest) + layers, err2 := s.imageRef.transport.store.LayersByUncompressedDigest(diffID) if err2 == nil && len(layers) > 0 { layer = layers[0].ID } else { diff --git a/vendor/github.com/containers/image/transports/alltransports/ostree.go b/vendor/github.com/containers/image/transports/alltransports/ostree.go index 4a3b29a00..cc4d69fe8 100644 --- a/vendor/github.com/containers/image/transports/alltransports/ostree.go +++ b/vendor/github.com/containers/image/transports/alltransports/ostree.go @@ -1,4 +1,4 @@ -// +build !containers_image_ostree_stub,linux +// +build containers_image_ostree,linux package alltransports diff --git a/vendor/github.com/containers/image/transports/alltransports/ostree_stub.go b/vendor/github.com/containers/image/transports/alltransports/ostree_stub.go index 48fcaa58d..fb5b96e54 100644 --- a/vendor/github.com/containers/image/transports/alltransports/ostree_stub.go +++ b/vendor/github.com/containers/image/transports/alltransports/ostree_stub.go @@ -1,4 +1,4 @@ -// +build containers_image_ostree_stub !linux +// +build !containers_image_ostree !linux package alltransports diff --git a/vendor/github.com/containers/image/types/types.go b/vendor/github.com/containers/image/types/types.go index 789504348..08b4241e0 100644 --- a/vendor/github.com/containers/image/types/types.go +++ b/vendor/github.com/containers/image/types/types.go @@ -398,6 +398,7 @@ type ImageInspectInfo struct { Architecture string Os string Layers []string + Env []string } // DockerAuthConfig contains authorization information for connecting to a registry. diff --git a/vendor/github.com/containers/image/version/version.go b/vendor/github.com/containers/image/version/version.go index 62b2c8bc5..807daf7a2 100644 --- a/vendor/github.com/containers/image/version/version.go +++ b/vendor/github.com/containers/image/version/version.go @@ -8,7 +8,7 @@ const ( // VersionMinor is for functionality in a backwards-compatible manner VersionMinor = 0 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 0 + VersionPatch = 1 // VersionDev indicates development branch. Releases will be empty string. VersionDev = "" diff --git a/vendor/github.com/vbauerster/mpb/.travis.yml b/vendor/github.com/vbauerster/mpb/.travis.yml index a7fd7763a..c982d1f90 100644 --- a/vendor/github.com/vbauerster/mpb/.travis.yml +++ b/vendor/github.com/vbauerster/mpb/.travis.yml @@ -1,8 +1,8 @@ language: go sudo: false go: - - 1.8.x - - 1.9.x + - 1.10.x + - tip before_install: - go get -t -v ./... diff --git a/vendor/github.com/vbauerster/mpb/README.md b/vendor/github.com/vbauerster/mpb/README.md index 9b760647e..f96857c47 100644 --- a/vendor/github.com/vbauerster/mpb/README.md +++ b/vendor/github.com/vbauerster/mpb/README.md @@ -31,8 +31,6 @@ _Note:_ it is preferable to go get from github.com, rather than gopkg.in. See is p := mpb.New( // override default (80) width mpb.WithWidth(64), - // override default "[=>-]" format - mpb.WithFormat("╢▌▌░╟"), // override default 120ms refresh rate mpb.WithRefreshRate(180*time.Millisecond), ) @@ -41,6 +39,8 @@ _Note:_ it is preferable to go get from github.com, rather than gopkg.in. See is name := "Single Bar:" // adding a single bar bar := p.AddBar(int64(total), + // override default "[=>-]" style + mpb.BarStyle("╢▌▌░╟"), mpb.PrependDecorators( // display our name with one space on the right decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight}), diff --git a/vendor/github.com/vbauerster/mpb/bar.go b/vendor/github.com/vbauerster/mpb/bar.go index 5a506fc84..a304a87cb 100644 --- a/vendor/github.com/vbauerster/mpb/bar.go +++ b/vendor/github.com/vbauerster/mpb/bar.go @@ -2,6 +2,7 @@ package mpb import ( "bytes" + "context" "fmt" "io" "io/ioutil" @@ -11,21 +12,8 @@ import ( "unicode/utf8" "github.com/vbauerster/mpb/decor" - "github.com/vbauerster/mpb/internal" ) -const ( - rLeft = iota - rFill - rTip - rEmpty - rRight -) - -const formatLen = 5 - -type barRunes [formatLen]rune - // Bar represents a progress Bar type Bar struct { priority int @@ -45,15 +33,30 @@ type Bar struct { shutdown chan struct{} } +// Filler interface. +// Bar renders by calling Filler's Fill method. You can literally have +// any bar kind, by implementing this interface and passing it to the +// Add method. +type Filler interface { + Fill(w io.Writer, width int, s *decor.Statistics) +} + +// FillerFunc is function type adapter to convert function into Filler. +type FillerFunc func(w io.Writer, width int, stat *decor.Statistics) + +func (f FillerFunc) Fill(w io.Writer, width int, stat *decor.Statistics) { + f(w, width, stat) +} + type ( bState struct { + filler Filler id int width int + alignment int total int64 current int64 - runes barRunes - trimLeftSpace bool - trimRightSpace bool + trimSpace bool toComplete bool removeOnComplete bool barClearOnComplete bool @@ -73,8 +76,8 @@ type ( runningBar *Bar } refill struct { - char rune - till int64 + r rune + limit int64 } frameReader struct { io.Reader @@ -84,14 +87,20 @@ type ( } ) -func newBar(wg *sync.WaitGroup, id int, total int64, cancel <-chan struct{}, options ...BarOption) *Bar { - if total <= 0 { - total = time.Now().Unix() - } +func newBar( + ctx context.Context, + wg *sync.WaitGroup, + filler Filler, + id, width int, + total int64, + options ...BarOption, +) *Bar { s := &bState{ + filler: filler, id: id, priority: id, + width: width, total: total, } @@ -104,6 +113,9 @@ func newBar(wg *sync.WaitGroup, id int, total int64, cancel <-chan struct{}, opt s.bufP = bytes.NewBuffer(make([]byte, 0, s.width)) s.bufB = bytes.NewBuffer(make([]byte, 0, s.width)) s.bufA = bytes.NewBuffer(make([]byte, 0, s.width)) + if s.newLineExtendFn != nil { + s.bufNL = bytes.NewBuffer(make([]byte, 0, s.width)) + } b := &Bar{ priority: s.priority, @@ -121,11 +133,7 @@ func newBar(wg *sync.WaitGroup, id int, total int64, cancel <-chan struct{}, opt b.priority = b.runningBar.priority } - if s.newLineExtendFn != nil { - s.bufNL = bytes.NewBuffer(make([]byte, 0, s.width)) - } - - go b.serve(wg, s, cancel) + go b.serve(ctx, wg, s) return b } @@ -178,52 +186,42 @@ func (b *Bar) Current() int64 { } // SetTotal sets total dynamically. -// Set final to true, when total is known, it will trigger bar complete event. -func (b *Bar) SetTotal(total int64, final bool) bool { +// Set complete to true, to trigger bar complete event now. +func (b *Bar) SetTotal(total int64, complete bool) { select { case b.operateState <- func(s *bState) { - if total > 0 { - s.total = total - } - if final { + s.total = total + if complete && !s.toComplete { s.current = s.total s.toComplete = true } }: - return true case <-b.done: - return false } } -// SetRefill sets fill rune to r, up until n. -func (b *Bar) SetRefill(n int, r rune) { - if n <= 0 { - return - } +// SetRefill sets refill, if supported by underlying Filler. +func (b *Bar) SetRefill(amount int64) { b.operateState <- func(s *bState) { - s.refill = &refill{r, int64(n)} + if f, ok := s.filler.(interface{ SetRefill(int64) }); ok { + f.SetRefill(amount) + } } } -// RefillBy is deprecated, use SetRefill -func (b *Bar) RefillBy(n int, r rune) { - b.SetRefill(n, r) -} - // Increment is a shorthand for b.IncrBy(1). func (b *Bar) Increment() { b.IncrBy(1) } // IncrBy increments progress bar by amount of n. -// wdd is optional work duration i.e. time.Since(start), -// which expected to be provided, if any ewma based decorator is used. +// wdd is optional work duration i.e. time.Since(start), which expected +// to be provided, if any ewma based decorator is used. func (b *Bar) IncrBy(n int, wdd ...time.Duration) { select { case b.operateState <- func(s *bState) { s.current += int64(n) - if s.current >= s.total { + if s.total > 0 && s.current >= s.total { s.current = s.total s.toComplete = true } @@ -238,9 +236,9 @@ func (b *Bar) IncrBy(n int, wdd ...time.Duration) { // Completed reports whether the bar is in completed state. func (b *Bar) Completed() bool { // omit select here, because primary usage of the method is for loop - // condition, like for !bar.Completed() {...} - // so when toComplete=true it is called once (at which time, the bar is still alive), - // then quits the loop and never suppose to be called afterwards. + // condition, like for !bar.Completed() {...} so when toComplete=true + // it is called once (at which time, the bar is still alive), then + // quits the loop and never suppose to be called afterwards. return <-b.boolCh } @@ -253,8 +251,9 @@ func (b *Bar) wSyncTable() [][]chan int { } } -func (b *Bar) serve(wg *sync.WaitGroup, s *bState, cancel <-chan struct{}) { +func (b *Bar) serve(ctx context.Context, wg *sync.WaitGroup, s *bState) { defer wg.Done() + cancel := ctx.Done() for { select { case op := <-b.operateState: @@ -322,8 +321,6 @@ func (b *Bar) render(debugOut io.Writer, tw int) { } func (s *bState) draw(termWidth int) io.Reader { - defer s.bufA.WriteByte('\n') - if s.panicMsg != "" { return strings.NewReader(fmt.Sprintf(fmt.Sprintf("%%.%ds\n", termWidth), s.panicMsg)) } @@ -338,77 +335,32 @@ func (s *bState) draw(termWidth int) io.Reader { s.bufA.WriteString(d.Decor(stat)) } - prependCount := utf8.RuneCount(s.bufP.Bytes()) - appendCount := utf8.RuneCount(s.bufA.Bytes()) - if s.barClearOnComplete && s.completeFlushed { + s.bufA.WriteByte('\n') return io.MultiReader(s.bufP, s.bufA) } - s.fillBar(s.width) - barCount := utf8.RuneCount(s.bufB.Bytes()) - totalCount := prependCount + barCount + appendCount - if spaceCount := 0; totalCount > termWidth { - if !s.trimLeftSpace { - spaceCount++ - } - if !s.trimRightSpace { - spaceCount++ - } - s.fillBar(termWidth - prependCount - appendCount - spaceCount) - } + prependCount := utf8.RuneCount(s.bufP.Bytes()) + appendCount := utf8.RuneCount(s.bufA.Bytes()) - return io.MultiReader(s.bufP, s.bufB, s.bufA) -} - -func (s *bState) fillBar(width int) { - defer func() { - s.bufB.WriteRune(s.runes[rRight]) - if !s.trimRightSpace { - s.bufB.WriteByte(' ') - } - }() - - s.bufB.Reset() - if !s.trimLeftSpace { + if !s.trimSpace { + // reserve space for edge spaces + termWidth -= 2 s.bufB.WriteByte(' ') } - s.bufB.WriteRune(s.runes[rLeft]) - if width <= 2 { - return - } - // bar s.width without leftEnd and rightEnd runes - barWidth := width - 2 - - completedWidth := internal.Percentage(s.total, s.current, int64(barWidth)) - - if s.refill != nil { - till := internal.Percentage(s.total, s.refill.till, int64(barWidth)) - // append refill rune - var i int64 - for i = 0; i < till; i++ { - s.bufB.WriteRune(s.refill.char) - } - for i = till; i < completedWidth; i++ { - s.bufB.WriteRune(s.runes[rFill]) - } + if prependCount+s.width+appendCount > termWidth { + s.filler.Fill(s.bufB, termWidth-prependCount-appendCount, stat) } else { - var i int64 - for i = 0; i < completedWidth; i++ { - s.bufB.WriteRune(s.runes[rFill]) - } + s.filler.Fill(s.bufB, s.width, stat) } - if completedWidth < int64(barWidth) && completedWidth > 0 { - _, size := utf8.DecodeLastRune(s.bufB.Bytes()) - s.bufB.Truncate(s.bufB.Len() - size) - s.bufB.WriteRune(s.runes[rTip]) + if !s.trimSpace { + s.bufB.WriteByte(' ') } - for i := completedWidth; i < int64(barWidth); i++ { - s.bufB.WriteRune(s.runes[rEmpty]) - } + s.bufA.WriteByte('\n') + return io.MultiReader(s.bufP, s.bufB, s.bufA) } func (s *bState) wSyncTable() [][]chan int { @@ -442,14 +394,6 @@ func newStatistics(s *bState) *decor.Statistics { } } -func strToBarRunes(format string) (array barRunes) { - for i, n := 0, 0; len(format) > 0; i++ { - array[i], n = utf8.DecodeRuneInString(format) - format = format[n:] - } - return -} - func countLines(b []byte) int { return bytes.Count(b, []byte("\n")) } diff --git a/vendor/github.com/vbauerster/mpb/bar_filler.go b/vendor/github.com/vbauerster/mpb/bar_filler.go new file mode 100644 index 000000000..4e9285ca5 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/bar_filler.go @@ -0,0 +1,111 @@ +package mpb + +import ( + "io" + "unicode/utf8" + + "github.com/vbauerster/mpb/decor" + "github.com/vbauerster/mpb/internal" +) + +const ( + rLeft = iota + rFill + rTip + rEmpty + rRight + rRevTip + rRefill +) + +var defaultBarStyle = "[=>-]<+" + +type barFiller struct { + format [][]byte + refillAmount int64 + reverse bool +} + +func newDefaultBarFiller() Filler { + bf := &barFiller{ + format: make([][]byte, utf8.RuneCountInString(defaultBarStyle)), + } + bf.setStyle(defaultBarStyle) + return bf +} + +func (s *barFiller) setStyle(style string) { + if !utf8.ValidString(style) { + return + } + src := make([][]byte, 0, utf8.RuneCountInString(style)) + for _, r := range style { + src = append(src, []byte(string(r))) + } + copy(s.format, src) +} + +func (s *barFiller) setReverse() { + s.reverse = true +} + +func (s *barFiller) SetRefill(amount int64) { + s.refillAmount = amount +} + +func (s *barFiller) Fill(w io.Writer, width int, stat *decor.Statistics) { + + // don't count rLeft and rRight [brackets] + width -= 2 + if width < 2 { + return + } + + w.Write(s.format[rLeft]) + if width == 2 { + w.Write(s.format[rRight]) + return + } + + bb := make([][]byte, width) + + cwidth := int(internal.Percentage(stat.Total, stat.Current, int64(width))) + + for i := 0; i < cwidth; i++ { + bb[i] = s.format[rFill] + } + + if s.refillAmount > 0 { + var rwidth int + if s.refillAmount > stat.Current { + rwidth = cwidth + } else { + rwidth = int(internal.Percentage(stat.Total, int64(s.refillAmount), int64(width))) + } + for i := 0; i < rwidth; i++ { + bb[i] = s.format[rRefill] + } + } + + if cwidth > 0 && cwidth < width { + bb[cwidth-1] = s.format[rTip] + } + + for i := cwidth; i < width; i++ { + bb[i] = s.format[rEmpty] + } + + if s.reverse { + if cwidth > 0 && cwidth < width { + bb[cwidth-1] = s.format[rRevTip] + } + for i := len(bb) - 1; i >= 0; i-- { + w.Write(bb[i]) + } + } else { + for i := 0; i < len(bb); i++ { + w.Write(bb[i]) + } + } + w.Write(s.format[rRight]) +} diff --git a/vendor/github.com/vbauerster/mpb/bar_option.go b/vendor/github.com/vbauerster/mpb/bar_option.go index e33bce4da..e9a4bd2a7 100644 --- a/vendor/github.com/vbauerster/mpb/bar_option.go +++ b/vendor/github.com/vbauerster/mpb/bar_option.go @@ -6,11 +6,10 @@ import ( "github.com/vbauerster/mpb/decor" ) -// BarOption is a function option which changes the default behavior of a bar, -// if passed to p.AddBar(int64, ...BarOption) +// BarOption is a function option which changes the default behavior of a bar. type BarOption func(*bState) -// AppendDecorators let you inject decorators to the bar's right side +// AppendDecorators let you inject decorators to the bar's right side. func AppendDecorators(appenders ...decor.Decorator) BarOption { return func(s *bState) { for _, decorator := range appenders { @@ -25,7 +24,7 @@ func AppendDecorators(appenders ...decor.Decorator) BarOption { } } -// PrependDecorators let you inject decorators to the bar's left side +// PrependDecorators let you inject decorators to the bar's left side. func PrependDecorators(prependers ...decor.Decorator) BarOption { return func(s *bState) { for _, decorator := range prependers { @@ -40,85 +39,155 @@ func PrependDecorators(prependers ...decor.Decorator) BarOption { } } -// BarTrimLeft trims left side space of the bar -func BarTrimLeft() BarOption { - return func(s *bState) { - s.trimLeftSpace = true - } -} - -// BarTrimRight trims right space of the bar -func BarTrimRight() BarOption { - return func(s *bState) { - s.trimRightSpace = true - } -} - -// BarTrim trims both left and right spaces of the bar -func BarTrim() BarOption { - return func(s *bState) { - s.trimLeftSpace = true - s.trimRightSpace = true - } -} - -// BarID overwrites internal bar id +// BarID sets bar id. func BarID(id int) BarOption { return func(s *bState) { s.id = id } } -// BarRemoveOnComplete is a flag, if set whole bar line will be removed on complete event. -// If both BarRemoveOnComplete and BarClearOnComplete are set, first bar section gets cleared -// and then whole bar line gets removed completely. +// BarWidth sets bar width independent of the container. +func BarWidth(width int) BarOption { + return func(s *bState) { + s.width = width + } +} + +// BarRemoveOnComplete is a flag, if set whole bar line will be removed +// on complete event. If both BarRemoveOnComplete and BarClearOnComplete +// are set, first bar section gets cleared and then whole bar line +// gets removed completely. func BarRemoveOnComplete() BarOption { return func(s *bState) { s.removeOnComplete = true } } -// BarReplaceOnComplete is indicator for delayed bar start, after the `runningBar` is complete. -// To achieve bar replacement effect, `runningBar` should has its `BarRemoveOnComplete` option set. +// BarReplaceOnComplete is indicator for delayed bar start, after the +// `runningBar` is complete. To achieve bar replacement effect, +// `runningBar` should has its `BarRemoveOnComplete` option set. func BarReplaceOnComplete(runningBar *Bar) BarOption { + return BarParkTo(runningBar) +} + +// BarParkTo same as BarReplaceOnComplete +func BarParkTo(runningBar *Bar) BarOption { return func(s *bState) { s.runningBar = runningBar } } -// BarClearOnComplete is a flag, if set will clear bar section on complete event. -// If you need to remove a whole bar line, refer to BarRemoveOnComplete. +// BarClearOnComplete is a flag, if set will clear bar section on +// complete event. If you need to remove a whole bar line, refer to +// BarRemoveOnComplete. func BarClearOnComplete() BarOption { return func(s *bState) { s.barClearOnComplete = true } } -// BarPriority sets bar's priority. -// Zero is highest priority, i.e. bar will be on top. -// If `BarReplaceOnComplete` option is supplied, this option is ignored. +// BarPriority sets bar's priority. Zero is highest priority, i.e. bar +// will be on top. If `BarReplaceOnComplete` option is supplied, this +// option is ignored. func BarPriority(priority int) BarOption { return func(s *bState) { s.priority = priority } } -// BarNewLineExtend takes user defined efn, which gets called each render cycle. -// Any write to provided writer of efn, will appear on new line of respective bar. +// BarNewLineExtend takes user defined efn, which gets called each +// render cycle. Any write to provided writer of efn, will appear on +// new line of respective bar. func BarNewLineExtend(efn func(io.Writer, *decor.Statistics)) BarOption { return func(s *bState) { s.newLineExtendFn = efn } } -func barWidth(w int) BarOption { +// TrimSpace trims bar's edge spaces. +func TrimSpace() BarOption { return func(s *bState) { - s.width = w + s.trimSpace = true } } -func barFormat(format string) BarOption { +// BarStyle sets custom bar style, default one is "[=>-]<+". +// +// '[' left bracket rune +// +// '=' fill rune +// +// '>' tip rune +// +// '-' empty rune +// +// ']' right bracket rune +// +// '<' reverse tip rune, used when BarReverse option is set +// +// '+' refill rune, used when *Bar.SetRefill(int64) is called +// +// It's ok to provide first five runes only, for example mpb.BarStyle("╢▌▌░╟") +func BarStyle(style string) BarOption { + chk := func(filler Filler) (interface{}, bool) { + if style == "" { + return nil, false + } + t, ok := filler.(*barFiller) + return t, ok + } + cb := func(t interface{}) { + t.(*barFiller).setStyle(style) + } + return MakeFillerTypeSpecificBarOption(chk, cb) +} + +// BarReverse reverse mode, bar will progress from right to left. +func BarReverse() BarOption { + chk := func(filler Filler) (interface{}, bool) { + t, ok := filler.(*barFiller) + return t, ok + } + cb := func(t interface{}) { + t.(*barFiller).setReverse() + } + return MakeFillerTypeSpecificBarOption(chk, cb) +} + +// SpinnerStyle sets custom spinner style. +// Effective when Filler type is spinner. +func SpinnerStyle(frames []string) BarOption { + chk := func(filler Filler) (interface{}, bool) { + if len(frames) == 0 { + return nil, false + } + t, ok := filler.(*spinnerFiller) + return t, ok + } + cb := func(t interface{}) { + t.(*spinnerFiller).frames = frames + } + return MakeFillerTypeSpecificBarOption(chk, cb) +} + +// MakeFillerTypeSpecificBarOption makes BarOption specific to Filler's +// actual type. If you implement your own Filler, so most probably +// you'll need this. See BarStyle or SpinnerStyle for example. +func MakeFillerTypeSpecificBarOption( + typeChecker func(Filler) (interface{}, bool), + cb func(interface{}), +) BarOption { return func(s *bState) { - s.runes = strToBarRunes(format) + if t, ok := typeChecker(s.filler); ok { + cb(t) + } } } + +// OptionOnCondition returns option when condition evaluates to true. +func OptionOnCondition(option BarOption, condition func() bool) BarOption { + if condition() { + return option + } + return nil +} diff --git a/vendor/github.com/vbauerster/mpb/cwriter/writer.go b/vendor/github.com/vbauerster/mpb/cwriter/writer.go index 0b1470d4c..638237c18 100644 --- a/vendor/github.com/vbauerster/mpb/cwriter/writer.go +++ b/vendor/github.com/vbauerster/mpb/cwriter/writer.go @@ -22,8 +22,8 @@ var ( clearCursorAndLine = cursorUp + clearLine ) -// Writer is a buffered the writer that updates the terminal. -// The contents of writer will be flushed when Flush is called. +// Writer is a buffered the writer that updates the terminal. The +// contents of writer will be flushed when Flush is called. type Writer struct { out io.Writer buf bytes.Buffer @@ -64,11 +64,13 @@ func (w *Writer) WriteString(s string) (n int, err error) { return w.buf.WriteString(s) } -// ReadFrom reads from the provided io.Reader and writes to the underlying buffer. +// ReadFrom reads from the provided io.Reader and writes to the +// underlying buffer. func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) { return w.buf.ReadFrom(r) } +// GetWidth returns width of underlying terminal. func (w *Writer) GetWidth() (int, error) { if w.isTerminal { tw, _, err := terminal.GetSize(w.fd) diff --git a/vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go b/vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go index dad7f50b2..747a63484 100644 --- a/vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go +++ b/vendor/github.com/vbauerster/mpb/cwriter/writer_windows.go @@ -8,7 +8,7 @@ import ( "syscall" "unsafe" - "github.com/mattn/go-isatty" + isatty "github.com/mattn/go-isatty" ) var kernel32 = syscall.NewLazyDLL("kernel32.dll") diff --git a/vendor/github.com/vbauerster/mpb/decor/counters.go b/vendor/github.com/vbauerster/mpb/decor/counters.go index e4161dc4b..7d581eefb 100644 --- a/vendor/github.com/vbauerster/mpb/decor/counters.go +++ b/vendor/github.com/vbauerster/mpb/decor/counters.go @@ -141,12 +141,14 @@ func CountersNoUnit(pairFormat string, wcc ...WC) Decorator { return Counters(0, pairFormat, wcc...) } -// CountersKibiByte is a wrapper around Counters with predefined unit UnitKiB (bytes/1024). +// CountersKibiByte is a wrapper around Counters with predefined unit +// UnitKiB (bytes/1024). func CountersKibiByte(pairFormat string, wcc ...WC) Decorator { return Counters(UnitKiB, pairFormat, wcc...) } -// CountersKiloByte is a wrapper around Counters with predefined unit UnitKB (bytes/1000). +// CountersKiloByte is a wrapper around Counters with predefined unit +// UnitKB (bytes/1000). func CountersKiloByte(pairFormat string, wcc ...WC) Decorator { return Counters(UnitKB, pairFormat, wcc...) } diff --git a/vendor/github.com/vbauerster/mpb/decor/decorator.go b/vendor/github.com/vbauerster/mpb/decor/decorator.go index 6aaf6c830..2fe40aea6 100644 --- a/vendor/github.com/vbauerster/mpb/decor/decorator.go +++ b/vendor/github.com/vbauerster/mpb/decor/decorator.go @@ -31,8 +31,12 @@ const ( DSyncSpaceR = DSyncWidth | DextraSpace | DidentRight ) +// TimeStyle enum. +type TimeStyle int + +// TimeStyle kinds. const ( - ET_STYLE_GO = iota + ET_STYLE_GO TimeStyle = iota ET_STYLE_HHMMSS ET_STYLE_HHMM ET_STYLE_MMSS @@ -47,35 +51,37 @@ type Statistics struct { } // Decorator interface. -// A decorator must implement this interface, in order to be used with mpb library. +// A decorator must implement this interface, in order to be used with +// mpb library. type Decorator interface { Decor(*Statistics) string Syncable } // Syncable interface. -// All decorators implement this interface implicitly. -// Its Syncable method exposes width sync channel, if sync is enabled. +// All decorators implement this interface implicitly. Its Syncable +// method exposes width sync channel, if sync is enabled. type Syncable interface { Syncable() (bool, chan int) } // OnCompleteMessenger interface. -// Decorators implementing this interface suppose to return provided string on complete event. +// Decorators implementing this interface suppose to return provided +// string on complete event. type OnCompleteMessenger interface { OnCompleteMessage(string) } // AmountReceiver interface. -// If decorator needs to receive increment amount, -// so this is the right interface to implement. +// If decorator needs to receive increment amount, so this is the right +// interface to implement. type AmountReceiver interface { NextAmount(int, ...time.Duration) } // ShutdownListener interface. -// If decorator needs to be notified once upon bar shutdown event, -// so this is the right interface to implement. +// If decorator needs to be notified once upon bar shutdown event, so +// this is the right interface to implement. type ShutdownListener interface { Shutdown() } @@ -90,6 +96,7 @@ var ( // WC is a struct with two public fields W and C, both of int type. // W represents width and C represents bit set of width related config. +// A decorator should embed WC, in order to become Syncable. type WC struct { W int C int @@ -126,12 +133,13 @@ func (wc *WC) Init() { } } +// Syncable is implementation of Syncable interface. func (wc *WC) Syncable() (bool, chan int) { return (wc.C & DSyncWidth) != 0, wc.wsync } -// OnComplete returns decorator, which wraps provided decorator, with sole -// purpose to display provided message on complete event. +// OnComplete returns decorator, which wraps provided decorator, with +// sole purpose to display provided message on complete event. // // `decorator` Decorator to wrap // diff --git a/vendor/github.com/vbauerster/mpb/decor/elapsed.go b/vendor/github.com/vbauerster/mpb/decor/elapsed.go index 649d40a30..b2e75852c 100644 --- a/vendor/github.com/vbauerster/mpb/decor/elapsed.go +++ b/vendor/github.com/vbauerster/mpb/decor/elapsed.go @@ -10,7 +10,7 @@ import ( // `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS] // // `wcc` optional WC config -func Elapsed(style int, wcc ...WC) Decorator { +func Elapsed(style TimeStyle, wcc ...WC) Decorator { var wc WC for _, widthConf := range wcc { wc = widthConf @@ -26,7 +26,7 @@ func Elapsed(style int, wcc ...WC) Decorator { type elapsedDecorator struct { WC - style int + style TimeStyle startTime time.Time msg string completeMsg *string diff --git a/vendor/github.com/vbauerster/mpb/decor/eta.go b/vendor/github.com/vbauerster/mpb/decor/eta.go index 44a1f03ea..e8dc979b4 100644 --- a/vendor/github.com/vbauerster/mpb/decor/eta.go +++ b/vendor/github.com/vbauerster/mpb/decor/eta.go @@ -6,7 +6,6 @@ import ( "time" "github.com/VividCortex/ewma" - "github.com/vbauerster/mpb/internal" ) type TimeNormalizer func(time.Duration) time.Duration @@ -18,7 +17,7 @@ type TimeNormalizer func(time.Duration) time.Duration // `age` is the previous N samples to average over. // // `wcc` optional WC config -func EwmaETA(style int, age float64, wcc ...WC) Decorator { +func EwmaETA(style TimeStyle, age float64, wcc ...WC) Decorator { return MovingAverageETA(style, ewma.NewMovingAverage(age), NopNormalizer(), wcc...) } @@ -31,7 +30,7 @@ func EwmaETA(style int, age float64, wcc ...WC) Decorator { // `normalizer` available implementations are [NopNormalizer|FixedIntervalTimeNormalizer|MaxTolerateTimeNormalizer] // // `wcc` optional WC config -func MovingAverageETA(style int, average MovingAverage, normalizer TimeNormalizer, wcc ...WC) Decorator { +func MovingAverageETA(style TimeStyle, average MovingAverage, normalizer TimeNormalizer, wcc ...WC) Decorator { var wc WC for _, widthConf := range wcc { wc = widthConf @@ -48,7 +47,7 @@ func MovingAverageETA(style int, average MovingAverage, normalizer TimeNormalize type movingAverageETA struct { WC - style int + style TimeStyle average ewma.MovingAverage completeMsg *string normalizer TimeNormalizer @@ -59,7 +58,7 @@ func (d *movingAverageETA) Decor(st *Statistics) string { return d.FormatMsg(*d.completeMsg) } - v := internal.Round(d.average.Value()) + v := math.Round(d.average.Value()) remaining := d.normalizer(time.Duration((st.Total - st.Current) * int64(v))) hours := int64((remaining / time.Hour) % 60) minutes := int64((remaining / time.Minute) % 60) @@ -105,7 +104,7 @@ func (d *movingAverageETA) OnCompleteMessage(msg string) { // `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS] // // `wcc` optional WC config -func AverageETA(style int, wcc ...WC) Decorator { +func AverageETA(style TimeStyle, wcc ...WC) Decorator { var wc WC for _, widthConf := range wcc { wc = widthConf @@ -121,7 +120,7 @@ func AverageETA(style int, wcc ...WC) Decorator { type averageETA struct { WC - style int + style TimeStyle startTime time.Time completeMsg *string } @@ -133,7 +132,7 @@ func (d *averageETA) Decor(st *Statistics) string { var str string timeElapsed := time.Since(d.startTime) - v := internal.Round(float64(timeElapsed) / float64(st.Current)) + v := math.Round(float64(timeElapsed) / float64(st.Current)) if math.IsInf(v, 0) || math.IsNaN(v) { v = 0 } diff --git a/vendor/github.com/vbauerster/mpb/decor/moving-average.go b/vendor/github.com/vbauerster/mpb/decor/moving-average.go index f9596a27f..fcd268923 100644 --- a/vendor/github.com/vbauerster/mpb/decor/moving-average.go +++ b/vendor/github.com/vbauerster/mpb/decor/moving-average.go @@ -6,9 +6,9 @@ import ( "github.com/VividCortex/ewma" ) -// MovingAverage is the interface that computes a moving average over a time- -// series stream of numbers. The average may be over a window or exponentially -// decaying. +// MovingAverage is the interface that computes a moving average over +// a time-series stream of numbers. The average may be over a window +// or exponentially decaying. type MovingAverage interface { Add(float64) Value() float64 @@ -57,7 +57,8 @@ func (s *medianEwma) Add(v float64) { s.count++ } -// NewMedianEwma is ewma based MovingAverage, which gets its values from median MovingAverage. +// NewMedianEwma is ewma based MovingAverage, which gets its values +// from median MovingAverage. func NewMedianEwma(age ...float64) MovingAverage { return &medianEwma{ MovingAverage: ewma.NewMovingAverage(age...), diff --git a/vendor/github.com/vbauerster/mpb/decor/speed.go b/vendor/github.com/vbauerster/mpb/decor/speed.go index 395e5d04d..74658ce41 100644 --- a/vendor/github.com/vbauerster/mpb/decor/speed.go +++ b/vendor/github.com/vbauerster/mpb/decor/speed.go @@ -137,7 +137,8 @@ func EwmaSpeed(unit int, unitFormat string, age float64, wcc ...WC) Decorator { return MovingAverageSpeed(unit, unitFormat, ewma.NewMovingAverage(age), wcc...) } -// MovingAverageSpeed decorator relies on MovingAverage implementation to calculate its average. +// MovingAverageSpeed decorator relies on MovingAverage implementation +// to calculate its average. // // `unit` one of [0|UnitKiB|UnitKB] zero for no unit // diff --git a/vendor/github.com/vbauerster/mpb/internal/percentage.go b/vendor/github.com/vbauerster/mpb/internal/percentage.go index 3c8defb7d..0483d2598 100644 --- a/vendor/github.com/vbauerster/mpb/internal/percentage.go +++ b/vendor/github.com/vbauerster/mpb/internal/percentage.go @@ -1,10 +1,12 @@ package internal +import "math" + // Percentage is a helper function, to calculate percentage. func Percentage(total, current, width int64) int64 { if total <= 0 { return 0 } p := float64(width*current) / float64(total) - return int64(Round(p)) + return int64(math.Round(p)) } diff --git a/vendor/github.com/vbauerster/mpb/internal/round.go b/vendor/github.com/vbauerster/mpb/internal/round.go deleted file mode 100644 index c54a789d2..000000000 --- a/vendor/github.com/vbauerster/mpb/internal/round.go +++ /dev/null @@ -1,49 +0,0 @@ -package internal - -import "math" - -const ( - uvone = 0x3FF0000000000000 - mask = 0x7FF - shift = 64 - 11 - 1 - bias = 1023 - signMask = 1 << 63 - fracMask = 1<= 0.5 { - // return t + Copysign(1, x) - // } - // return t - // } - bits := math.Float64bits(x) - e := uint(bits>>shift) & mask - if e < bias { - // Round abs(x) < 1 including denormals. - bits &= signMask // +-0 - if e == bias-1 { - bits |= uvone // +-1 - } - } else if e < bias+shift { - // Round any abs(x) >= 1 containing a fractional component [0,1). - // - // Numbers with larger exponents are returned unchanged since they - // must be either an integer, infinity, or NaN. - const half = 1 << (shift - 1) - e -= bias - bits += half >> e - bits &^= fracMask >> e - } - return math.Float64frombits(bits) -} diff --git a/vendor/github.com/vbauerster/mpb/options.go b/vendor/github.com/vbauerster/mpb/options.go index 05d2ecf1f..44a6ee3f3 100644 --- a/vendor/github.com/vbauerster/mpb/options.go +++ b/vendor/github.com/vbauerster/mpb/options.go @@ -1,29 +1,30 @@ package mpb import ( + "context" "io" "sync" "time" - "unicode/utf8" "github.com/vbauerster/mpb/cwriter" ) -// ProgressOption is a function option which changes the default behavior of -// progress pool, if passed to mpb.New(...ProgressOption) +// ProgressOption is a function option which changes the default +// behavior of progress pool, if passed to mpb.New(...ProgressOption). type ProgressOption func(*pState) -// WithWaitGroup provides means to have a single joint point. -// If *sync.WaitGroup is provided, you can safely call just p.Wait() -// without calling Wait() on provided *sync.WaitGroup. -// Makes sense when there are more than one bar to render. +// WithWaitGroup provides means to have a single joint point. If +// *sync.WaitGroup is provided, you can safely call just p.Wait() +// without calling Wait() on provided *sync.WaitGroup. Makes sense +// when there are more than one bar to render. func WithWaitGroup(wg *sync.WaitGroup) ProgressOption { return func(s *pState) { s.uwg = wg } } -// WithWidth overrides default width 80 +// WithWidth sets container width. Default is 80. Bars inherit this +// width, as long as no BarWidth is applied. func WithWidth(w int) ProgressOption { return func(s *pState) { if w >= 0 { @@ -32,16 +33,7 @@ func WithWidth(w int) ProgressOption { } } -// WithFormat overrides default bar format "[=>-]" -func WithFormat(format string) ProgressOption { - return func(s *pState) { - if utf8.RuneCountInString(format) == formatLen { - s.format = format - } - } -} - -// WithRefreshRate overrides default 120ms refresh rate +// WithRefreshRate overrides default 120ms refresh rate. func WithRefreshRate(d time.Duration) ProgressOption { return func(s *pState) { if d < 10*time.Millisecond { @@ -59,22 +51,25 @@ func WithManualRefresh(ch <-chan time.Time) ProgressOption { } } -// WithCancel provide your cancel channel, -// which you plan to close at some point. -func WithCancel(ch <-chan struct{}) ProgressOption { +// WithContext provided context will be used for cancellation purposes. +func WithContext(ctx context.Context) ProgressOption { return func(s *pState) { - s.cancel = ch + if ctx == nil { + return + } + s.ctx = ctx } } -// WithShutdownNotifier provided chanel will be closed, after all bars have been rendered. +// WithShutdownNotifier provided chanel will be closed, after all bars +// have been rendered. func WithShutdownNotifier(ch chan struct{}) ProgressOption { return func(s *pState) { s.shutdownNotifier = ch } } -// WithOutput overrides default output os.Stdout +// WithOutput overrides default output os.Stdout. func WithOutput(w io.Writer) ProgressOption { return func(s *pState) { if w == nil { diff --git a/vendor/github.com/vbauerster/mpb/options_go1.7.go b/vendor/github.com/vbauerster/mpb/options_go1.7.go deleted file mode 100644 index ca9a5bad8..000000000 --- a/vendor/github.com/vbauerster/mpb/options_go1.7.go +++ /dev/null @@ -1,15 +0,0 @@ -//+build go1.7 - -package mpb - -import "context" - -// WithContext provided context will be used for cancellation purposes -func WithContext(ctx context.Context) ProgressOption { - return func(s *pState) { - if ctx == nil { - panic("ctx must not be nil") - } - s.cancel = ctx.Done() - } -} diff --git a/vendor/github.com/vbauerster/mpb/progress.go b/vendor/github.com/vbauerster/mpb/progress.go index d95fe45b7..f9e25af79 100644 --- a/vendor/github.com/vbauerster/mpb/progress.go +++ b/vendor/github.com/vbauerster/mpb/progress.go @@ -2,6 +2,7 @@ package mpb import ( "container/heap" + "context" "fmt" "io" "io/ioutil" @@ -17,8 +18,6 @@ const ( prr = 120 * time.Millisecond // default width pwidth = 80 - // default format - pformat = "[=>-]" ) // Progress represents the container that renders Progress bars @@ -42,24 +41,24 @@ type pState struct { pMatrix map[int][]chan int aMatrix map[int][]chan int - // following are provided by user + // following are provided/overrided by user + ctx context.Context uwg *sync.WaitGroup manualRefreshCh <-chan time.Time - cancel <-chan struct{} shutdownNotifier chan struct{} waitBars map[*Bar]*Bar debugOut io.Writer } -// New creates new Progress instance, which orchestrates bars rendering process. -// Accepts mpb.ProgressOption funcs for customization. +// New creates new Progress instance, which orchestrates bars rendering +// process. Accepts mpb.ProgressOption funcs for customization. func New(options ...ProgressOption) *Progress { pq := make(priorityQueue, 0) heap.Init(&pq) s := &pState{ + ctx: context.Background(), bHeap: &pq, width: pwidth, - format: pformat, cw: cwriter.New(os.Stdout), rr: prr, waitBars: make(map[*Bar]*Bar), @@ -84,12 +83,28 @@ func New(options ...ProgressOption) *Progress { // AddBar creates a new progress bar and adds to the container. func (p *Progress) AddBar(total int64, options ...BarOption) *Bar { + return p.Add(total, newDefaultBarFiller(), options...) +} + +// AddSpinner creates a new spinner bar and adds to the container. +func (p *Progress) AddSpinner(total int64, alignment SpinnerAlignment, options ...BarOption) *Bar { + filler := &spinnerFiller{ + frames: defaultSpinnerStyle, + alignment: alignment, + } + return p.Add(total, filler, options...) +} + +// Add creates a bar which renders itself by provided filler. +func (p *Progress) Add(total int64, filler Filler, options ...BarOption) *Bar { + if filler == nil { + filler = newDefaultBarFiller() + } p.wg.Add(1) result := make(chan *Bar) select { case p.operateState <- func(s *pState) { - options = append(options, barWidth(s.width), barFormat(s.format)) - b := newBar(p.wg, s.idCounter, total, s.cancel, options...) + b := newBar(s.ctx, p.wg, filler, s.idCounter, s.width, total, options...) if b.runningBar != nil { s.waitBars[b.runningBar] = b } else { @@ -106,10 +121,10 @@ func (p *Progress) AddBar(total int64, options ...BarOption) *Bar { } } -// Abort is only effective while bar progress is running, -// it means remove bar now without waiting for its completion. -// If bar is already completed, there is nothing to abort. -// If you need to remove bar after completion, use BarRemoveOnComplete BarOption. +// Abort is only effective while bar progress is running, it means +// remove bar now without waiting for its completion. If bar is already +// completed, there is nothing to abort. If you need to remove bar +// after completion, use BarRemoveOnComplete BarOption. func (p *Progress) Abort(b *Bar, remove bool) { select { case p.operateState <- func(s *pState) { @@ -145,9 +160,10 @@ func (p *Progress) BarCount() int { } } -// Wait first waits for user provided *sync.WaitGroup, if any, -// then waits far all bars to complete and finally shutdowns master goroutine. -// After this method has been called, there is no way to reuse *Progress instance. +// Wait first waits for user provided *sync.WaitGroup, if any, then +// waits far all bars to complete and finally shutdowns master goroutine. +// After this method has been called, there is no way to reuse *Progress +// instance. func (p *Progress) Wait() { if p.uwg != nil { p.uwg.Wait() @@ -205,8 +221,8 @@ func (s *pState) flush(lineCount int) error { defer func() { if frameReader.toShutdown { // shutdown at next flush, in other words decrement underlying WaitGroup - // only after the bar with completed state has been flushed. - // this ensures no bar ends up with less than 100% rendered. + // only after the bar with completed state has been flushed. this + // ensures no bar ends up with less than 100% rendered. s.shutdownPending = append(s.shutdownPending, bar) if replacementBar, ok := s.waitBars[bar]; ok { heap.Push(s.bHeap, replacementBar) diff --git a/vendor/github.com/vbauerster/mpb/spinner_filler.go b/vendor/github.com/vbauerster/mpb/spinner_filler.go new file mode 100644 index 000000000..36299fef0 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/spinner_filler.go @@ -0,0 +1,48 @@ +package mpb + +import ( + "io" + "strings" + "unicode/utf8" + + "github.com/vbauerster/mpb/decor" +) + +// SpinnerAlignment enum. +type SpinnerAlignment int + +// SpinnerAlignment kinds. +const ( + SpinnerOnLeft SpinnerAlignment = iota + SpinnerOnMiddle + SpinnerOnRight +) + +var defaultSpinnerStyle = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"} + +type spinnerFiller struct { + frames []string + count uint + alignment SpinnerAlignment +} + +func (s *spinnerFiller) Fill(w io.Writer, width int, stat *decor.Statistics) { + + frame := s.frames[s.count%uint(len(s.frames))] + frameWidth := utf8.RuneCountInString(frame) + + if width < frameWidth { + return + } + + switch rest := width - frameWidth; s.alignment { + case SpinnerOnLeft: + io.WriteString(w, frame+strings.Repeat(" ", rest)) + case SpinnerOnMiddle: + str := strings.Repeat(" ", rest/2) + frame + strings.Repeat(" ", rest/2+rest%2) + io.WriteString(w, str) + case SpinnerOnRight: + io.WriteString(w, strings.Repeat(" ", rest)+frame) + } + s.count++ +} diff --git a/vendor/modules.txt b/vendor/modules.txt index f8fe344c6..977dbc0b1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -38,7 +38,7 @@ github.com/containernetworking/cni/pkg/invoke github.com/containernetworking/cni/pkg/types github.com/containernetworking/cni/pkg/types/020 github.com/containernetworking/cni/pkg/types/current -# github.com/containers/image v2.0.0+incompatible +# github.com/containers/image v2.0.1+incompatible github.com/containers/image/copy github.com/containers/image/directory github.com/containers/image/docker @@ -318,7 +318,7 @@ github.com/ulikunitz/xz/internal/hash github.com/vbatts/tar-split/tar/asm github.com/vbatts/tar-split/tar/storage github.com/vbatts/tar-split/archive/tar -# github.com/vbauerster/mpb v3.3.4+incompatible +# github.com/vbauerster/mpb v3.4.0+incompatible github.com/vbauerster/mpb github.com/vbauerster/mpb/decor github.com/vbauerster/mpb/cwriter