aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml15
-rw-r--r--Makefile9
-rw-r--r--cmd/podman/build.go4
-rw-r--r--cmd/podman/common.go78
-rw-r--r--cmd/podman/create.go1
-rw-r--r--cmd/podman/pod_create.go12
-rw-r--r--cmd/podman/ps.go4
-rw-r--r--cmd/podman/run.go1
-rw-r--r--contrib/msi/podman.wxs2
-rw-r--r--docs/links-to-html.lua1
-rw-r--r--docs/source/markdown/podman-ps.1.md1
-rw-r--r--go.mod9
-rw-r--r--go.sum21
-rw-r--r--libpod/container.go2
-rw-r--r--libpod/container_internal.go6
-rw-r--r--libpod/image/image.go5
-rw-r--r--libpod/image/pull.go1
-rw-r--r--pkg/api/handlers/exec.go25
-rw-r--r--pkg/api/handlers/generic/images.go45
-rw-r--r--pkg/api/handlers/generic/ping.go27
-rw-r--r--pkg/api/handlers/libpod/images.go52
-rw-r--r--pkg/api/handlers/ping.go30
-rw-r--r--pkg/api/handlers/swagger.go21
-rw-r--r--pkg/api/handlers/types.go19
-rw-r--r--pkg/api/server/register_exec.go329
-rw-r--r--pkg/api/server/register_images.go98
-rw-r--r--pkg/api/server/register_ping.go60
-rw-r--r--pkg/api/server/server.go1
-rw-r--r--pkg/api/server/swagger.go9
-rw-r--r--pkg/api/tags.yaml8
-rw-r--r--pkg/bindings/errors.go3
-rw-r--r--pkg/bindings/test/images_test.go35
-rw-r--r--pkg/specgen/specgen.go399
-rw-r--r--test/e2e/build_test.go37
-rw-r--r--test/e2e/ps_test.go16
-rw-r--r--vendor/github.com/acarl005/stripansi/LICENSE21
-rw-r--r--vendor/github.com/acarl005/stripansi/README.md30
-rw-r--r--vendor/github.com/acarl005/stripansi/stripansi.go13
-rw-r--r--vendor/github.com/containers/image/v5/copy/copy.go4
-rw-r--r--vendor/github.com/containers/image/v5/directory/directory_dest.go21
-rw-r--r--vendor/github.com/containers/image/v5/docker/docker_client.go124
-rw-r--r--vendor/github.com/containers/image/v5/docker/docker_image.go2
-rw-r--r--vendor/github.com/containers/image/v5/docker/docker_image_dest.go11
-rw-r--r--vendor/github.com/containers/image/v5/docker/docker_image_src.go99
-rw-r--r--vendor/github.com/containers/image/v5/docker/errors.go11
-rw-r--r--vendor/github.com/containers/image/v5/docker/tarfile/dest.go3
-rw-r--r--vendor/github.com/containers/image/v5/docker/tarfile/src.go9
-rw-r--r--vendor/github.com/containers/image/v5/image/docker_schema2.go4
-rw-r--r--vendor/github.com/containers/image/v5/image/oci.go4
-rw-r--r--vendor/github.com/containers/image/v5/internal/iolimits/iolimits.go60
-rw-r--r--vendor/github.com/containers/image/v5/openshift/openshift.go4
-rw-r--r--vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go4
-rw-r--r--vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go2
-rw-r--r--vendor/github.com/containers/image/v5/types/types.go2
-rw-r--r--vendor/github.com/containers/image/v5/version/version.go2
-rw-r--r--vendor/github.com/containers/storage/.golangci.yml66
-rw-r--r--vendor/github.com/containers/storage/VERSION2
-rw-r--r--vendor/github.com/containers/storage/drivers/aufs/aufs.go2
-rw-r--r--vendor/github.com/containers/storage/drivers/btrfs/btrfs.go2
-rw-r--r--vendor/github.com/containers/storage/drivers/chown_unix.go6
-rw-r--r--vendor/github.com/containers/storage/drivers/devmapper/deviceset.go43
-rw-r--r--vendor/github.com/containers/storage/drivers/devmapper/driver.go2
-rw-r--r--vendor/github.com/containers/storage/drivers/driver.go4
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/overlay.go15
-rw-r--r--vendor/github.com/containers/storage/drivers/overlayutils/overlayutils.go2
-rw-r--r--vendor/github.com/containers/storage/drivers/vfs/driver.go2
-rw-r--r--vendor/github.com/containers/storage/drivers/zfs/zfs.go2
-rw-r--r--vendor/github.com/containers/storage/drivers/zfs/zfs_linux.go2
-rw-r--r--vendor/github.com/containers/storage/go.mod8
-rw-r--r--vendor/github.com/containers/storage/go.sum8
-rw-r--r--vendor/github.com/containers/storage/images.go22
-rw-r--r--vendor/github.com/containers/storage/layers.go47
-rw-r--r--vendor/github.com/containers/storage/layers_ffjson.go2156
-rw-r--r--vendor/github.com/containers/storage/pkg/archive/archive.go18
-rw-r--r--vendor/github.com/containers/storage/pkg/archive/changes_unix.go10
-rw-r--r--vendor/github.com/containers/storage/pkg/archive/diff.go2
-rw-r--r--vendor/github.com/containers/storage/pkg/fileutils/fileutils.go13
-rw-r--r--vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go10
-rw-r--r--vendor/github.com/containers/storage/pkg/mount/flags_linux.go2
-rw-r--r--vendor/github.com/containers/storage/pkg/mount/mounter_linux.go4
-rw-r--r--vendor/github.com/containers/storage/store.go10
-rw-r--r--vendor/github.com/containers/storage/utils.go32
-rw-r--r--vendor/github.com/klauspost/compress/flate/deflate.go6
-rw-r--r--vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go52
-rw-r--r--vendor/github.com/klauspost/compress/flate/huffman_code.go76
-rw-r--r--vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go178
-rw-r--r--vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go201
-rw-r--r--vendor/github.com/klauspost/compress/flate/token.go42
-rw-r--r--vendor/github.com/mattn/go-shellwords/go.mod2
-rw-r--r--vendor/github.com/mattn/go-shellwords/shellwords.go28
-rw-r--r--vendor/github.com/mtrmac/gpgme/.appveyor.yml40
-rw-r--r--vendor/github.com/mtrmac/gpgme/.travis.yml32
-rw-r--r--vendor/github.com/mtrmac/gpgme/data.go18
-rw-r--r--vendor/github.com/mtrmac/gpgme/go.mod3
-rw-r--r--vendor/github.com/mtrmac/gpgme/go_gpgme.c22
-rw-r--r--vendor/github.com/mtrmac/gpgme/go_gpgme.h12
-rw-r--r--vendor/github.com/mtrmac/gpgme/gpgme.go346
-rw-r--r--vendor/github.com/mtrmac/gpgme/unset_agent_info.go18
-rw-r--r--vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go14
-rw-r--r--vendor/github.com/onsi/ginkgo/.travis.yml18
-rw-r--r--vendor/github.com/onsi/ginkgo/CHANGELOG.md5
-rw-r--r--vendor/github.com/onsi/ginkgo/config/config.go2
-rw-r--r--vendor/github.com/onsi/ginkgo/go.mod9
-rw-r--r--vendor/github.com/onsi/ginkgo/go.sum26
-rw-r--r--vendor/github.com/onsi/gomega/CHANGELOG.md7
-rw-r--r--vendor/github.com/onsi/gomega/gomega_dsl.go2
-rw-r--r--vendor/github.com/onsi/gomega/matchers.go14
-rw-r--r--vendor/github.com/onsi/gomega/matchers/consist_of.go91
-rw-r--r--vendor/github.com/onsi/gomega/matchers/contain_elements_matcher.go44
-rw-r--r--vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph/bipartitegraph.go26
-rw-r--r--vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph/bipartitegraphmatching.go37
-rw-r--r--vendor/github.com/onsi/gomega/matchers/support/goraph/edge/edge.go8
-rw-r--r--vendor/github.com/onsi/gomega/matchers/support/goraph/node/node.go3
-rw-r--r--vendor/github.com/vbauerster/mpb/v4/bar_option.go7
-rw-r--r--vendor/github.com/vbauerster/mpb/v4/decor/decorator.go27
-rw-r--r--vendor/github.com/vbauerster/mpb/v4/decor/merge.go45
-rw-r--r--vendor/github.com/vbauerster/mpb/v4/go.mod1
-rw-r--r--vendor/github.com/vbauerster/mpb/v4/go.sum2
-rw-r--r--vendor/github.com/vbauerster/mpb/v4/proxyreader.go8
-rw-r--r--vendor/modules.txt19
120 files changed, 2927 insertions, 2872 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index bb2da0812..655fa3830 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -93,7 +93,6 @@ gating_task:
CIRRUS_WORKING_DIR: "/usr/src/libpod"
GOPATH: "/go"
GOSRC: "/go/src/github.com/containers/libpod"
- EPOCH_TEST_COMMIT: "${CIRRUS_BASE_SHA}"
# Runs within Cirrus's "community cluster"
container:
@@ -103,6 +102,16 @@ gating_task:
timeout_in: 20m
+ # Custom cloning is required to satisfy lint/validation needs
+ clone_script: |
+ git clone --recursive --branch=$DEST_BRANCH https://x-access-token:${CIRRUS_REPO_CLONE_TOKEN}@github.com/${CIRRUS_REPO_FULL_NAME}.git $CIRRUS_WORKING_DIR
+ git remote update origin
+ if [[ -n "$CIRRUS_PR" ]]; then # running for a PR
+ git fetch origin pull/$CIRRUS_PR/head:pull/$CIRRUS_PR
+ git checkout pull/$CIRRUS_PR
+ fi
+ git reset --hard $CIRRUS_CHANGE_IN_REPO
+
# Don't bother going further if something is down
networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
@@ -674,9 +683,7 @@ docs_task:
# Only run this for PRs on mention, and after merge
only_if: >-
- $CIRRUS_BRANCH == $DEST_BRANCH &&
- $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:IMG.*' &&
- $CIRRUS_CHANGE_MESSAGE =~ '.*CI:DOCS.*'
+ $CIRRUS_BRANCH != $DEST_BRANCH
depends_on:
- "gating"
diff --git a/Makefile b/Makefile
index f71f7d2b1..1e5aa4d77 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ export GOPROXY=https://proxy.golang.org
GO ?= go
DESTDIR ?=
-EPOCH_TEST_COMMIT ?= $(shell git merge-base HEAD $${DEST_BRANCH:-master})
+EPOCH_TEST_COMMIT ?= $(shell git merge-base $${DEST_BRANCH:-master} HEAD)
HEAD ?= HEAD
CHANGELOG_BASE ?= HEAD~
CHANGELOG_TARGET ?= HEAD
@@ -132,6 +132,9 @@ for cmd in sorted(cmds):
endef
export PRINT_HELP_PYSCRIPT
+# Dereference variable $(1), return value if non-empty, otherwise raise an error.
+err_if_empty = $(if $(strip $($(1))),$(strip $($(1))),$(error Required variable $(1) value is undefined, whitespace, or empty))
+
.PHONY: help
help:
@$(PYTHON) -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)
@@ -146,6 +149,7 @@ endif
.PHONY: lint
lint: golangci-lint
+ @echo "Linting vs commit '$(call err_if_empty,EPOCH_TEST_COMMIT)'"
ifeq ($(PRE_COMMIT),)
@echo "FATAL: pre-commit was not found, check https://pre-commit.com/ about installing it." >&2
@exit 2
@@ -531,6 +535,7 @@ uninstall:
.PHONY: .gitvalidation
.gitvalidation: .gopathok
+ @echo "Validating vs commit '$(call err_if_empty,EPOCH_TEST_COMMIT)'"
GIT_CHECK_EXCLUDE="./vendor:docs/make.bat" $(GOBIN)/git-validation -run DCO,short-subject,dangling-whitespace -range $(EPOCH_TEST_COMMIT)..$(HEAD)
.PHONY: install.tools
@@ -591,7 +596,7 @@ validate.completions: completions/bash/podman
if [ -x /bin/zsh ]; then /bin/zsh completions/zsh/_podman; fi
.PHONY: validate
-validate: lint gofmt .gitvalidation validate.completions man-page-check
+validate: gofmt lint .gitvalidation validate.completions man-page-check
.PHONY: build-all-new-commits
build-all-new-commits:
diff --git a/cmd/podman/build.go b/cmd/podman/build.go
index 885f2ac51..1fcb98a0e 100644
--- a/cmd/podman/build.go
+++ b/cmd/podman/build.go
@@ -234,10 +234,6 @@ func buildCmd(c *cliconfig.BuildValues) error {
return errors.Wrapf(err, "error determining path to file %q", containerfiles[i])
}
contextDir = filepath.Dir(absFile)
- containerfiles[i], err = filepath.Rel(contextDir, absFile)
- if err != nil {
- return errors.Wrapf(err, "error determining path to file %q", containerfiles[i])
- }
break
}
}
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 46feae90d..7610edbc0 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -16,6 +16,7 @@ import (
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
"github.com/spf13/cobra"
+ "github.com/spf13/pflag"
)
var (
@@ -116,14 +117,49 @@ func getDefaultNetwork() string {
return "bridge"
}
-func getCreateFlags(c *cliconfig.PodmanCommand) {
-
- createFlags := c.Flags()
-
- createFlags.StringSlice(
+func getNetFlags() *pflag.FlagSet {
+ netFlags := pflag.FlagSet{}
+ netFlags.StringSlice(
"add-host", []string{},
"Add a custom host-to-IP mapping (host:ip) (default [])",
)
+ netFlags.StringSlice(
+ "dns", []string{},
+ "Set custom DNS servers",
+ )
+ netFlags.StringSlice(
+ "dns-opt", []string{},
+ "Set custom DNS options",
+ )
+ netFlags.StringSlice(
+ "dns-search", []string{},
+ "Set custom DNS search domains",
+ )
+ netFlags.String(
+ "ip", "",
+ "Specify a static IPv4 address for the container",
+ )
+ netFlags.String(
+ "mac-address", "",
+ "Container MAC address (e.g. 92:d0:c6:0a:29:33)",
+ )
+ netFlags.String(
+ "network", getDefaultNetwork(),
+ "Connect a container to a network",
+ )
+ netFlags.StringSliceP(
+ "publish", "p", []string{},
+ "Publish a container's port, or a range of ports, to the host (default [])",
+ )
+ netFlags.Bool(
+ "no-hosts", false,
+ "Do not create /etc/hosts within the container, instead use the version from the image",
+ )
+ return &netFlags
+}
+
+func getCreateFlags(c *cliconfig.PodmanCommand) {
+ createFlags := c.Flags()
createFlags.StringSlice(
"annotation", []string{},
"Add annotations to container (key:value) (default [])",
@@ -236,18 +272,6 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
"device-write-iops", []string{},
"Limit write rate (IO per second) to a device (e.g. --device-write-iops=/dev/sda:1000)",
)
- createFlags.StringSlice(
- "dns", []string{},
- "Set custom DNS servers",
- )
- createFlags.StringSlice(
- "dns-opt", []string{},
- "Set custom DNS options",
- )
- createFlags.StringSlice(
- "dns-search", []string{},
- "Set custom DNS search domains",
- )
createFlags.String(
"entrypoint", "",
"Overwrite the default ENTRYPOINT of the image",
@@ -324,10 +348,6 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
"Keep STDIN open even if not attached",
)
createFlags.String(
- "ip", "",
- "Specify a static IPv4 address for the container",
- )
- createFlags.String(
"ipc", "",
"IPC namespace to use",
)
@@ -351,10 +371,6 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
"log-opt", []string{},
"Logging driver options (default [])",
)
- createFlags.String(
- "mac-address", "",
- "Container MAC address (e.g. 92:d0:c6:0a:29:33)",
- )
createFlags.StringP(
"memory", "m", "",
"Memory limit "+sizeWithUnitFormat,
@@ -375,14 +391,6 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
"name", "",
"Assign a name to the container",
)
- createFlags.String(
- "network", getDefaultNetwork(),
- "Connect a container to a network",
- )
- createFlags.Bool(
- "no-hosts", false,
- "Do not create /etc/hosts within the container, instead use the version from the image",
- )
createFlags.Bool(
"oom-kill-disable", false,
"Disable OOM Killer",
@@ -417,10 +425,6 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
"privileged", false,
"Give extended privileges to container",
)
- createFlags.StringSliceP(
- "publish", "p", []string{},
- "Publish a container's port, or a range of ports, to the host (default [])",
- )
createFlags.BoolP(
"publish-all", "P", false,
"Publish all exposed ports to random ports on the host interface",
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index 01cad9765..73d62bddb 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -41,6 +41,7 @@ func init() {
getCreateFlags(&createCommand.PodmanCommand)
flags := createCommand.Flags()
+ flags.AddFlagSet(getNetFlags())
flags.SetInterspersed(false)
flags.SetNormalizeFunc(aliasFlags)
}
diff --git a/cmd/podman/pod_create.go b/cmd/podman/pod_create.go
index ad3c00aa8..cee6476ea 100644
--- a/cmd/podman/pod_create.go
+++ b/cmd/podman/pod_create.go
@@ -44,6 +44,18 @@ func init() {
podCreateCommand.SetUsageTemplate(UsageTemplate())
flags := podCreateCommand.Flags()
flags.SetInterspersed(false)
+ // When we are ready to add the network options to the create commmand, we need to uncomment
+ // the following
+
+ //flags.AddFlagSet(getNetFlags())
+
+ // Once this is uncommented, then the publish option below needs to be removed because it
+ // conflicts with the publish in getNetFlags. Upon removal, the c.Publish will not work
+ // anymore and needs to be cleaned up. I suggest starting with removing the Publish attribute
+ // from PodCreateValues structure. Running make should then expose all areas that need to be
+ // addressed. To get the value of publish (and other flags in getNetFlags, use the syntax:
+ // c.<type>("<flag_name") or c.Bool("publish")
+ // Remember to do this safely by checking len, etc.
flags.StringVar(&podCreateCommand.CgroupParent, "cgroup-parent", "", "Set parent cgroup for the pod")
flags.BoolVar(&podCreateCommand.Infra, "infra", true, "Create an infra container associated with the pod to share namespaces with")
diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go
index d2c5e19e2..d93ccc24c 100644
--- a/cmd/podman/ps.go
+++ b/cmd/podman/ps.go
@@ -205,6 +205,10 @@ func checkFlagsPassed(c *cliconfig.PsValues) error {
if c.Last >= 0 && c.Latest {
return errors.Errorf("last and latest are mutually exclusive")
}
+ // Filter forces all
+ if len(c.Filter) > 0 {
+ c.All = true
+ }
// Quiet conflicts with size and namespace and is overridden by a Go
// template.
if c.Quiet {
diff --git a/cmd/podman/run.go b/cmd/podman/run.go
index caa594682..219f057c3 100644
--- a/cmd/podman/run.go
+++ b/cmd/podman/run.go
@@ -38,6 +38,7 @@ func init() {
flags.SetInterspersed(false)
flags.SetNormalizeFunc(aliasFlags)
flags.Bool("sig-proxy", true, "Proxy received signals to the process")
+ flags.AddFlagSet(getNetFlags())
getCreateFlags(&runCommand.PodmanCommand)
markFlagHiddenForRemoteClient("authfile", flags)
}
diff --git a/contrib/msi/podman.wxs b/contrib/msi/podman.wxs
index ec62a93c5..c2c2cea4f 100644
--- a/contrib/msi/podman.wxs
+++ b/contrib/msi/podman.wxs
@@ -33,7 +33,7 @@
</Directory>
<Property Id="setx" Value="setx.exe"/>
- <CustomAction Id="ChangePath" ExeCommand='PATH "%PATH%;[INSTALLDIR]"' Property="setx" Execute="deferred" Impersonate="yes" Return="check"/>
+ <CustomAction Id="ChangePath" ExeCommand="PATH &quot;%PATH%;[INSTALLDIR] &quot;" Property="setx" Execute="deferred" Impersonate="yes" Return="check"/>
<Feature Id="Complete" Level="1">
<ComponentRef Id="INSTALLDIR_Component"/>
diff --git a/docs/links-to-html.lua b/docs/links-to-html.lua
index 74072a9e4..816c43353 100644
--- a/docs/links-to-html.lua
+++ b/docs/links-to-html.lua
@@ -1,4 +1,3 @@
-# links-to-html.lua
function Link(el)
el.target = string.gsub(el.target, "%.1.md", ".html")
return el
diff --git a/docs/source/markdown/podman-ps.1.md b/docs/source/markdown/podman-ps.1.md
index 024b85ea5..23bf9f45d 100644
--- a/docs/source/markdown/podman-ps.1.md
+++ b/docs/source/markdown/podman-ps.1.md
@@ -96,6 +96,7 @@ Display namespace information
Filter what containers are shown in the output.
Multiple filters can be given with multiple uses of the --filter flag.
If multiple filters are given, only containers which match all of the given filters will be shown.
+Results will be drawn from all containers, regardless of whether --all was given.
Valid filters are listed below:
diff --git a/go.mod b/go.mod
index 09b983fd1..b4922217f 100644
--- a/go.mod
+++ b/go.mod
@@ -12,9 +12,9 @@ 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.7
+ github.com/containers/storage v1.15.8
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
github.com/cri-o/ocicni v0.1.1-0.20190920040751-deac903fd99b
@@ -45,9 +45,10 @@ require (
github.com/json-iterator/go v1.1.9
github.com/mrtazz/checkmake v0.0.0-20191009095831-03dd76b964dd // indirect
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618
+ github.com/mtrmac/gpgme v0.1.2 // indirect
github.com/olekukonko/tablewriter v0.0.4 // indirect
- github.com/onsi/ginkgo v1.11.0
- github.com/onsi/gomega v1.8.1
+ github.com/onsi/ginkgo v1.12.0
+ github.com/onsi/gomega v1.9.0
github.com/opencontainers/go-digest v1.0.0-rc1
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
github.com/opencontainers/runc v1.0.0-rc9
diff --git a/go.sum b/go.sum
index 206defc99..d3771671b 100644
--- a/go.sum
+++ b/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=
@@ -109,6 +113,8 @@ github.com/containers/storage v1.15.5 h1:dBZx9yRFHod9c8FVaXlVtRqr2cmlAhpl+9rt87c
github.com/containers/storage v1.15.5/go.mod h1:v0lq/3f+cXH3Y/HiDaFYRR0zilwDve7I4W7U5xQxvF8=
github.com/containers/storage v1.15.7 h1:ecPmv2y/qpxeSTHZ147jQLO6to8wDn8yUPtDCZlz0H4=
github.com/containers/storage v1.15.7/go.mod h1:gLZIp+/hP8nFn9tLS0uJlnk4h1tSoDu3oS2eFiaIqkE=
+github.com/containers/storage v1.15.8 h1:ef7OfUMTpyq0PIVAhV7qfufEI92gAldk25nItrip+6Q=
+github.com/containers/storage v1.15.8/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-iptables v0.4.2 h1:KH0EwId05JwWIfb96gWvkiT2cbuOu8ygqUaB+yPAwIg=
@@ -311,6 +317,8 @@ github.com/klauspost/compress v1.9.4 h1:xhvAeUPQ2drNUhKtrGdTGNvV9nNafHMUkRyLkzxJ
github.com/klauspost/compress v1.9.4/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.9.7 h1:hYW1gP94JUmAhBtJ+LNz5My+gBobDxPR1iVuKug26aA=
github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.9.8 h1:VMAMUUOh+gaxKTMk+zqbjsSjsIcUcL/LF4o63i82QyA=
+github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.1 h1:oIPZROsWuPHpOdMVWLuJZXwgjhrW8r1yEX8UqMyeNHM=
@@ -341,6 +349,8 @@ github.com/mattn/go-shellwords v1.0.6 h1:9Jok5pILi5S1MnDirGVTufYGtksUs/V2BWUP3Zk
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/mattn/go-shellwords v1.0.7 h1:KqhVjVZomx2puPACkj9vrGFqnp42Htvo9SEAWePHKOs=
github.com/mattn/go-shellwords v1.0.7/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
+github.com/mattn/go-shellwords v1.0.9 h1:eaB5JspOwiKKcHdqcjbfe5lA9cNn/4NRRtddXJCimqk=
+github.com/mattn/go-shellwords v1.0.9/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mistifyio/go-zfs v2.1.1+incompatible h1:gAMO1HM9xBRONLHHYnu5iFsOJUiJdNZo6oqSENd4eW8=
@@ -364,6 +374,10 @@ 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/mtrmac/gpgme v0.1.2 h1:dNOmvYmsrakgW7LcgiprD0yfRuQQe8/C8F6Z+zogO3s=
+github.com/mtrmac/gpgme v0.1.2/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=
@@ -380,6 +394,8 @@ github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
+github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -390,6 +406,8 @@ github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34=
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
+github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg=
+github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@@ -536,6 +554,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=
@@ -644,6 +664,7 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2 h1:/J2nHFg1MTqaRLFO7M+J78ASNsJoz3r0cvHBPQ77fsE=
golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/libpod/container.go b/libpod/container.go
index f29cebf20..5e5c8ab26 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -244,7 +244,7 @@ type ContainerConfig struct {
// UID/GID mappings used by the storage
IDMappings storage.IDMappingOptions `json:"idMappingsOptions,omitempty"`
- // Information on the image used for the root filesystem/
+ // Information on the image used for the root filesystem
RootfsImageID string `json:"rootfsImageID,omitempty"`
RootfsImageName string `json:"rootfsImageName,omitempty"`
// Rootfs to use for the container, this conflicts with RootfsImageID
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 0e883588c..78ec09f29 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -1254,6 +1254,12 @@ func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (err e
}
}
}
+ // Ensure we tear down the container network so it will be
+ // recreated - otherwise, behavior of restart differs from stop
+ // and start
+ if err := c.cleanupNetwork(); err != nil {
+ return err
+ }
}
defer func() {
if err != nil {
diff --git a/libpod/image/image.go b/libpod/image/image.go
index 355249b12..ba1080a71 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -709,11 +709,12 @@ func (i *Image) Size(ctx context.Context) (*uint64, error) {
}
i.image = localImage
}
- if sum, err := i.imageruntime.store.ImageSize(i.ID()); err == nil && sum >= 0 {
+ sum, err := i.imageruntime.store.ImageSize(i.ID())
+ if err == nil && sum >= 0 {
usum := uint64(sum)
return &usum, nil
}
- return nil, errors.Errorf("unable to determine size")
+ return nil, errors.Wrap(err, "unable to determine size")
}
// toImageRef returns an Image Reference type from an image
diff --git a/libpod/image/pull.go b/libpod/image/pull.go
index 76294ba06..fd359d593 100644
--- a/libpod/image/pull.go
+++ b/libpod/image/pull.go
@@ -126,6 +126,7 @@ func (ir *Runtime) pullGoalFromImageReference(ctx context.Context, srcRef types.
if err != nil {
return nil, err
}
+ defer tarSource.Close()
manifest, err := tarSource.LoadTarManifest()
if err != nil {
diff --git a/pkg/api/handlers/exec.go b/pkg/api/handlers/exec.go
new file mode 100644
index 000000000..8a7b2ae26
--- /dev/null
+++ b/pkg/api/handlers/exec.go
@@ -0,0 +1,25 @@
+package handlers
+
+import (
+ "net/http"
+
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/api/handlers/utils"
+)
+
+func CreateExec(w http.ResponseWriter, r *http.Request) {
+ utils.Error(w, "function not implemented", http.StatusInternalServerError, define.ErrNotImplemented)
+}
+
+func StartExec(w http.ResponseWriter, r *http.Request) {
+ utils.Error(w, "function not implemented", http.StatusInternalServerError, define.ErrNotImplemented)
+}
+
+func ResizeExec(w http.ResponseWriter, r *http.Request) {
+ utils.Error(w, "function not implemented", http.StatusInternalServerError, define.ErrNotImplemented)
+
+}
+
+func InspectExec(w http.ResponseWriter, r *http.Request) {
+ utils.Error(w, "function not implemented", http.StatusInternalServerError, define.ErrNotImplemented)
+}
diff --git a/pkg/api/handlers/generic/images.go b/pkg/api/handlers/generic/images.go
index 20dd84456..c65db7575 100644
--- a/pkg/api/handlers/generic/images.go
+++ b/pkg/api/handlers/generic/images.go
@@ -3,6 +3,7 @@ package generic
import (
"encoding/json"
"fmt"
+ "io"
"io/ioutil"
"net/http"
"os"
@@ -315,3 +316,47 @@ func GetImages(w http.ResponseWriter, r *http.Request) {
}
utils.WriteResponse(w, http.StatusOK, summaries)
}
+
+func LoadImages(w http.ResponseWriter, r *http.Request) {
+ // TODO this is basically wrong
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+
+ query := struct {
+ Changes map[string]string `json:"changes"`
+ Message string `json:"message"`
+ Quiet bool `json:"quiet"`
+ }{
+ // This is where you can override the golang default value for one of fields
+ }
+
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+
+ var (
+ err error
+ writer io.Writer
+ )
+ f, err := ioutil.TempFile("", "api_load.tar")
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to create tempfile"))
+ return
+ }
+ if err := handlers.SaveFromBody(f, r); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file"))
+ return
+ }
+ id, err := runtime.LoadImage(r.Context(), "", f.Name(), writer, "")
+ //id, err := runtime.Import(r.Context())
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to load image"))
+ return
+ }
+ utils.WriteResponse(w, http.StatusOK, struct {
+ Stream string `json:"stream"`
+ }{
+ Stream: fmt.Sprintf("Loaded image: %s\n", id),
+ })
+}
diff --git a/pkg/api/handlers/generic/ping.go b/pkg/api/handlers/generic/ping.go
deleted file mode 100644
index 00afd86bc..000000000
--- a/pkg/api/handlers/generic/ping.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package generic
-
-import (
- "fmt"
- "net/http"
-
- "github.com/containers/libpod/pkg/api/handlers"
-)
-
-func PingGET(w http.ResponseWriter, _ *http.Request) {
- setHeaders(w)
- fmt.Fprintln(w, "OK")
-}
-
-func PingHEAD(w http.ResponseWriter, _ *http.Request) {
- setHeaders(w)
- fmt.Fprintln(w, "")
-}
-
-func setHeaders(w http.ResponseWriter) {
- w.Header().Set("API-Version", handlers.DefaultApiVersion)
- w.Header().Set("BuildKit-Version", "")
- w.Header().Set("Docker-Experimental", "true")
- w.Header().Set("Cache-Control", "no-cache")
- w.Header().Set("Pragma", "no-cache")
- w.WriteHeader(http.StatusOK)
-}
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index 202ed5eaa..6c926c45b 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -2,7 +2,6 @@ package libpod
import (
"fmt"
- "io"
"io/ioutil"
"net/http"
"os"
@@ -176,46 +175,17 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, rdr)
}
-func ImportImage(w http.ResponseWriter, r *http.Request) {
- // TODO this is basically wrong
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
-
- query := struct {
- Changes map[string]string `json:"changes"`
- Message string `json:"message"`
- Quiet bool `json:"quiet"`
- }{
- // This is where you can override the golang default value for one of fields
- }
+func ImagesLoad(w http.ResponseWriter, r *http.Request) {
+ //TODO ...
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.New("/libpod/images/load is not yet implemented"))
+}
- if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
- return
- }
+func ImagesImport(w http.ResponseWriter, r *http.Request) {
+ //TODO ...
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.New("/libpod/images/import is not yet implemented"))
+}
- var (
- err error
- writer io.Writer
- )
- f, err := ioutil.TempFile("", "api_load.tar")
- if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to create tempfile"))
- return
- }
- if err := handlers.SaveFromBody(f, r); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file"))
- return
- }
- id, err := runtime.LoadImage(r.Context(), "", f.Name(), writer, "")
- //id, err := runtime.Import(r.Context())
- if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to load image"))
- return
- }
- utils.WriteResponse(w, http.StatusOK, struct {
- Stream string `json:"stream"`
- }{
- Stream: fmt.Sprintf("Loaded image: %s\n", id),
- })
+func ImagesPull(w http.ResponseWriter, r *http.Request) {
+ //TODO ...
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.New("/libpod/images/pull is not yet implemented"))
}
diff --git a/pkg/api/handlers/ping.go b/pkg/api/handlers/ping.go
new file mode 100644
index 000000000..d41da60f3
--- /dev/null
+++ b/pkg/api/handlers/ping.go
@@ -0,0 +1,30 @@
+package handlers
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/containers/buildah"
+)
+
+// Ping returns headers to client about the service
+//
+// This handler must always be the same for the compatibility and libpod URL trees!
+// Clients will use the Header availability to test which backend engine is in use.
+func Ping(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("API-Version", DefaultApiVersion)
+ w.Header().Set("BuildKit-Version", "")
+ w.Header().Set("Docker-Experimental", "true")
+ w.Header().Set("Cache-Control", "no-cache")
+ w.Header().Set("Pragma", "no-cache")
+
+ // API-Version and Libpod-API-Version may not always be equal
+ w.Header().Set("Libpod-API-Version", DefaultApiVersion)
+ w.Header().Set("Libpod-Buildha-Version", buildah.Version)
+ w.WriteHeader(http.StatusOK)
+
+ if r.Method == http.MethodGet {
+ fmt.Fprint(w, "OK")
+ }
+ fmt.Fprint(w, "\n")
+}
diff --git a/pkg/api/handlers/swagger.go b/pkg/api/handlers/swagger.go
index faae98798..bc75777aa 100644
--- a/pkg/api/handlers/swagger.go
+++ b/pkg/api/handlers/swagger.go
@@ -26,6 +26,27 @@ type swagImageInspect struct {
}
}
+// Load response
+// swagger:response DocsLibpodImagesLoadResponse
+type swagLibpodImagesLoadResponse struct {
+ // in:body
+ Body []LibpodImagesLoadReport
+}
+
+// Import response
+// swagger:response DocsLibpodImagesImportResponse
+type swagLibpodImagesImportResponse struct {
+ // in:body
+ Body LibpodImagesImportReport
+}
+
+// Pull response
+// swagger:response DocsLibpodImagesPullResponse
+type swagLibpodImagesPullResponse struct {
+ // in:body
+ Body LibpodImagesPullReport
+}
+
// Delete response
// swagger:response DocsImageDeleteResponse
type swagImageDeleteResponse struct {
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index 9c8562744..6169adb18 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -49,6 +49,21 @@ type LibpodContainersPruneReport struct {
PruneError string `json:"error"`
}
+type LibpodImagesLoadReport struct {
+ ID string `json:"id"`
+ RepoTags []string `json:"repoTags"`
+}
+
+type LibpodImagesImportReport struct {
+ ID string `json:"id"`
+ RepoTags []string `json:"repoTags"`
+}
+
+type LibpodImagesPullReport struct {
+ ID string `json:"id"`
+ RepoTags []string `json:"repoTags"`
+}
+
type Info struct {
docker.Info
BuildahVersion string
@@ -70,10 +85,6 @@ type ContainerStats struct {
docker.ContainerStats
}
-type Ping struct {
- docker.Ping
-}
-
type Version struct {
docker.Version
}
diff --git a/pkg/api/server/register_exec.go b/pkg/api/server/register_exec.go
new file mode 100644
index 000000000..dbf04dc19
--- /dev/null
+++ b/pkg/api/server/register_exec.go
@@ -0,0 +1,329 @@
+package server
+
+import (
+ "net/http"
+
+ "github.com/containers/libpod/pkg/api/handlers"
+ "github.com/gorilla/mux"
+)
+
+func (s *APIServer) registerExecHandlers(r *mux.Router) error {
+ // swagger:operation POST /containers/{name}/create compat createExec
+ // ---
+ // tags:
+ // - exec (compat)
+ // summary: Create an exec instance
+ // description: Run a command inside a running container.
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: name of container
+ // - in: body
+ // name: control
+ // description: Attributes for create
+ // schema:
+ // type: object
+ // properties:
+ // AttachStdin:
+ // type: boolean
+ // description: Attach to stdin of the exec command
+ // AttachStdout:
+ // type: boolean
+ // description: Attach to stdout of the exec command
+ // AttachStderr:
+ // type: boolean
+ // description: Attach to stderr of the exec command
+ // DetachKeys:
+ // type: string
+ // description: |
+ // "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _."
+ // Tty:
+ // type: boolean
+ // description: Allocate a pseudo-TTY
+ // Env:
+ // type: array
+ // description: A list of environment variables in the form ["VAR=value", ...]
+ // items:
+ // type: string
+ // Cmd:
+ // type: array
+ // description: Command to run, as a string or array of strings.
+ // items:
+ // type: string
+ // Privileged:
+ // type: boolean
+ // default: false
+ // description: Runs the exec process with extended privileges
+ // User:
+ // type: string
+ // description: |
+ // "The user, and optionally, group to run the exec process inside the container. Format is one of: user, user:group, uid, or uid:gid."
+ // WorkingDir:
+ // type: string
+ // description: The working directory for the exec process inside the container.
+ // produces:
+ // - application/json
+ // responses:
+ // 201:
+ // description: no error
+ // 404:
+ // $ref: "#/responses/NoSuchContainer"
+ // 409:
+ // description: container is paused
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.Handle(VersionedPath("/containers/{name}/create"), APIHandler(s.Context, handlers.CreateExec)).Methods(http.MethodPost)
+ // swagger:operation POST /exec/{id}/start compat startExec
+ // ---
+ // tags:
+ // - exec (compat)
+ // summary: Start an exec instance
+ // description: Starts a previously set up exec instance. If detach is true, this endpoint returns immediately after starting the command. Otherwise, it sets up an interactive session with the command.
+ // parameters:
+ // - in: path
+ // name: id
+ // type: string
+ // required: true
+ // description: Exec instance ID
+ // - in: body
+ // name: control
+ // description: Attributes for start
+ // schema:
+ // type: object
+ // properties:
+ // Detach:
+ // type: boolean
+ // description: Detach from the command
+ // Tty:
+ // type: boolean
+ // description: Allocate a pseudo-TTY
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // description: no error
+ // 404:
+ // $ref: "#/responses/NoSuchExecInstance"
+ // 409:
+ // description: container is stopped or paused
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.Handle(VersionedPath("/exec/{id}/start"), APIHandler(s.Context, handlers.StartExec)).Methods(http.MethodPost)
+ // swagger:operation POST /exec/{id}/resize compat resizeExec
+ // ---
+ // tags:
+ // - exec (compat)
+ // summary: Resize an exec instance
+ // description: |
+ // Resize the TTY session used by an exec instance. This endpoint only works if tty was specified as part of creating and starting the exec instance.
+ // parameters:
+ // - in: path
+ // name: id
+ // type: string
+ // required: true
+ // description: Exec instance ID
+ // - in: query
+ // name: h
+ // type: integer
+ // description: Height of the TTY session in characters
+ // - in: query
+ // name: w
+ // type: integer
+ // description: Width of the TTY session in characters
+ // produces:
+ // - application/json
+ // responses:
+ // 201:
+ // description: no error
+ // 404:
+ // $ref: "#/responses/NoSuchExecInstance"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.Handle(VersionedPath("/exec/{id}/resize"), APIHandler(s.Context, handlers.ResizeExec)).Methods(http.MethodPost)
+ // swagger:operation GET /exec/{id}/inspect compat inspectExec
+ // ---
+ // tags:
+ // - exec (compat)
+ // summary: Inspect an exec instance
+ // description: Return low-level information about an exec instance.
+ // parameters:
+ // - in: path
+ // name: id
+ // type: string
+ // required: true
+ // description: Exec instance ID
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // description: no error
+ // 404:
+ // $ref: "#/responses/NoSuchExecInstance"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.Handle(VersionedPath("/exec/{id}/json"), APIHandler(s.Context, handlers.InspectExec)).Methods(http.MethodGet)
+
+ /*
+ libpod api follows
+ */
+
+ // swagger:operation POST /libpod/containers/{name}/create libpod libpodCreateExec
+ // ---
+ // tags:
+ // - exec
+ // summary: Create an exec instance
+ // description: Run a command inside a running container.
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: name of container
+ // - in: body
+ // name: control
+ // description: Attributes for create
+ // schema:
+ // type: object
+ // properties:
+ // AttachStdin:
+ // type: boolean
+ // description: Attach to stdin of the exec command
+ // AttachStdout:
+ // type: boolean
+ // description: Attach to stdout of the exec command
+ // AttachStderr:
+ // type: boolean
+ // description: Attach to stderr of the exec command
+ // DetachKeys:
+ // type: string
+ // description: |
+ // "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _."
+ // Tty:
+ // type: boolean
+ // description: Allocate a pseudo-TTY
+ // Env:
+ // type: array
+ // description: A list of environment variables in the form ["VAR=value", ...]
+ // items:
+ // type: string
+ // Cmd:
+ // type: array
+ // description: Command to run, as a string or array of strings.
+ // items:
+ // type: string
+ // Privileged:
+ // type: boolean
+ // default: false
+ // description: Runs the exec process with extended privileges
+ // User:
+ // type: string
+ // description: |
+ // "The user, and optionally, group to run the exec process inside the container. Format is one of: user, user:group, uid, or uid:gid."
+ // WorkingDir:
+ // type: string
+ // description: The working directory for the exec process inside the container.
+ // produces:
+ // - application/json
+ // responses:
+ // 201:
+ // description: no error
+ // 404:
+ // $ref: "#/responses/NoSuchContainer"
+ // 409:
+ // description: container is paused
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.Handle(VersionedPath("/libpod/containers/{name}/create"), APIHandler(s.Context, handlers.CreateExec)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/exec/{id}/start libpod libpodStartExec
+ // ---
+ // tags:
+ // - exec
+ // summary: Start an exec instance
+ // description: Starts a previously set up exec instance. If detach is true, this endpoint returns immediately after starting the command. Otherwise, it sets up an interactive session with the command.
+ // parameters:
+ // - in: path
+ // name: id
+ // type: string
+ // required: true
+ // description: Exec instance ID
+ // - in: body
+ // name: control
+ // description: Attributes for start
+ // schema:
+ // type: object
+ // properties:
+ // Detach:
+ // type: boolean
+ // description: Detach from the command
+ // Tty:
+ // type: boolean
+ // description: Allocate a pseudo-TTY
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // description: no error
+ // 404:
+ // $ref: "#/responses/NoSuchExecInstance"
+ // 409:
+ // description: container is stopped or paused
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.Handle(VersionedPath("/libpod/exec/{id}/start"), APIHandler(s.Context, handlers.StartExec)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/exec/{id}/resize libpod libpodResizeExec
+ // ---
+ // tags:
+ // - exec
+ // summary: Resize an exec instance
+ // description: |
+ // Resize the TTY session used by an exec instance. This endpoint only works if tty was specified as part of creating and starting the exec instance.
+ // parameters:
+ // - in: path
+ // name: id
+ // type: string
+ // required: true
+ // description: Exec instance ID
+ // - in: query
+ // name: h
+ // type: integer
+ // description: Height of the TTY session in characters
+ // - in: query
+ // name: w
+ // type: integer
+ // description: Width of the TTY session in characters
+ // produces:
+ // - application/json
+ // responses:
+ // 201:
+ // description: no error
+ // 404:
+ // $ref: "#/responses/NoSuchExecInstance"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.Handle(VersionedPath("/libpod/exec/{id}/resize"), APIHandler(s.Context, handlers.ResizeExec)).Methods(http.MethodPost)
+ // swagger:operation GET /libpod/exec/{id}/inspect libpod libpodInspectExec
+ // ---
+ // tags:
+ // - exec
+ // summary: Inspect an exec instance
+ // description: Return low-level information about an exec instance.
+ // parameters:
+ // - in: path
+ // name: id
+ // type: string
+ // required: true
+ // description: Exec instance ID
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // description: no error
+ // 404:
+ // $ref: "#/responses/NoSuchExecInstance"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.Handle(VersionedPath("/libpod/exec/{id}/json"), APIHandler(s.Context, handlers.InspectExec)).Methods(http.MethodGet)
+ return nil
+}
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index f1cc0574c..4a46b6ee6 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -107,7 +107,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: no error
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/images/load"), APIHandler(s.Context, libpod.ImportImage)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/images/load"), APIHandler(s.Context, generic.LoadImages)).Methods(http.MethodPost)
// swagger:operation POST /images/prune compat pruneImages
// ---
// tags:
@@ -300,8 +300,9 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// swagger:operation POST /commit/ compat commitContainer
// ---
// tags:
- // - commit (compat)
- // summary: Create a new image from a container
+ // - containers (compat)
+ // summary: New Image
+ // description: Create a new image from a container
// parameters:
// - in: query
// name: container
@@ -630,39 +631,94 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// 500:
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/json"), APIHandler(s.Context, libpod.GetImages)).Methods(http.MethodGet)
- // swagger:operation POST /libpod/images/load libpod libpodImportImage
+ // swagger:operation POST /libpod/images/load libpod libpodImagesLoad
+ // ---
+ // tags:
+ // - images
+ // summary: Load image
+ // description: Load an image (oci-archive or docker-archive) stream.
+ // parameters:
+ // - in: query
+ // name: change
+ // description: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string"
+ // type: string
+ // - in: query
+ // name: message
+ // description: Set commit message for imported image
+ // type: string
+ // - in: formData
+ // name: upload
+ // description: tarball of container image
+ // type: file
+ // required: true
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // $ref: "#/responses/DocsLibpodImagesLoadResponse"
+ // 500:
+ // $ref: '#/responses/InternalError'
+ r.Handle(VersionedPath("/libpod/images/load"), APIHandler(s.Context, libpod.ImagesLoad)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/images/import libpod libpodImagesImport
// ---
// tags:
// - images
// summary: Import image
- // description: Load a set of images and tags into a repository.
+ // description: Import a previously exported tarball as an image.
+ // parameters:
+ // - in: query
+ // name: change
+ // description: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string"
+ // type: string
+ // - in: query
+ // name: message
+ // description: Set commit message for imported image
+ // type: string
+ // - in: query
+ // name: url
+ // description: Specify a URL instead of a tarball
+ // type: boolean
+ // - in: formData
+ // name: upload
+ // type: file
+ // required: true
+ // description: tarball for imported image
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // $ref: "#/responses/DocsLibpodImagesImportResponse"
+ // 500:
+ // $ref: '#/responses/InternalError'
+ r.Handle(VersionedPath("/libpod/images/import"), APIHandler(s.Context, libpod.ImagesImport)).Methods(http.MethodPost)
+ // swagger:operation GET /libpod/images/pull libpod libpodImagesPull
+ // ---
+ // tags:
+ // - images
+ // summary: Import image
+ // description: Import a previosly exported image as a tarball.
// parameters:
// - in: query
- // name: quiet
- // type: boolean
- // description: not supported
- // - in: query
- // name: change
- // description: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string"
+ // name: reference
+ // description: Mandatory reference to the image (e.g., quay.io/image/name:tag)/
// type: string
// - in: query
- // name: message
- // description: Set commit message for imported image
+ // name: credentials
+ // description: username:password for the registry.
// type: string
- // - in: body
- // name: request
- // description: tarball of container image
- // required: true
- // schema:
- // type: string
+ // - in: query
+ // name: tls-verify
+ // description: Require TLS verification.
+ // type: boolean
+ // default: true
// produces:
// - application/json
// responses:
// 200:
- // description: no error
+ // $ref: "#/responses/DocsLibpodImagesPullResponse"
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/load"), APIHandler(s.Context, libpod.ImportImage)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/images/pull"), APIHandler(s.Context, libpod.ImagesPull)).Methods(http.MethodPost)
// swagger:operation POST /libpod/images/prune libpod libpodPruneImages
// ---
// tags:
diff --git a/pkg/api/server/register_ping.go b/pkg/api/server/register_ping.go
index 4956f9822..086e674a1 100644
--- a/pkg/api/server/register_ping.go
+++ b/pkg/api/server/register_ping.go
@@ -3,15 +3,65 @@ package server
import (
"net/http"
- "github.com/containers/libpod/pkg/api/handlers/generic"
+ "github.com/containers/libpod/pkg/api/handlers"
"github.com/gorilla/mux"
)
func (s *APIServer) registerPingHandlers(r *mux.Router) error {
- r.Handle("/_ping", APIHandler(s.Context, generic.PingGET)).Methods(http.MethodGet)
- r.Handle("/_ping", APIHandler(s.Context, generic.PingHEAD)).Methods("HEAD")
- // libpod
- r.Handle("/libpod/_ping", APIHandler(s.Context, generic.PingGET)).Methods(http.MethodGet)
+ r.Handle("/_ping", APIHandler(s.Context, handlers.Ping)).Methods(http.MethodGet)
+ r.Handle("/_ping", APIHandler(s.Context, handlers.Ping)).Methods(http.MethodHead)
+
+ // swagger:operation GET /libpod/_ping libpod libpodPingGet
+ // ---
+ // summary: Ping service
+ // description: |
+ // Return protocol information in response headers.
+ // `HEAD /libpod/_ping` is also supported.
+ // `/_ping` is available for compatibility with other engines.
+ // tags:
+ // - system (compat)
+ // - system
+ // produces:
+ // - text/plain
+ // responses:
+ // 200:
+ // description: Success
+ // schema:
+ // description: OK
+ // type: string
+ // example: "OK"
+ // headers:
+ // API-Version:
+ // type: string
+ // description: Max compatibility API Version the server supports
+ // BuildKit-Version:
+ // type: string
+ // description: Default version of docker image builder
+ // Docker-Experimental:
+ // type: boolean
+ // description: If the server is running with experimental mode enabled, always true
+ // Cache-Control:
+ // type: string
+ // description: always no-cache
+ // Pragma:
+ // type: string
+ // description: always no-cache
+ // Libpod-API-Version:
+ // type: string
+ // description: |
+ // Max Podman API Version the server supports.
+ // Available if service is backed by Podman, therefore may be used to
+ // determine if talking to Podman engine or another engine
+ // Libpod-Buildha-Version:
+ // type: string
+ // description: |
+ // Default version of libpod image builder.
+ // Available if service is backed by Podman, therefore may be used to
+ // determine if talking to Podman engine or another engine
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.Handle("/libpod/_ping", APIHandler(s.Context, handlers.Ping)).Methods(http.MethodGet)
+ r.Handle("/libpod/_ping", APIHandler(s.Context, handlers.Ping)).Methods(http.MethodHead)
return nil
}
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index d030961cb..7bb0f5481 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -105,6 +105,7 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
server.RegisterAuthHandlers,
server.RegisterContainersHandlers,
server.RegisterDistributionHandlers,
+ server.registerExecHandlers,
server.registerHealthCheckHandlers,
server.registerImagesHandlers,
server.registerInfoHandlers,
diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go
index 5098390bc..fc409d816 100644
--- a/pkg/api/server/swagger.go
+++ b/pkg/api/server/swagger.go
@@ -23,6 +23,15 @@ type swagErrNoSuchContainer struct {
}
}
+// No such exec instance
+// swagger:response NoSuchExecInstance
+type swagErrNoSuchExecInstance struct {
+ // in:body
+ Body struct {
+ utils.ErrorModel
+ }
+}
+
// No such volume
// swagger:response NoSuchVolume
type swagErrNoSuchVolume struct {
diff --git a/pkg/api/tags.yaml b/pkg/api/tags.yaml
index ad0de656f..3bf2bb64f 100644
--- a/pkg/api/tags.yaml
+++ b/pkg/api/tags.yaml
@@ -1,13 +1,21 @@
tags:
- name: containers
description: Actions related to containers
+ - name: exec
+ description: Actions related to exec
- name: images
description: Actions related to images
- name: pods
description: Actions related to pods
- name: volumes
description: Actions related to volumes
+ - name: system
+ description: Actions related to Podman engine
- name: containers (compat)
description: Actions related to containers for the compatibility endpoints
+ - name: exec (compat)
+ description: Actions related to exec for the compatibility endpoints
- name: images (compat)
description: Actions related to images for the compatibility endpoints
+ - name: system (compat)
+ description: Actions related to Podman and compatiblity engines
diff --git a/pkg/bindings/errors.go b/pkg/bindings/errors.go
index 8bd40f804..1bcaac3f0 100644
--- a/pkg/bindings/errors.go
+++ b/pkg/bindings/errors.go
@@ -3,7 +3,6 @@ package bindings
import (
"encoding/json"
"io/ioutil"
- "net/http"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/pkg/errors"
@@ -26,7 +25,7 @@ func (a APIResponse) Process(unmarshalInto interface{}) error {
if err != nil {
return errors.Wrap(err, "unable to process API response")
}
- if a.Response.StatusCode == http.StatusOK {
+ if a.IsSuccess() {
if unmarshalInto != nil {
return json.Unmarshal(data, unmarshalInto)
}
diff --git a/pkg/bindings/test/images_test.go b/pkg/bindings/test/images_test.go
index 227f28d16..f2dc856b2 100644
--- a/pkg/bindings/test/images_test.go
+++ b/pkg/bindings/test/images_test.go
@@ -89,4 +89,39 @@ var _ = Describe("Podman images", func() {
})
+ //Tests to validate the image tag command.
+ It("tag image", func() {
+ // Validates if invalid image name is given a bad response is encountered.
+ err = images.Tag(connText, "dummy", "demo", "alpine")
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", 404))
+
+ // Validates if the image is tagged sucessfully.
+ err = images.Tag(connText, "alpine", "demo", "alpine")
+ Expect(err).To(BeNil())
+
+ //Validates if name updates when the image is retagged.
+ _, err := images.GetImage(connText, "alpine:demo", nil)
+ Expect(err).To(BeNil())
+
+ })
+
+ //Test to validate the List images command.
+ It("List image", func() {
+ //Array to hold the list of images returned
+ imageSummary, err := images.List(connText, nil, nil)
+ //There Should be no errors in the response.
+ Expect(err).To(BeNil())
+ //Since in the begin context only one image is created the list context should have only one image
+ Expect(len(imageSummary)).To(Equal(1))
+
+ //To be written create a new image and check list count again
+ //imageSummary, err = images.List(connText, nil, nil)
+
+ //Since in the begin context only one image adding one more image should
+ ///Expect(len(imageSummary)).To(Equal(2)
+
+ })
+
})
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
new file mode 100644
index 000000000..e22ee598f
--- /dev/null
+++ b/pkg/specgen/specgen.go
@@ -0,0 +1,399 @@
+package specgen
+
+import (
+ "net"
+
+ "github.com/containers/image/v5/manifest"
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/storage"
+ "github.com/cri-o/ocicni/pkg/ocicni"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+)
+
+// TODO
+// mheon provided this an off the cuff suggestion. Adding it here to retain
+// for history as we implement it. When this struct is implemented, we need
+// to remove the nolints.
+type Namespace struct {
+ isHost bool //nolint
+ isPath string //nolint
+ isContainer string //nolint
+ isPod bool //nolint
+}
+
+// ContainerBasicConfig contains the basic parts of a container.
+type ContainerBasicConfig struct {
+ // Name is the name the container will be given.
+ // If no name is provided, one will be randomly generated.
+ // Optional.
+ Name string `json:"name,omitempty"`
+ // Pod is the ID of the pod the container will join.
+ // Optional.
+ Pod string `json:"pod,omitempty"`
+ // Entrypoint is the container's entrypoint.
+ // If not given and Image is specified, this will be populated by the
+ // image's configuration.
+ // Optional.
+ Entrypoint []string `json:"entrypoint,omitempty"`
+ // Command is the container's command.
+ // If not given and Image is specified, this will be populated by the
+ // image's configuration.
+ // Optional.
+ Command []string `json:"command,omitempty"`
+ // Env is a set of environment variables that will be set in the
+ // container.
+ // Optional.
+ Env map[string]string `json:"env,omitempty"`
+ // Terminal is whether the container will create a PTY.
+ Terminal bool `json:"terminal,omitempty"`
+ // Stdin is whether the container will keep its STDIN open.
+ Stdin bool `json:"stdin,omitempty"`
+ // Labels are key-valid labels that are used to add metadata to
+ // containers.
+ // Optional.
+ Labels map[string]string `json:"labels,omitempty"`
+ // Annotations are key-value options passed into the container runtime
+ // that can be used to trigger special behavior.
+ // Optional.
+ Annotations map[string]string `json:"annotations,omitempty"`
+ // StopSignal is the signal that will be used to stop the container.
+ // Must be a non-zero integer below SIGRTMAX.
+ // If not provided, the default, SIGTERM, will be used.
+ // Will conflict with Systemd if Systemd is set to "true" or "always".
+ // Optional.
+ StopSignal *uint `json:"stop_signal,omitempty"`
+ // StopTimeout is a timeout between the container's stop signal being
+ // sent and SIGKILL being sent.
+ // If not provided, the default will be used.
+ // If 0 is used, stop signal will not be sent, and SIGKILL will be sent
+ // instead.
+ // Optional.
+ StopTimeout *uint `json:"stop_timeout,omitempty"`
+ // LogDriver is the container's log driver.
+ // Optional.
+ LogDriver string `json:"log_driver,omitempty"`
+ // LogPath is the path the container's logs will be stored at.
+ // Only available if LogDriver is set to "json-file" or "k8s-file".
+ // Optional.
+ LogPath string `json:"log_path,omitempty"`
+ // ConmonPidFile is a path at which a PID file for Conmon will be
+ // placed.
+ // If not given, a default location will be used.
+ // Optional.
+ ConmonPidFile string `json:"conmon_pid_file,omitempty"`
+ // RestartPolicy is the container's restart policy - an action which
+ // will be taken when the container exits.
+ // If not given, the default policy, which does nothing, will be used.
+ // Optional.
+ RestartPolicy string `json:"restart_policy,omitempty"`
+ // RestartRetries is the number of attempts that will be made to restart
+ // the container.
+ // Only available when RestartPolicy is set to "on-failure".
+ // Optional.
+ RestartRetries *uint `json:"restart_tries,omitempty"`
+ // OCIRuntime is the name of the OCI runtime that will be used to create
+ // the container.
+ // If not specified, the default will be used.
+ // Optional.
+ OCIRuntime string `json:"oci_runtime,omitempty"`
+ // Systemd is whether the container will be started in systemd mode.
+ // Valid options are "true", "false", and "always".
+ // "true" enables this mode only if the binary run in the container is
+ // /sbin/init or systemd. "always" unconditionally enables systemd mode.
+ // "false" unconditionally disables systemd mode.
+ // If enabled, mounts and stop signal will be modified.
+ // If set to "always" or set to "true" and conditionally triggered,
+ // conflicts with StopSignal.
+ // If not specified, "false" will be assumed.
+ // Optional.
+ Systemd string `json:"systemd,omitempty"`
+ // Namespace is the libpod namespace the container will be placed in.
+ // Optional.
+ Namespace string `json:"namespace,omitempty"`
+
+ // PidNS is the container's PID namespace.
+ // It defaults to private.
+ // Mandatory.
+ PidNS Namespace `json:"pidns,omitempty"`
+
+ // UtsNS is the container's UTS namespace.
+ // It defaults to private.
+ // Must be set to Private to set Hostname.
+ // Mandatory.
+ UtsNS Namespace `json:"utsns,omitempty"`
+ // Hostname is the container's hostname. If not set, the hostname will
+ // not be modified (if UtsNS is not private) or will be set to the
+ // container ID (if UtsNS is private).
+ // Conflicts with UtsNS if UtsNS is not set to private.
+ // Optional.
+ Hostname string `json:"hostname,omitempty"`
+}
+
+// ContainerStorageConfig contains information on the storage configuration of a
+// container.
+type ContainerStorageConfig struct {
+ // Image is the image the container will be based on. The image will be
+ // used as the container's root filesystem, and its environment vars,
+ // volumes, and other configuration will be applied to the container.
+ // Conflicts with Rootfs.
+ // At least one of Image or Rootfs must be specified.
+ Image string `json:"image"`
+ // Rootfs is the path to a directory that will be used as the
+ // container's root filesystem. No modification will be made to the
+ // directory, it will be directly mounted into the container as root.
+ // Conflicts with Image.
+ // At least one of Image or Rootfs must be specified.
+ Rootfs string `json:"rootfs,omitempty"`
+ // ImageVolumeMode indicates how image volumes will be created.
+ // Supported modes are "ignore" (do not create), "tmpfs" (create as
+ // tmpfs), and "anonymous" (create as anonymous volumes).
+ // The default is anonymous.
+ // Optional.
+ ImageVolumeMode string `json:"image_volume_mode,omitempty"`
+ // VolumesFrom is a list of containers whose volumes will be added to
+ // this container. Supported mount options may be added after the
+ // container name with a : and include "ro" and "rw".
+ // Optional.
+ VolumesFrom []string `json:"volumes_from,omitempty"`
+ // Mounts are mounts that will be added to the container.
+ // These will supersede Image Volumes and VolumesFrom volumes where
+ // there are conflicts.
+ // Optional.
+ Mounts []spec.Mount `json:"mounts,omitempty"`
+ // Volumes are named volumes that will be added to the container.
+ // These will supersede Image Volumes and VolumesFrom volumes where
+ // there are conflicts.
+ // Optional.
+ Volumes []*libpod.ContainerNamedVolume `json:"volumes,omitempty"`
+ // Devices are devices that will be added to the container.
+ // Optional.
+ Devices []spec.LinuxDevice `json:"devices,omitempty"`
+ // IpcNS is the container's IPC namespace.
+ // Default is private.
+ // Conflicts with ShmSize if not set to private.
+ // Mandatory.
+ IpcNS Namespace `json:"ipcns,omitempty"`
+ // ShmSize is the size of the tmpfs to mount in at /dev/shm, in bytes.
+ // Conflicts with ShmSize if ShmSize is not private.
+ // Optional.
+ ShmSize *int64 `json:"shm_size,omitempty"`
+ // WorkDir is the container's working directory.
+ // If unset, the default, /, will be used.
+ // Optional.
+ WorkDir string `json:"work_dir,omitempty"`
+ // RootfsPropagation is the rootfs propagation mode for the container.
+ // If not set, the default of rslave will be used.
+ // Optional.
+ RootfsPropagation string `json:"rootfs_propagation,omitempty"`
+}
+
+// ContainerSecurityConfig is a container's security features, including
+// SELinux, Apparmor, and Seccomp.
+type ContainerSecurityConfig struct {
+ // Privileged is whether the container is privileged.
+ // Privileged does the following:
+ // - Adds all devices on the system to the container.
+ // - Adds all capabilities to the container.
+ // - Disables Seccomp, SELinux, and Apparmor confinement.
+ // TODO: this conflicts with things.
+ // TODO: this does more.
+ Privileged bool `json:"privileged,omitempty"`
+ // User is the user the container will be run as.
+ // Can be given as a UID or a username; if a username, it will be
+ // resolved within the container, using the container's /etc/passwd.
+ // If unset, the container will be run as root.
+ // Optional.
+ User string `json:"user,omitempty"`
+ // Groups are a list of supplemental groups the container's user will
+ // be granted access to.
+ // Optional.
+ Groups []string `json:"groups,omitempty"`
+ // CapAdd are capabilities which will be added to the container.
+ // Conflicts with Privileged.
+ // Optional.
+ CapAdd []string `json:"cap_add,omitempty"`
+ // CapDrop are capabilities which will be removed from the container.
+ // Conflicts with Privileged.
+ // Optional.
+ CapDrop []string `json:"cap_drop,omitempty"`
+ // SelinuxProcessLabel is the process label the container will use.
+ // If SELinux is enabled and this is not specified, a label will be
+ // automatically generated if not specified.
+ // Optional.
+ SelinuxProcessLabel string `json:"selinux_process_label,omitempty"`
+ // SelinuxMountLabel is the mount label the container will use.
+ // If SELinux is enabled and this is not specified, a label will be
+ // automatically generated if not specified.
+ // Optional.
+ SelinuxMountLabel string `json:"selinux_mount_label,omitempty"`
+ // SelinuxOpts are options for configuring SELinux.
+ // Optional.
+ SelinuxOpts []string `json:"selinux_opts,omitempty"`
+ // ApparmorProfile is the name of the Apparmor profile the container
+ // will use.
+ // Optional.
+ ApparmorProfile string `json:"apparmor_profile,omitempty"`
+ // SeccompProfilePath is the path to a JSON file containing the
+ // container's Seccomp profile.
+ // If not specified, no Seccomp profile will be used.
+ // Optional.
+ SeccompProfilePath string `json:"seccomp_profile_path,omitempty"`
+ // NoNewPrivileges is whether the container will set the no new
+ // privileges flag on create, which disables gaining additional
+ // privileges (e.g. via setuid) in the container.
+ NoNewPrivileges bool `json:"no_new_privileges,omitempty"`
+ // UserNS is the container's user namespace.
+ // It defaults to host, indicating that no user namespace will be
+ // created.
+ // If set to private, IDMappings must be set.
+ // Mandatory.
+ UserNS Namespace `json:"userns,omitempty"`
+ // IDMappings are UID and GID mappings that will be used by user
+ // namespaces.
+ // Required if UserNS is private.
+ IDMappings storage.IDMappingOptions `json:"idmappings,omitempty"`
+}
+
+// ContainerCgroupConfig contains configuration information about a container's
+// cgroups.
+type ContainerCgroupConfig struct {
+ // CgroupNS is the container's cgroup namespace.
+ // It defaults to private.
+ // Conflicts with NoCgroups if not set to host.
+ // Mandatory.
+ CgroupNS Namespace `json:"cgroupns,omitempty"`
+ // NoCgroups indicates that the container should not create CGroups.
+ // Conflicts with CgroupParent and CgroupNS if CgroupNS is not set to
+ // host.
+ NoCgroups bool `json:"no_cgroups,omitempty"`
+ // CgroupParent is the container's CGroup parent.
+ // If not set, the default for the current cgroup driver will be used.
+ // Conflicts with NoCgroups.
+ // Optional.
+ CgroupParent string `json:"cgroup_parent,omitempty"`
+}
+
+// ContainerNetworkConfig contains information on a container's network
+// configuration.
+type ContainerNetworkConfig struct {
+ // NetNS is the configuration to use for the container's network
+ // namespace.
+ // Mandatory.
+ NetNS Namespace `json:"netns,omitempty"`
+ // ConfigureNetNS is whether Libpod will configure the container's
+ // network namespace to send and receive traffic.
+ // Only available is NetNS is private - conflicts with other NetNS
+ // modes.
+ ConfigureNetNS bool `json:"configure_netns,omitempty"`
+ // StaticIP is the a IPv4 address of the container.
+ // Only available if ConfigureNetNS is true.
+ // Optional.
+ StaticIP *net.IP `json:"static_ip,omitempty"`
+ // StaticIPv6 is a static IPv6 address to set in the container.
+ // Only available if ConfigureNetNS is true.
+ // Optional.
+ StaticIPv6 *net.IP `json:"static_ipv6,omitempty"`
+ // StaticMAC is a static MAC address to set in the container.
+ // Only available if ConfigureNetNS is true.
+ // Optional.
+ StaticMAC *net.HardwareAddr `json:"static_mac,omitempty"`
+ // PortBindings is a set of ports to map into the container.
+ // Only available if ConfigureNetNS is true.
+ // Optional.
+ PortMappings []ocicni.PortMapping `json:"portmappings,omitempty"`
+ // PublishImagePorts will publish ports specified in the image to random
+ // ports outside.
+ // Requires Image to be set.
+ PublishImagePorts bool `json:"publish_image_ports,omitempty"`
+ // CNINetworks is a list of CNI networks to join the container to.
+ // If this list is empty, the default CNI network will be joined
+ // instead. If at least one entry is present, we will not join the
+ // default network (unless it is part of this list).
+ // Only available if ConfigureNetNS is true.
+ // Optional.
+ CNINetworks []string `json:"cni_networks,omitempty"`
+ // UseImageResolvConf indicates that resolv.conf should not be managed
+ // by Podman, but instead sourced from the image.
+ // Conflicts with DNSServer, DNSSearch, DNSOption.
+ UseImageResolvConf bool `json:"use_image_resolve_conf,omitempty"`
+ // DNSServer is a set of DNS servers that will be used in the
+ // container's resolv.conf, replacing the host's DNS Servers which are
+ // used by default.
+ // Conflicts with UseImageResolvConf.
+ // Optional.
+ DNSServer []net.IP `json:"dns_server,omitempty"`
+ // DNSSearch is a set of DNS search domains that will be used in the
+ // container's resolv.conf, replacing the host's DNS search domains
+ // which are used by default.
+ // Conflicts with UseImageResolvConf.
+ // Optional.
+ DNSSearch []string `json:"dns_search,omitempty"`
+ // DNSOption is a set of DNS options that will be used in the
+ // container's resolv.conf, replacing the host's DNS options which are
+ // used by default.
+ // Conflicts with UseImageResolvConf.
+ // Optional.
+ DNSOption []string `json:"dns_option,omitempty"`
+ // UseImageHosts indicates that /etc/hosts should not be managed by
+ // Podman, and instead sourced from the image.
+ // Conflicts with HostAdd.
+ UseImageHosts bool `json:"use_image_hosts,omitempty"`
+ // HostAdd is a set of hosts which will be added to the container's
+ // /etc/hosts file.
+ // Conflicts with UseImageHosts.
+ // Optional.
+ HostAdd []string `json:"hostadd,omitempty"`
+}
+
+// ContainerResourceConfig contains information on container resource limits.
+type ContainerResourceConfig struct {
+ // ResourceLimits are resource limits to apply to the container.
+ // Can only be set as root on cgroups v1 systems, but can be set as
+ // rootless as well for cgroups v2.
+ // Optional.
+ ResourceLimits *spec.LinuxResources `json:"resource_limits,omitempty"`
+ // Rlimits are POSIX rlimits to apply to the container.
+ // Optional.
+ Rlimits []spec.POSIXRlimit `json:"r_limits,omitempty"`
+ // OOMScoreAdj adjusts the score used by the OOM killer to determine
+ // processes to kill for the container's process.
+ // Optional.
+ OOMScoreAdj *int `json:"oom_score_adj,omitempty"`
+}
+
+// ContainerHealthCheckConfig describes a container healthcheck with attributes
+// like command, retries, interval, start period, and timeout.
+type ContainerHealthCheckConfig struct {
+ HealthConfig manifest.Schema2HealthConfig `json:"healthconfig,omitempty"`
+}
+
+// SpecGenerator creates an OCI spec and Libpod configuration options to create
+// a container based on the given configuration.
+type SpecGenerator struct {
+ ContainerBasicConfig
+ ContainerStorageConfig
+ ContainerSecurityConfig
+ ContainerCgroupConfig
+ ContainerNetworkConfig
+ ContainerResourceConfig
+ ContainerHealthCheckConfig
+}
+
+// NewSpecGenerator returns a SpecGenerator struct given one of two mandatory inputs
+func NewSpecGenerator(image, rootfs *string) (*SpecGenerator, error) {
+ _ = image
+ _ = rootfs
+ return &SpecGenerator{}, define.ErrNotImplemented
+}
+
+// Validate verifies that the given SpecGenerator is valid and satisfies required
+// input for creating a container.
+func (s *SpecGenerator) Validate() error {
+ return define.ErrNotImplemented
+}
+
+// MakeContainer creates a container based on the SpecGenerator
+func (s *SpecGenerator) MakeContainer() (*libpod.Container, error) {
+ return nil, define.ErrNotImplemented
+}
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 71f5d1b02..b4e400549 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -3,7 +3,9 @@
package integration
import (
+ "io/ioutil"
"os"
+ "path/filepath"
"strings"
. "github.com/containers/libpod/test/utils"
@@ -105,4 +107,39 @@ var _ = Describe("Podman build", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
+
+ It("podman build Containerfile locations", func() {
+ // Given
+ // Switch to temp dir and restore it afterwards
+ cwd, err := os.Getwd()
+ Expect(err).To(BeNil())
+ Expect(os.Chdir(os.TempDir())).To(BeNil())
+ defer Expect(os.Chdir(cwd)).To(BeNil())
+
+ // Write target and fake files
+ targetPath := filepath.Join(os.TempDir(), "dir")
+ Expect(os.MkdirAll(targetPath, 0755)).To(BeNil())
+
+ fakeFile := filepath.Join(os.TempDir(), "Containerfile")
+ Expect(ioutil.WriteFile(fakeFile, []byte("FROM alpine"), 0755)).To(BeNil())
+
+ targetFile := filepath.Join(targetPath, "Containerfile")
+ Expect(ioutil.WriteFile(targetFile, []byte("FROM scratch"), 0755)).To(BeNil())
+
+ defer func() {
+ Expect(os.RemoveAll(fakeFile)).To(BeNil())
+ Expect(os.RemoveAll(targetFile)).To(BeNil())
+ }()
+
+ // When
+ session := podmanTest.PodmanNoCache([]string{
+ "build", "-f", targetFile, "-t", "test-locations",
+ })
+ session.WaitWithDefaultTimeout()
+
+ // Then
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(strings.Fields(session.OutputToString())).
+ To(ContainElement("scratch"))
+ })
})
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index 12bfdfe41..fccc5c93b 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -227,6 +227,22 @@ var _ = Describe("Podman ps", func() {
Expect(output[0]).To(Equal(fullCid))
})
+ It("podman ps filter by exited does not need all", func() {
+ ctr := podmanTest.Podman([]string{"run", "-t", "-i", ALPINE, "ls", "/"})
+ ctr.WaitWithDefaultTimeout()
+ Expect(ctr.ExitCode()).To(Equal(0))
+
+ psAll := podmanTest.Podman([]string{"ps", "-aq", "--no-trunc"})
+ psAll.WaitWithDefaultTimeout()
+ Expect(psAll.ExitCode()).To(Equal(0))
+
+ psFilter := podmanTest.Podman([]string{"ps", "--no-trunc", "--quiet", "--filter", "status=exited"})
+ psFilter.WaitWithDefaultTimeout()
+ Expect(psFilter.ExitCode()).To(Equal(0))
+
+ Expect(psAll.OutputToString()).To(Equal(psFilter.OutputToString()))
+ })
+
It("podman ps mutually exclusive flags", func() {
session := podmanTest.Podman([]string{"ps", "-aqs"})
session.WaitWithDefaultTimeout()
diff --git a/vendor/github.com/acarl005/stripansi/LICENSE b/vendor/github.com/acarl005/stripansi/LICENSE
new file mode 100644
index 000000000..00abe0dbf
--- /dev/null
+++ b/vendor/github.com/acarl005/stripansi/LICENSE
@@ -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.
diff --git a/vendor/github.com/acarl005/stripansi/README.md b/vendor/github.com/acarl005/stripansi/README.md
new file mode 100644
index 000000000..8bdb1f505
--- /dev/null
+++ b/vendor/github.com/acarl005/stripansi/README.md
@@ -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"
+}
+```
diff --git a/vendor/github.com/acarl005/stripansi/stripansi.go b/vendor/github.com/acarl005/stripansi/stripansi.go
new file mode 100644
index 000000000..235732a78
--- /dev/null
+++ b/vendor/github.com/acarl005/stripansi/stripansi.go
@@ -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, "")
+}
diff --git a/vendor/github.com/containers/image/v5/copy/copy.go b/vendor/github.com/containers/image/v5/copy/copy.go
index 29660b6b2..36957fc77 100644
--- a/vendor/github.com/containers/image/v5/copy/copy.go
+++ b/vendor/github.com/containers/image/v5/copy/copy.go
@@ -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
diff --git a/vendor/github.com/containers/image/v5/directory/directory_dest.go b/vendor/github.com/containers/image/v5/directory/directory_dest.go
index caa7a207f..d70b6c07f 100644
--- a/vendor/github.com/containers/image/v5/directory/directory_dest.go
+++ b/vendor/github.com/containers/image/v5/directory/directory_dest.go
@@ -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
}
diff --git a/vendor/github.com/containers/image/v5/docker/docker_client.go b/vendor/github.com/containers/image/v5/docker/docker_client.go
index 986bcb986..aa8463d18 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_client.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_client.go
@@ -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
-
- // 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 := 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
}
- return b
- }
- 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)
+ delay = parseRetryAfter(res, delay)
+ if delay > backoffMaxDelay {
+ delay = backoffMaxDelay
}
- // 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)
+ 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
}
- // 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
+ delay = delay * 2 // exponential back off
}
- 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
}
diff --git a/vendor/github.com/containers/image/v5/docker/docker_image.go b/vendor/github.com/containers/image/v5/docker/docker_image.go
index dad382cd0..483581dbc 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_image.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_image.go
@@ -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
}
diff --git a/vendor/github.com/containers/image/v5/docker/docker_image_dest.go b/vendor/github.com/containers/image/v5/docker/docker_image_dest.go
index 47a73d868..ab74e1607 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_image_dest.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_image_dest.go
@@ -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))
}
diff --git a/vendor/github.com/containers/image/v5/docker/docker_image_src.go b/vendor/github.com/containers/image/v5/docker/docker_image_src.go
index 35beb30e5..967845e72 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_image_src.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_image_src.go
@@ -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
}
+ type attempt struct {
+ ref reference.Named
+ err error
+ }
+ attempts := []attempt{}
for _, pullSource := range pullSources {
- logrus.Debugf("Trying to pull %q", pullSource.Reference)
- dockerRef, err := newReference(pullSource.Reference)
- if err != nil {
- return nil, err
+ logrus.Debugf("Trying to access %q", pullSource.Reference)
+ s, err := newImageSourceAttempt(ctx, sys, pullSource, primaryDomain)
+ if err == nil {
+ return s, nil
}
-
- 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 = &copy
+ 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())
+ }
+}
- client, err := newDockerClientFromRef(endpointSys, dockerRef, false, "pull")
- if err != nil {
- return nil, err
- }
- client.tlsClientConfig.InsecureSkipVerify = pullSource.Endpoint.Insecure
+// 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
+ }
- testImageSource := &dockerImageSource{
- ref: dockerRef,
- c: client,
- }
+ 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 = &copy
+ }
- manifestLoadErr = testImageSource.ensureManifestIsLoaded(ctx)
- if manifestLoadErr == nil {
- return testImageSource, nil
- }
+ client, err := newDockerClientFromRef(endpointSys, ref, false, "pull")
+ if err != nil {
+ return nil, err
}
- return nil, manifestLoadErr
+ 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
}
diff --git a/vendor/github.com/containers/image/v5/docker/errors.go b/vendor/github.com/containers/image/v5/docker/errors.go
index 860868f41..f626cc7da 100644
--- a/vendor/github.com/containers/image/v5/docker/errors.go
+++ b/vendor/github.com/containers/image/v5/docker/errors.go
@@ -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))
}
}
diff --git a/vendor/github.com/containers/image/v5/docker/tarfile/dest.go b/vendor/github.com/containers/image/v5/docker/tarfile/dest.go
index c322156b5..c171da505 100644
--- a/vendor/github.com/containers/image/v5/docker/tarfile/dest.go
+++ b/vendor/github.com/containers/image/v5/docker/tarfile/dest.go
@@ -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")
}
diff --git a/vendor/github.com/containers/image/v5/docker/tarfile/src.go b/vendor/github.com/containers/image/v5/docker/tarfile/src.go
index 80dd753e4..c1f1a0f27 100644
--- a/vendor/github.com/containers/image/v5/docker/tarfile/src.go
+++ b/vendor/github.com/containers/image/v5/docker/tarfile/src.go
@@ -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
}
diff --git a/vendor/github.com/containers/image/v5/image/docker_schema2.go b/vendor/github.com/containers/image/v5/image/docker_schema2.go
index 7891562b7..1e2114d7e 100644
--- a/vendor/github.com/containers/image/v5/image/docker_schema2.go
+++ b/vendor/github.com/containers/image/v5/image/docker_schema2.go
@@ -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
}
diff --git a/vendor/github.com/containers/image/v5/image/oci.go b/vendor/github.com/containers/image/v5/image/oci.go
index 059d84977..b5ddb9aaa 100644
--- a/vendor/github.com/containers/image/v5/image/oci.go
+++ b/vendor/github.com/containers/image/v5/image/oci.go
@@ -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
}
diff --git a/vendor/github.com/containers/image/v5/internal/iolimits/iolimits.go b/vendor/github.com/containers/image/v5/internal/iolimits/iolimits.go
new file mode 100644
index 000000000..3fed1995c
--- /dev/null
+++ b/vendor/github.com/containers/image/v5/internal/iolimits/iolimits.go
@@ -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
+}
diff --git a/vendor/github.com/containers/image/v5/openshift/openshift.go b/vendor/github.com/containers/image/v5/openshift/openshift.go
index b9242da6e..28bfc456d 100644
--- a/vendor/github.com/containers/image/v5/openshift/openshift.go
+++ b/vendor/github.com/containers/image/v5/openshift/openshift.go
@@ -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
}
diff --git a/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go b/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
index 4825ab27c..277fba16b 100644
--- a/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
+++ b/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
@@ -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)
}
diff --git a/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go b/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
index eccd610c9..51f20f310 100644
--- a/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
+++ b/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
@@ -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)
}
diff --git a/vendor/github.com/containers/image/v5/types/types.go b/vendor/github.com/containers/image/v5/types/types.go
index d38a17fab..ba249ca25 100644
--- a/vendor/github.com/containers/image/v5/types/types.go
+++ b/vendor/github.com/containers/image/v5/types/types.go
@@ -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
diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go
index a92774466..1a44baf99 100644
--- a/vendor/github.com/containers/image/v5/version/version.go
+++ b/vendor/github.com/containers/image/v5/version/version.go
@@ -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
diff --git a/vendor/github.com/containers/storage/.golangci.yml b/vendor/github.com/containers/storage/.golangci.yml
index ec4ebb187..cd4638a39 100644
--- a/vendor/github.com/containers/storage/.golangci.yml
+++ b/vendor/github.com/containers/storage/.golangci.yml
@@ -3,37 +3,35 @@ run:
concurrency: 6
deadline: 5m
linters:
- disable-all: true
- enable:
- - bodyclose
- - depguard
- - gofmt
- - interfacer
- - typecheck
- # - deadcode
- # - dupl
- # - errcheck
- # - gochecknoglobals
- # - gochecknoinits
- # - goconst
- # - gocritic
- # - gocyclo
- # - goimports
- # - golint
- # - gosec
- # - gosimple
- # - govet
- # - ineffassign
- # - lll
- # - maligned
- # - misspell
- # - nakedret
- # - prealloc
- # - scopelint
- # - staticcheck
- # - structcheck
- # - stylecheck
- # - unconvert
- # - unparam
- # - unused
- # - varcheck
+ enable-all: true
+ disable:
+ - dogsled
+ - dupl
+ - errcheck
+ - funlen
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - gocritic
+ - gocyclo
+ - godox
+ - gomnd
+ - gosec
+ - gosimple
+ - govet
+ - ineffassign
+ - lll
+ - maligned
+ - misspell
+ - nakedret
+ - prealloc
+ - scopelint
+ - staticcheck
+ - structcheck
+ - stylecheck
+ - unconvert
+ - unparam
+ - unused
+ - varcheck
+ - whitespace
+ - wsl
diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION
index 928b5d437..98e863cdf 100644
--- a/vendor/github.com/containers/storage/VERSION
+++ b/vendor/github.com/containers/storage/VERSION
@@ -1 +1 @@
-1.15.8-dev
+1.15.8
diff --git a/vendor/github.com/containers/storage/drivers/aufs/aufs.go b/vendor/github.com/containers/storage/drivers/aufs/aufs.go
index 4430670a2..c4ced0488 100644
--- a/vendor/github.com/containers/storage/drivers/aufs/aufs.go
+++ b/vendor/github.com/containers/storage/drivers/aufs/aufs.go
@@ -35,7 +35,7 @@ import (
"sync"
"time"
- "github.com/containers/storage/drivers"
+ graphdriver "github.com/containers/storage/drivers"
"github.com/containers/storage/pkg/archive"
"github.com/containers/storage/pkg/chrootarchive"
"github.com/containers/storage/pkg/directory"
diff --git a/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go b/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go
index 5be1639d0..be4362dc0 100644
--- a/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go
+++ b/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go
@@ -26,7 +26,7 @@ import (
"sync"
"unsafe"
- "github.com/containers/storage/drivers"
+ graphdriver "github.com/containers/storage/drivers"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/mount"
"github.com/containers/storage/pkg/parsers"
diff --git a/vendor/github.com/containers/storage/drivers/chown_unix.go b/vendor/github.com/containers/storage/drivers/chown_unix.go
index 51d6d754b..94c641536 100644
--- a/vendor/github.com/containers/storage/drivers/chown_unix.go
+++ b/vendor/github.com/containers/storage/drivers/chown_unix.go
@@ -25,14 +25,14 @@ func platformLChown(path string, info os.FileInfo, toHost, toContainer *idtools.
UID: uid,
GID: gid,
}
- mappedUid, mappedGid, err := toContainer.ToContainer(pair)
+ mappedUID, mappedGID, err := toContainer.ToContainer(pair)
if err != nil {
if (uid != 0) || (gid != 0) {
return fmt.Errorf("error mapping host ID pair %#v for %q to container: %v", pair, path, err)
}
- mappedUid, mappedGid = uid, gid
+ mappedUID, mappedGID = uid, gid
}
- uid, gid = mappedUid, mappedGid
+ uid, gid = mappedUID, mappedGID
}
if toHost != nil {
pair := idtools.IDPair{
diff --git a/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go b/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go
index 1ea6cfc36..867ad1196 100644
--- a/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go
+++ b/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go
@@ -18,7 +18,7 @@ import (
"sync"
"time"
- "github.com/containers/storage/drivers"
+ graphdriver "github.com/containers/storage/drivers"
"github.com/containers/storage/pkg/devicemapper"
"github.com/containers/storage/pkg/dmesg"
"github.com/containers/storage/pkg/idtools"
@@ -49,8 +49,13 @@ var (
lvmSetupConfigForce bool
)
-const deviceSetMetaFile string = "deviceset-metadata"
-const transactionMetaFile string = "transaction-metadata"
+const (
+ deviceSetMetaFile = "deviceset-metadata"
+ transactionMetaFile = "transaction-metadata"
+ xfs = "xfs"
+ ext4 = "ext4"
+ base = "base"
+)
type transaction struct {
OpenTransactionID uint64 `json:"open_transaction_id"`
@@ -199,7 +204,7 @@ func getDevName(name string) string {
func (info *devInfo) Name() string {
hash := info.Hash
if hash == "" {
- hash = "base"
+ hash = base
}
return fmt.Sprintf("%s-%s", info.devices.devicePrefix, hash)
}
@@ -219,7 +224,7 @@ func (devices *DeviceSet) metadataDir() string {
func (devices *DeviceSet) metadataFile(info *devInfo) string {
file := info.Hash
if file == "" {
- file = "base"
+ file = base
}
return path.Join(devices.metadataDir(), file)
}
@@ -440,7 +445,7 @@ func (devices *DeviceSet) deviceFileWalkFunction(path string, finfo os.FileInfo)
logrus.Debugf("devmapper: Loading data for file %s", path)
hash := finfo.Name()
- if hash == "base" {
+ if hash == base {
hash = ""
}
@@ -542,7 +547,7 @@ func xfsSupported() error {
}
// Check if kernel supports xfs filesystem or not.
- exec.Command("modprobe", "xfs").Run()
+ exec.Command("modprobe", xfs).Run()
f, err := os.Open("/proc/filesystems")
if err != nil {
@@ -567,16 +572,16 @@ func xfsSupported() error {
func determineDefaultFS() string {
err := xfsSupported()
if err == nil {
- return "xfs"
+ return xfs
}
- logrus.Warnf("devmapper: XFS is not supported in your system (%v). Defaulting to ext4 filesystem", err)
- return "ext4"
+ logrus.Warnf("devmapper: XFS is not supported in your system (%v). Defaulting to %s filesystem", ext4, err)
+ return ext4
}
// mkfsOptions tries to figure out whether some additional mkfs options are required
func mkfsOptions(fs string) []string {
- if fs == "xfs" && !kernel.CheckKernelVersion(3, 16, 0) {
+ if fs == xfs && !kernel.CheckKernelVersion(3, 16, 0) {
// For kernels earlier than 3.16 (and newer xfsutils),
// some xfs features need to be explicitly disabled.
return []string{"-m", "crc=0,finobt=0"}
@@ -609,9 +614,9 @@ func (devices *DeviceSet) createFilesystem(info *devInfo) (err error) {
}()
switch devices.filesystem {
- case "xfs":
+ case xfs:
err = exec.Command("mkfs.xfs", args...).Run()
- case "ext4":
+ case ext4:
err = exec.Command("mkfs.ext4", append([]string{"-E", "nodiscard,lazy_itable_init=0,lazy_journal_init=0"}, args...)...).Run()
if err != nil {
err = exec.Command("mkfs.ext4", append([]string{"-E", "nodiscard,lazy_itable_init=0"}, args...)...).Run()
@@ -1197,7 +1202,7 @@ func (devices *DeviceSet) growFS(info *devInfo) error {
}
options := ""
- if devices.BaseDeviceFilesystem == "xfs" {
+ if devices.BaseDeviceFilesystem == xfs {
// XFS needs nouuid or it can't mount filesystems with the same fs
options = joinMountOptions(options, "nouuid")
}
@@ -1210,11 +1215,11 @@ func (devices *DeviceSet) growFS(info *devInfo) error {
defer unix.Unmount(fsMountPoint, unix.MNT_DETACH)
switch devices.BaseDeviceFilesystem {
- case "ext4":
+ case ext4:
if out, err := exec.Command("resize2fs", info.DevName()).CombinedOutput(); err != nil {
return fmt.Errorf("Failed to grow rootfs:%v:%s", err, string(out))
}
- case "xfs":
+ case xfs:
if out, err := exec.Command("xfs_growfs", info.DevName()).CombinedOutput(); err != nil {
return fmt.Errorf("Failed to grow rootfs:%v:%s", err, string(out))
}
@@ -2391,7 +2396,7 @@ func (devices *DeviceSet) MountDevice(hash, path string, moptions graphdriver.Mo
options := ""
- if fstype == "xfs" {
+ if fstype == xfs {
// XFS needs nouuid or it can't mount filesystems with the same fs
options = joinMountOptions(options, "nouuid")
}
@@ -2412,7 +2417,7 @@ func (devices *DeviceSet) MountDevice(hash, path string, moptions graphdriver.Mo
return fmt.Errorf("devmapper: Error mounting '%s' on '%s': %s\n%v", info.DevName(), path, err, string(dmesg.Dmesg(256)))
}
- if fstype == "xfs" && devices.xfsNospaceRetries != "" {
+ if fstype == xfs && devices.xfsNospaceRetries != "" {
if err := devices.xfsSetNospaceRetries(info); err != nil {
unix.Unmount(path, unix.MNT_DETACH)
devices.deactivateDevice(info)
@@ -2693,7 +2698,7 @@ func NewDeviceSet(root string, doInit bool, options []string, uidMaps, gidMaps [
}
devices.metaDataLoopbackSize = size
case "dm.fs":
- if val != "ext4" && val != "xfs" {
+ if val != ext4 && val != xfs {
return nil, fmt.Errorf("devmapper: Unsupported filesystem %s", val)
}
devices.filesystem = val
diff --git a/vendor/github.com/containers/storage/drivers/devmapper/driver.go b/vendor/github.com/containers/storage/drivers/devmapper/driver.go
index 3c044c12e..ca50e7f06 100644
--- a/vendor/github.com/containers/storage/drivers/devmapper/driver.go
+++ b/vendor/github.com/containers/storage/drivers/devmapper/driver.go
@@ -9,7 +9,7 @@ import (
"path"
"strconv"
- "github.com/containers/storage/drivers"
+ graphdriver "github.com/containers/storage/drivers"
"github.com/containers/storage/pkg/devicemapper"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/locker"
diff --git a/vendor/github.com/containers/storage/drivers/driver.go b/vendor/github.com/containers/storage/drivers/driver.go
index 8d6b2a5dc..a5393c10f 100644
--- a/vendor/github.com/containers/storage/drivers/driver.go
+++ b/vendor/github.com/containers/storage/drivers/driver.go
@@ -49,8 +49,8 @@ type MountOpts struct {
// Mount label is the MAC Labels to assign to mount point (SELINUX)
MountLabel string
// UidMaps & GidMaps are the User Namespace mappings to be assigned to content in the mount point
- UidMaps []idtools.IDMap
- GidMaps []idtools.IDMap
+ UidMaps []idtools.IDMap // nolint: golint
+ GidMaps []idtools.IDMap // nolint: golint
Options []string
}
diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
index 25d885be9..232cac71a 100644
--- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go
+++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
@@ -401,9 +401,8 @@ func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGI
if err == nil {
logrus.Debugf("overlay test mount with multiple lowers succeeded")
return supportsDType, nil
- } else {
- logrus.Debugf("overlay test mount with multiple lowers failed %v", err)
}
+ logrus.Debugf("overlay test mount with multiple lowers failed %v", err)
}
flags = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lower1Dir, upperDir, workDir)
if len(flags) < unix.Getpagesize() {
@@ -411,9 +410,8 @@ func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGI
if err == nil {
logrus.Errorf("overlay test mount with multiple lowers failed, but succeeded with a single lower")
return supportsDType, errors.Wrap(graphdriver.ErrNotSupported, "kernel too old to provide multiple lowers feature for overlay")
- } else {
- logrus.Debugf("overlay test mount with a single lower failed %v", err)
}
+ logrus.Debugf("overlay test mount with a single lower failed %v", err)
}
logrus.Errorf("'overlay' is not supported over %s at %q", backingFs, home)
return supportsDType, errors.Wrapf(graphdriver.ErrIncompatibleFS, "'overlay' is not supported over %s at %q", backingFs, home)
@@ -810,15 +808,6 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
return "", err
}
readWrite := true
- // fuse-overlayfs doesn't support working without an upperdir.
- if d.options.mountProgram == "" {
- for _, o := range options.Options {
- if o == "ro" {
- readWrite = false
- break
- }
- }
- }
lowers, err := ioutil.ReadFile(path.Join(dir, lowerFile))
if err != nil && !os.IsNotExist(err) {
diff --git a/vendor/github.com/containers/storage/drivers/overlayutils/overlayutils.go b/vendor/github.com/containers/storage/drivers/overlayutils/overlayutils.go
index 49aaad07d..9fc57b36b 100644
--- a/vendor/github.com/containers/storage/drivers/overlayutils/overlayutils.go
+++ b/vendor/github.com/containers/storage/drivers/overlayutils/overlayutils.go
@@ -5,7 +5,7 @@ package overlayutils
import (
"fmt"
- "github.com/containers/storage/drivers"
+ graphdriver "github.com/containers/storage/drivers"
"github.com/pkg/errors"
)
diff --git a/vendor/github.com/containers/storage/drivers/vfs/driver.go b/vendor/github.com/containers/storage/drivers/vfs/driver.go
index 58a1635ae..f2859b427 100644
--- a/vendor/github.com/containers/storage/drivers/vfs/driver.go
+++ b/vendor/github.com/containers/storage/drivers/vfs/driver.go
@@ -8,7 +8,7 @@ import (
"strconv"
"strings"
- "github.com/containers/storage/drivers"
+ graphdriver "github.com/containers/storage/drivers"
"github.com/containers/storage/pkg/archive"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/parsers"
diff --git a/vendor/github.com/containers/storage/drivers/zfs/zfs.go b/vendor/github.com/containers/storage/drivers/zfs/zfs.go
index a2bf5565b..c9c8c5c3c 100644
--- a/vendor/github.com/containers/storage/drivers/zfs/zfs.go
+++ b/vendor/github.com/containers/storage/drivers/zfs/zfs.go
@@ -12,7 +12,7 @@ import (
"sync"
"time"
- "github.com/containers/storage/drivers"
+ graphdriver "github.com/containers/storage/drivers"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/mount"
"github.com/containers/storage/pkg/parsers"
diff --git a/vendor/github.com/containers/storage/drivers/zfs/zfs_linux.go b/vendor/github.com/containers/storage/drivers/zfs/zfs_linux.go
index fb1ef3a3d..edcb1da36 100644
--- a/vendor/github.com/containers/storage/drivers/zfs/zfs_linux.go
+++ b/vendor/github.com/containers/storage/drivers/zfs/zfs_linux.go
@@ -1,7 +1,7 @@
package zfs
import (
- "github.com/containers/storage/drivers"
+ graphdriver "github.com/containers/storage/drivers"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod
index b7a05a65b..ba40f9c14 100644
--- a/vendor/github.com/containers/storage/go.mod
+++ b/vendor/github.com/containers/storage/go.mod
@@ -7,14 +7,14 @@ require (
github.com/Microsoft/hcsshim v0.8.7
github.com/docker/docker v0.0.0-20171019062838-86f080cff091 // indirect
github.com/docker/go-units v0.4.0
- github.com/klauspost/compress v1.9.7
+ github.com/klauspost/compress v1.9.8
github.com/klauspost/cpuid v1.2.1 // indirect
github.com/klauspost/pgzip v1.2.1
- github.com/mattn/go-shellwords v1.0.7
+ github.com/mattn/go-shellwords v1.0.9
github.com/mistifyio/go-zfs v2.1.1+incompatible
github.com/opencontainers/go-digest v1.0.0-rc1
github.com/opencontainers/runc v1.0.0-rc9
- github.com/opencontainers/selinux v1.3.0
+ github.com/opencontainers/selinux v1.3.1
github.com/pkg/errors v0.9.1
github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7
github.com/sirupsen/logrus v1.4.2
@@ -24,7 +24,7 @@ require (
github.com/tchap/go-patricia v2.3.0+incompatible
github.com/vbatts/tar-split v0.11.1
golang.org/x/net v0.0.0-20190628185345-da137c7871d7
- golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3
+ golang.org/x/sys v0.0.0-20191115151921-52ab43148777
gotest.tools v2.2.0+incompatible
)
diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum
index ffda0c42f..e2785594d 100644
--- a/vendor/github.com/containers/storage/go.sum
+++ b/vendor/github.com/containers/storage/go.sum
@@ -77,6 +77,8 @@ github.com/klauspost/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzV
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.9.7 h1:hYW1gP94JUmAhBtJ+LNz5My+gBobDxPR1iVuKug26aA=
github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.9.8 h1:VMAMUUOh+gaxKTMk+zqbjsSjsIcUcL/LF4o63i82QyA=
+github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.1 h1:oIPZROsWuPHpOdMVWLuJZXwgjhrW8r1yEX8UqMyeNHM=
@@ -89,6 +91,8 @@ github.com/mattn/go-shellwords v1.0.6 h1:9Jok5pILi5S1MnDirGVTufYGtksUs/V2BWUP3Zk
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/mattn/go-shellwords v1.0.7 h1:KqhVjVZomx2puPACkj9vrGFqnp42Htvo9SEAWePHKOs=
github.com/mattn/go-shellwords v1.0.7/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
+github.com/mattn/go-shellwords v1.0.9 h1:eaB5JspOwiKKcHdqcjbfe5lA9cNn/4NRRtddXJCimqk=
+github.com/mattn/go-shellwords v1.0.9/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mistifyio/go-zfs v2.1.1+incompatible h1:gAMO1HM9xBRONLHHYnu5iFsOJUiJdNZo6oqSENd4eW8=
github.com/mistifyio/go-zfs v2.1.1+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618 h1:7InQ7/zrOh6SlFjaXFubv0xX0HsuC9qJsdqm7bNQpYM=
@@ -111,6 +115,8 @@ github.com/opencontainers/selinux v1.2.2 h1:Kx9J6eDG5/24A6DtUquGSpJQ+m2MUTahn4Ft
github.com/opencontainers/selinux v1.2.2/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
github.com/opencontainers/selinux v1.3.0 h1:xsI95WzPZu5exzA6JzkLSfdr/DilzOhCJOqGe5TgR0g=
github.com/opencontainers/selinux v1.3.0/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
+github.com/opencontainers/selinux v1.3.1 h1:dn2Rc3wTEvTB6iVqoFrKKeMb0uZ38ZheeyMu2h5C1TI=
+github.com/opencontainers/selinux v1.3.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -194,6 +200,8 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339 h1:zSqWKgm/o7HAnlAzBQ+aetp9fpuyytsXnKA8eiLHYQM=
golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191115151921-52ab43148777 h1:wejkGHRTr38uaKRqECZlsCsJ1/TGxIyFbH32x5zUdu4=
+golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2 h1:/J2nHFg1MTqaRLFO7M+J78ASNsJoz3r0cvHBPQ77fsE=
golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/vendor/github.com/containers/storage/images.go b/vendor/github.com/containers/storage/images.go
index 6373ebb41..ef95598b8 100644
--- a/vendor/github.com/containers/storage/images.go
+++ b/vendor/github.com/containers/storage/images.go
@@ -214,17 +214,17 @@ func bigDataNameIsManifest(name string) bool {
// recomputeDigests takes a fixed digest and a name-to-digest map and builds a
// list of the unique values that would identify the image.
-func (image *Image) recomputeDigests() error {
- validDigests := make([]digest.Digest, 0, len(image.BigDataDigests)+1)
+func (i *Image) recomputeDigests() error {
+ validDigests := make([]digest.Digest, 0, len(i.BigDataDigests)+1)
digests := make(map[digest.Digest]struct{})
- if image.Digest != "" {
- if err := image.Digest.Validate(); err != nil {
- return errors.Wrapf(err, "error validating image digest %q", string(image.Digest))
+ if i.Digest != "" {
+ if err := i.Digest.Validate(); err != nil {
+ return errors.Wrapf(err, "error validating image digest %q", string(i.Digest))
}
- digests[image.Digest] = struct{}{}
- validDigests = append(validDigests, image.Digest)
+ digests[i.Digest] = struct{}{}
+ validDigests = append(validDigests, i.Digest)
}
- for name, digest := range image.BigDataDigests {
+ for name, digest := range i.BigDataDigests {
if !bigDataNameIsManifest(name) {
continue
}
@@ -237,10 +237,10 @@ func (image *Image) recomputeDigests() error {
validDigests = append(validDigests, digest)
}
}
- if image.Digest == "" && len(validDigests) > 0 {
- image.Digest = validDigests[0]
+ if i.Digest == "" && len(validDigests) > 0 {
+ i.Digest = validDigests[0]
}
- image.Digests = validDigests
+ i.Digests = validDigests
return nil
}
diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go
index 0c5fcafde..dccfc169d 100644
--- a/vendor/github.com/containers/storage/layers.go
+++ b/vendor/github.com/containers/storage/layers.go
@@ -239,6 +239,10 @@ type LayerStore interface {
// ApplyDiff reads a tarstream which was created by a previous call to Diff and
// applies its changes to a specified layer.
ApplyDiff(to string, diff io.Reader) (int64, error)
+
+ // LoadLocked wraps Load in a locked state. This means it loads the store
+ // and cleans-up invalid layers if needed.
+ LoadLocked() error
}
type layerStore struct {
@@ -346,6 +350,7 @@ func (r *layerStore) Load() error {
r.byname = names
r.bycompressedsum = compressedsums
r.byuncompressedsum = uncompressedsums
+
// Load and merge information about which layers are mounted, and where.
if r.IsReadWrite() {
r.mountsLockfile.RLock()
@@ -353,22 +358,23 @@ func (r *layerStore) Load() error {
if err = r.loadMounts(); err != nil {
return err
}
- }
- // Last step: if we're writable, try to remove anything that a previous
- // user of this storage area marked for deletion but didn't manage to
- // actually delete.
- if r.IsReadWrite() && r.Locked() {
- for _, layer := range r.layers {
- if layer.Flags == nil {
- layer.Flags = make(map[string]interface{})
- }
- if cleanup, ok := layer.Flags[incompleteFlag]; ok {
- if b, ok := cleanup.(bool); ok && b {
- err = r.deleteInternal(layer.ID)
- if err != nil {
- break
+
+ // Last step: as we’re writable, try to remove anything that a previous
+ // user of this storage area marked for deletion but didn't manage to
+ // actually delete.
+ if r.Locked() {
+ for _, layer := range r.layers {
+ if layer.Flags == nil {
+ layer.Flags = make(map[string]interface{})
+ }
+ if cleanup, ok := layer.Flags[incompleteFlag]; ok {
+ if b, ok := cleanup.(bool); ok && b {
+ err = r.deleteInternal(layer.ID)
+ if err != nil {
+ break
+ }
+ shouldSave = true
}
- shouldSave = true
}
}
}
@@ -376,9 +382,16 @@ func (r *layerStore) Load() error {
return r.saveLayers()
}
}
+
return err
}
+func (r *layerStore) LoadLocked() error {
+ r.lockfile.Lock()
+ defer r.lockfile.Unlock()
+ return r.Load()
+}
+
func (r *layerStore) loadMounts() error {
mounts := make(map[string]*Layer)
mpath := r.mountspath()
@@ -487,8 +500,6 @@ func (s *store) newLayerStore(rundir string, layerdir string, driver drivers.Dri
if err != nil {
return nil, err
}
- lockfile.Lock()
- defer lockfile.Unlock()
mountsLockfile, err := GetLockfile(filepath.Join(rundir, "mountpoints.lock"))
if err != nil {
return nil, err
@@ -516,8 +527,6 @@ func newROLayerStore(rundir string, layerdir string, driver drivers.Driver) (ROL
if err != nil {
return nil, err
}
- lockfile.RLock()
- defer lockfile.Unlock()
rlstore := layerStore{
lockfile: lockfile,
mountsLockfile: nil,
diff --git a/vendor/github.com/containers/storage/layers_ffjson.go b/vendor/github.com/containers/storage/layers_ffjson.go
deleted file mode 100644
index 3a1095226..000000000
--- a/vendor/github.com/containers/storage/layers_ffjson.go
+++ /dev/null
@@ -1,2156 +0,0 @@
-// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
-// source: layers.go
-
-package storage
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "github.com/containers/storage/pkg/archive"
- "github.com/containers/storage/pkg/idtools"
- "github.com/opencontainers/go-digest"
- fflib "github.com/pquerna/ffjson/fflib/v1"
-)
-
-// MarshalJSON marshal bytes to json - template
-func (j *DiffOptions) MarshalJSON() ([]byte, error) {
- var buf fflib.Buffer
- if j == nil {
- buf.WriteString("null")
- return buf.Bytes(), nil
- }
- err := j.MarshalJSONBuf(&buf)
- if err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
-}
-
-// MarshalJSONBuf marshal buff to json - template
-func (j *DiffOptions) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
- if j == nil {
- buf.WriteString("null")
- return nil
- }
- var err error
- var obj []byte
- _ = obj
- _ = err
- if j.Compression != nil {
- buf.WriteString(`{"Compression":`)
- fflib.FormatBits2(buf, uint64(*j.Compression), 10, *j.Compression < 0)
- } else {
- buf.WriteString(`{"Compression":null`)
- }
- buf.WriteByte('}')
- return nil
-}
-
-const (
- ffjtDiffOptionsbase = iota
- ffjtDiffOptionsnosuchkey
-
- ffjtDiffOptionsCompression
-)
-
-var ffjKeyDiffOptionsCompression = []byte("Compression")
-
-// UnmarshalJSON umarshall json - template of ffjson
-func (j *DiffOptions) UnmarshalJSON(input []byte) error {
- fs := fflib.NewFFLexer(input)
- return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
-}
-
-// UnmarshalJSONFFLexer fast json unmarshall - template ffjson
-func (j *DiffOptions) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
- var err error
- currentKey := ffjtDiffOptionsbase
- _ = currentKey
- tok := fflib.FFTok_init
- wantedTok := fflib.FFTok_init
-
-mainparse:
- for {
- tok = fs.Scan()
- // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state))
- if tok == fflib.FFTok_error {
- goto tokerror
- }
-
- switch state {
-
- case fflib.FFParse_map_start:
- if tok != fflib.FFTok_left_bracket {
- wantedTok = fflib.FFTok_left_bracket
- goto wrongtokenerror
- }
- state = fflib.FFParse_want_key
- continue
-
- case fflib.FFParse_after_value:
- if tok == fflib.FFTok_comma {
- state = fflib.FFParse_want_key
- } else if tok == fflib.FFTok_right_bracket {
- goto done
- } else {
- wantedTok = fflib.FFTok_comma
- goto wrongtokenerror
- }
-
- case fflib.FFParse_want_key:
- // json {} ended. goto exit. woo.
- if tok == fflib.FFTok_right_bracket {
- goto done
- }
- if tok != fflib.FFTok_string {
- wantedTok = fflib.FFTok_string
- goto wrongtokenerror
- }
-
- kn := fs.Output.Bytes()
- if len(kn) <= 0 {
- // "" case. hrm.
- currentKey = ffjtDiffOptionsnosuchkey
- state = fflib.FFParse_want_colon
- goto mainparse
- } else {
- switch kn[0] {
-
- case 'C':
-
- if bytes.Equal(ffjKeyDiffOptionsCompression, kn) {
- currentKey = ffjtDiffOptionsCompression
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- }
-
- if fflib.EqualFoldRight(ffjKeyDiffOptionsCompression, kn) {
- currentKey = ffjtDiffOptionsCompression
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- currentKey = ffjtDiffOptionsnosuchkey
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case fflib.FFParse_want_colon:
- if tok != fflib.FFTok_colon {
- wantedTok = fflib.FFTok_colon
- goto wrongtokenerror
- }
- state = fflib.FFParse_want_value
- continue
- case fflib.FFParse_want_value:
-
- if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
- switch currentKey {
-
- case ffjtDiffOptionsCompression:
- goto handle_Compression
-
- case ffjtDiffOptionsnosuchkey:
- err = fs.SkipField(tok)
- if err != nil {
- return fs.WrapErr(err)
- }
- state = fflib.FFParse_after_value
- goto mainparse
- }
- } else {
- goto wantedvalue
- }
- }
- }
-
-handle_Compression:
-
- /* handler: j.Compression type=archive.Compression kind=int quoted=false*/
-
- {
- if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Compression", tok))
- }
- }
-
- {
-
- if tok == fflib.FFTok_null {
-
- j.Compression = nil
-
- } else {
-
- tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
-
- if err != nil {
- return fs.WrapErr(err)
- }
-
- ttypval := archive.Compression(tval)
- j.Compression = &ttypval
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-wantedvalue:
- return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
-wrongtokenerror:
- return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
-tokerror:
- if fs.BigError != nil {
- return fs.WrapErr(fs.BigError)
- }
- err = fs.Error.ToError()
- if err != nil {
- return fs.WrapErr(err)
- }
- panic("ffjson-generated: unreachable, please report bug.")
-done:
-
- return nil
-}
-
-// MarshalJSON marshal bytes to json - template
-func (j *Layer) MarshalJSON() ([]byte, error) {
- var buf fflib.Buffer
- if j == nil {
- buf.WriteString("null")
- return buf.Bytes(), nil
- }
- err := j.MarshalJSONBuf(&buf)
- if err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
-}
-
-// MarshalJSONBuf marshal buff to json - template
-func (j *Layer) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
- if j == nil {
- buf.WriteString("null")
- return nil
- }
- var err error
- var obj []byte
- _ = obj
- _ = err
- buf.WriteString(`{ "id":`)
- fflib.WriteJsonString(buf, string(j.ID))
- buf.WriteByte(',')
- if len(j.Names) != 0 {
- buf.WriteString(`"names":`)
- if j.Names != nil {
- buf.WriteString(`[`)
- for i, v := range j.Names {
- if i != 0 {
- buf.WriteString(`,`)
- }
- fflib.WriteJsonString(buf, string(v))
- }
- buf.WriteString(`]`)
- } else {
- buf.WriteString(`null`)
- }
- buf.WriteByte(',')
- }
- if len(j.Parent) != 0 {
- buf.WriteString(`"parent":`)
- fflib.WriteJsonString(buf, string(j.Parent))
- buf.WriteByte(',')
- }
- if len(j.Metadata) != 0 {
- buf.WriteString(`"metadata":`)
- fflib.WriteJsonString(buf, string(j.Metadata))
- buf.WriteByte(',')
- }
- if len(j.MountLabel) != 0 {
- buf.WriteString(`"mountlabel":`)
- fflib.WriteJsonString(buf, string(j.MountLabel))
- buf.WriteByte(',')
- }
- if true {
- buf.WriteString(`"created":`)
-
- {
-
- obj, err = j.Created.MarshalJSON()
- if err != nil {
- return err
- }
- buf.Write(obj)
-
- }
- buf.WriteByte(',')
- }
- if len(j.CompressedDigest) != 0 {
- buf.WriteString(`"compressed-diff-digest":`)
- fflib.WriteJsonString(buf, string(j.CompressedDigest))
- buf.WriteByte(',')
- }
- if j.CompressedSize != 0 {
- buf.WriteString(`"compressed-size":`)
- fflib.FormatBits2(buf, uint64(j.CompressedSize), 10, j.CompressedSize < 0)
- buf.WriteByte(',')
- }
- if len(j.UncompressedDigest) != 0 {
- buf.WriteString(`"diff-digest":`)
- fflib.WriteJsonString(buf, string(j.UncompressedDigest))
- buf.WriteByte(',')
- }
- if j.UncompressedSize != 0 {
- buf.WriteString(`"diff-size":`)
- fflib.FormatBits2(buf, uint64(j.UncompressedSize), 10, j.UncompressedSize < 0)
- buf.WriteByte(',')
- }
- if j.CompressionType != 0 {
- buf.WriteString(`"compression":`)
- fflib.FormatBits2(buf, uint64(j.CompressionType), 10, j.CompressionType < 0)
- buf.WriteByte(',')
- }
- if len(j.UIDs) != 0 {
- buf.WriteString(`"uidset":`)
- if j.UIDs != nil {
- buf.WriteString(`[`)
- for i, v := range j.UIDs {
- if i != 0 {
- buf.WriteString(`,`)
- }
- fflib.FormatBits2(buf, uint64(v), 10, false)
- }
- buf.WriteString(`]`)
- } else {
- buf.WriteString(`null`)
- }
- buf.WriteByte(',')
- }
- if len(j.GIDs) != 0 {
- buf.WriteString(`"gidset":`)
- if j.GIDs != nil {
- buf.WriteString(`[`)
- for i, v := range j.GIDs {
- if i != 0 {
- buf.WriteString(`,`)
- }
- fflib.FormatBits2(buf, uint64(v), 10, false)
- }
- buf.WriteString(`]`)
- } else {
- buf.WriteString(`null`)
- }
- buf.WriteByte(',')
- }
- if len(j.Flags) != 0 {
- buf.WriteString(`"flags":`)
- /* Falling back. type=map[string]interface {} kind=map */
- err = buf.Encode(j.Flags)
- if err != nil {
- return err
- }
- buf.WriteByte(',')
- }
- if len(j.UIDMap) != 0 {
- buf.WriteString(`"uidmap":`)
- if j.UIDMap != nil {
- buf.WriteString(`[`)
- for i, v := range j.UIDMap {
- if i != 0 {
- buf.WriteString(`,`)
- }
- /* Struct fall back. type=idtools.IDMap kind=struct */
- err = buf.Encode(&v)
- if err != nil {
- return err
- }
- }
- buf.WriteString(`]`)
- } else {
- buf.WriteString(`null`)
- }
- buf.WriteByte(',')
- }
- if len(j.GIDMap) != 0 {
- buf.WriteString(`"gidmap":`)
- if j.GIDMap != nil {
- buf.WriteString(`[`)
- for i, v := range j.GIDMap {
- if i != 0 {
- buf.WriteString(`,`)
- }
- /* Struct fall back. type=idtools.IDMap kind=struct */
- err = buf.Encode(&v)
- if err != nil {
- return err
- }
- }
- buf.WriteString(`]`)
- } else {
- buf.WriteString(`null`)
- }
- buf.WriteByte(',')
- }
- buf.Rewind(1)
- buf.WriteByte('}')
- return nil
-}
-
-const (
- ffjtLayerbase = iota
- ffjtLayernosuchkey
-
- ffjtLayerID
-
- ffjtLayerNames
-
- ffjtLayerParent
-
- ffjtLayerMetadata
-
- ffjtLayerMountLabel
-
- ffjtLayerCreated
-
- ffjtLayerCompressedDigest
-
- ffjtLayerCompressedSize
-
- ffjtLayerUncompressedDigest
-
- ffjtLayerUncompressedSize
-
- ffjtLayerCompressionType
-
- ffjtLayerUIDs
-
- ffjtLayerGIDs
-
- ffjtLayerFlags
-
- ffjtLayerUIDMap
-
- ffjtLayerGIDMap
-)
-
-var ffjKeyLayerID = []byte("id")
-
-var ffjKeyLayerNames = []byte("names")
-
-var ffjKeyLayerParent = []byte("parent")
-
-var ffjKeyLayerMetadata = []byte("metadata")
-
-var ffjKeyLayerMountLabel = []byte("mountlabel")
-
-var ffjKeyLayerCreated = []byte("created")
-
-var ffjKeyLayerCompressedDigest = []byte("compressed-diff-digest")
-
-var ffjKeyLayerCompressedSize = []byte("compressed-size")
-
-var ffjKeyLayerUncompressedDigest = []byte("diff-digest")
-
-var ffjKeyLayerUncompressedSize = []byte("diff-size")
-
-var ffjKeyLayerCompressionType = []byte("compression")
-
-var ffjKeyLayerUIDs = []byte("uidset")
-
-var ffjKeyLayerGIDs = []byte("gidset")
-
-var ffjKeyLayerFlags = []byte("flags")
-
-var ffjKeyLayerUIDMap = []byte("uidmap")
-
-var ffjKeyLayerGIDMap = []byte("gidmap")
-
-// UnmarshalJSON umarshall json - template of ffjson
-func (j *Layer) UnmarshalJSON(input []byte) error {
- fs := fflib.NewFFLexer(input)
- return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
-}
-
-// UnmarshalJSONFFLexer fast json unmarshall - template ffjson
-func (j *Layer) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
- var err error
- currentKey := ffjtLayerbase
- _ = currentKey
- tok := fflib.FFTok_init
- wantedTok := fflib.FFTok_init
-
-mainparse:
- for {
- tok = fs.Scan()
- // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state))
- if tok == fflib.FFTok_error {
- goto tokerror
- }
-
- switch state {
-
- case fflib.FFParse_map_start:
- if tok != fflib.FFTok_left_bracket {
- wantedTok = fflib.FFTok_left_bracket
- goto wrongtokenerror
- }
- state = fflib.FFParse_want_key
- continue
-
- case fflib.FFParse_after_value:
- if tok == fflib.FFTok_comma {
- state = fflib.FFParse_want_key
- } else if tok == fflib.FFTok_right_bracket {
- goto done
- } else {
- wantedTok = fflib.FFTok_comma
- goto wrongtokenerror
- }
-
- case fflib.FFParse_want_key:
- // json {} ended. goto exit. woo.
- if tok == fflib.FFTok_right_bracket {
- goto done
- }
- if tok != fflib.FFTok_string {
- wantedTok = fflib.FFTok_string
- goto wrongtokenerror
- }
-
- kn := fs.Output.Bytes()
- if len(kn) <= 0 {
- // "" case. hrm.
- currentKey = ffjtLayernosuchkey
- state = fflib.FFParse_want_colon
- goto mainparse
- } else {
- switch kn[0] {
-
- case 'c':
-
- if bytes.Equal(ffjKeyLayerCreated, kn) {
- currentKey = ffjtLayerCreated
- state = fflib.FFParse_want_colon
- goto mainparse
-
- } else if bytes.Equal(ffjKeyLayerCompressedDigest, kn) {
- currentKey = ffjtLayerCompressedDigest
- state = fflib.FFParse_want_colon
- goto mainparse
-
- } else if bytes.Equal(ffjKeyLayerCompressedSize, kn) {
- currentKey = ffjtLayerCompressedSize
- state = fflib.FFParse_want_colon
- goto mainparse
-
- } else if bytes.Equal(ffjKeyLayerCompressionType, kn) {
- currentKey = ffjtLayerCompressionType
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case 'd':
-
- if bytes.Equal(ffjKeyLayerUncompressedDigest, kn) {
- currentKey = ffjtLayerUncompressedDigest
- state = fflib.FFParse_want_colon
- goto mainparse
-
- } else if bytes.Equal(ffjKeyLayerUncompressedSize, kn) {
- currentKey = ffjtLayerUncompressedSize
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case 'f':
-
- if bytes.Equal(ffjKeyLayerFlags, kn) {
- currentKey = ffjtLayerFlags
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case 'g':
-
- if bytes.Equal(ffjKeyLayerGIDs, kn) {
- currentKey = ffjtLayerGIDs
- state = fflib.FFParse_want_colon
- goto mainparse
-
- } else if bytes.Equal(ffjKeyLayerGIDMap, kn) {
- currentKey = ffjtLayerGIDMap
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case 'i':
-
- if bytes.Equal(ffjKeyLayerID, kn) {
- currentKey = ffjtLayerID
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case 'm':
-
- if bytes.Equal(ffjKeyLayerMetadata, kn) {
- currentKey = ffjtLayerMetadata
- state = fflib.FFParse_want_colon
- goto mainparse
-
- } else if bytes.Equal(ffjKeyLayerMountLabel, kn) {
- currentKey = ffjtLayerMountLabel
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case 'n':
-
- if bytes.Equal(ffjKeyLayerNames, kn) {
- currentKey = ffjtLayerNames
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case 'p':
-
- if bytes.Equal(ffjKeyLayerParent, kn) {
- currentKey = ffjtLayerParent
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case 'u':
-
- if bytes.Equal(ffjKeyLayerUIDs, kn) {
- currentKey = ffjtLayerUIDs
- state = fflib.FFParse_want_colon
- goto mainparse
-
- } else if bytes.Equal(ffjKeyLayerUIDMap, kn) {
- currentKey = ffjtLayerUIDMap
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- }
-
- if fflib.SimpleLetterEqualFold(ffjKeyLayerGIDMap, kn) {
- currentKey = ffjtLayerGIDMap
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.SimpleLetterEqualFold(ffjKeyLayerUIDMap, kn) {
- currentKey = ffjtLayerUIDMap
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.EqualFoldRight(ffjKeyLayerFlags, kn) {
- currentKey = ffjtLayerFlags
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.EqualFoldRight(ffjKeyLayerGIDs, kn) {
- currentKey = ffjtLayerGIDs
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.EqualFoldRight(ffjKeyLayerUIDs, kn) {
- currentKey = ffjtLayerUIDs
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.EqualFoldRight(ffjKeyLayerCompressionType, kn) {
- currentKey = ffjtLayerCompressionType
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.EqualFoldRight(ffjKeyLayerUncompressedSize, kn) {
- currentKey = ffjtLayerUncompressedSize
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.EqualFoldRight(ffjKeyLayerUncompressedDigest, kn) {
- currentKey = ffjtLayerUncompressedDigest
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.EqualFoldRight(ffjKeyLayerCompressedSize, kn) {
- currentKey = ffjtLayerCompressedSize
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.EqualFoldRight(ffjKeyLayerCompressedDigest, kn) {
- currentKey = ffjtLayerCompressedDigest
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.SimpleLetterEqualFold(ffjKeyLayerCreated, kn) {
- currentKey = ffjtLayerCreated
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.SimpleLetterEqualFold(ffjKeyLayerMountLabel, kn) {
- currentKey = ffjtLayerMountLabel
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.SimpleLetterEqualFold(ffjKeyLayerMetadata, kn) {
- currentKey = ffjtLayerMetadata
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.SimpleLetterEqualFold(ffjKeyLayerParent, kn) {
- currentKey = ffjtLayerParent
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.EqualFoldRight(ffjKeyLayerNames, kn) {
- currentKey = ffjtLayerNames
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.SimpleLetterEqualFold(ffjKeyLayerID, kn) {
- currentKey = ffjtLayerID
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- currentKey = ffjtLayernosuchkey
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case fflib.FFParse_want_colon:
- if tok != fflib.FFTok_colon {
- wantedTok = fflib.FFTok_colon
- goto wrongtokenerror
- }
- state = fflib.FFParse_want_value
- continue
- case fflib.FFParse_want_value:
-
- if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
- switch currentKey {
-
- case ffjtLayerID:
- goto handle_ID
-
- case ffjtLayerNames:
- goto handle_Names
-
- case ffjtLayerParent:
- goto handle_Parent
-
- case ffjtLayerMetadata:
- goto handle_Metadata
-
- case ffjtLayerMountLabel:
- goto handle_MountLabel
-
- case ffjtLayerCreated:
- goto handle_Created
-
- case ffjtLayerCompressedDigest:
- goto handle_CompressedDigest
-
- case ffjtLayerCompressedSize:
- goto handle_CompressedSize
-
- case ffjtLayerUncompressedDigest:
- goto handle_UncompressedDigest
-
- case ffjtLayerUncompressedSize:
- goto handle_UncompressedSize
-
- case ffjtLayerCompressionType:
- goto handle_CompressionType
-
- case ffjtLayerUIDs:
- goto handle_UIDs
-
- case ffjtLayerGIDs:
- goto handle_GIDs
-
- case ffjtLayerFlags:
- goto handle_Flags
-
- case ffjtLayerUIDMap:
- goto handle_UIDMap
-
- case ffjtLayerGIDMap:
- goto handle_GIDMap
-
- case ffjtLayernosuchkey:
- err = fs.SkipField(tok)
- if err != nil {
- return fs.WrapErr(err)
- }
- state = fflib.FFParse_after_value
- goto mainparse
- }
- } else {
- goto wantedvalue
- }
- }
- }
-
-handle_ID:
-
- /* handler: j.ID type=string kind=string quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- outBuf := fs.Output.Bytes()
-
- j.ID = string(string(outBuf))
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_Names:
-
- /* handler: j.Names type=[]string kind=slice quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
- j.Names = nil
- } else {
-
- j.Names = []string{}
-
- wantVal := true
-
- for {
-
- var tmpJNames string
-
- tok = fs.Scan()
- if tok == fflib.FFTok_error {
- goto tokerror
- }
- if tok == fflib.FFTok_right_brace {
- break
- }
-
- if tok == fflib.FFTok_comma {
- if wantVal == true {
- // TODO(pquerna): this isn't an ideal error message, this handles
- // things like [,,,] as an array value.
- return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
- }
- continue
- } else {
- wantVal = true
- }
-
- /* handler: tmpJNames type=string kind=string quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- outBuf := fs.Output.Bytes()
-
- tmpJNames = string(string(outBuf))
-
- }
- }
-
- j.Names = append(j.Names, tmpJNames)
-
- wantVal = false
- }
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_Parent:
-
- /* handler: j.Parent type=string kind=string quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- outBuf := fs.Output.Bytes()
-
- j.Parent = string(string(outBuf))
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_Metadata:
-
- /* handler: j.Metadata type=string kind=string quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- outBuf := fs.Output.Bytes()
-
- j.Metadata = string(string(outBuf))
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_MountLabel:
-
- /* handler: j.MountLabel type=string kind=string quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- outBuf := fs.Output.Bytes()
-
- j.MountLabel = string(string(outBuf))
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_Created:
-
- /* handler: j.Created type=time.Time kind=struct quoted=false*/
-
- {
- if tok == fflib.FFTok_null {
-
- } else {
-
- tbuf, err := fs.CaptureField(tok)
- if err != nil {
- return fs.WrapErr(err)
- }
-
- err = j.Created.UnmarshalJSON(tbuf)
- if err != nil {
- return fs.WrapErr(err)
- }
- }
- state = fflib.FFParse_after_value
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_CompressedDigest:
-
- /* handler: j.CompressedDigest type=digest.Digest kind=string quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Digest", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- outBuf := fs.Output.Bytes()
-
- j.CompressedDigest = digest.Digest(string(outBuf))
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_CompressedSize:
-
- /* handler: j.CompressedSize type=int64 kind=int64 quoted=false*/
-
- {
- if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int64", tok))
- }
- }
-
- {
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
-
- if err != nil {
- return fs.WrapErr(err)
- }
-
- j.CompressedSize = int64(tval)
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_UncompressedDigest:
-
- /* handler: j.UncompressedDigest type=digest.Digest kind=string quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Digest", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- outBuf := fs.Output.Bytes()
-
- j.UncompressedDigest = digest.Digest(string(outBuf))
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_UncompressedSize:
-
- /* handler: j.UncompressedSize type=int64 kind=int64 quoted=false*/
-
- {
- if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int64", tok))
- }
- }
-
- {
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
-
- if err != nil {
- return fs.WrapErr(err)
- }
-
- j.UncompressedSize = int64(tval)
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_CompressionType:
-
- /* handler: j.CompressionType type=archive.Compression kind=int quoted=false*/
-
- {
- if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Compression", tok))
- }
- }
-
- {
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
-
- if err != nil {
- return fs.WrapErr(err)
- }
-
- j.CompressionType = archive.Compression(tval)
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_UIDs:
-
- /* handler: j.UIDs type=[]uint32 kind=slice quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
- j.UIDs = nil
- } else {
-
- j.UIDs = []uint32{}
-
- wantVal := true
-
- for {
-
- var tmpJUIDs uint32
-
- tok = fs.Scan()
- if tok == fflib.FFTok_error {
- goto tokerror
- }
- if tok == fflib.FFTok_right_brace {
- break
- }
-
- if tok == fflib.FFTok_comma {
- if wantVal == true {
- // TODO(pquerna): this isn't an ideal error message, this handles
- // things like [,,,] as an array value.
- return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
- }
- continue
- } else {
- wantVal = true
- }
-
- /* handler: tmpJUIDs type=uint32 kind=uint32 quoted=false*/
-
- {
- if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for uint32", tok))
- }
- }
-
- {
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- tval, err := fflib.ParseUint(fs.Output.Bytes(), 10, 32)
-
- if err != nil {
- return fs.WrapErr(err)
- }
-
- tmpJUIDs = uint32(tval)
-
- }
- }
-
- j.UIDs = append(j.UIDs, tmpJUIDs)
-
- wantVal = false
- }
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_GIDs:
-
- /* handler: j.GIDs type=[]uint32 kind=slice quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
- j.GIDs = nil
- } else {
-
- j.GIDs = []uint32{}
-
- wantVal := true
-
- for {
-
- var tmpJGIDs uint32
-
- tok = fs.Scan()
- if tok == fflib.FFTok_error {
- goto tokerror
- }
- if tok == fflib.FFTok_right_brace {
- break
- }
-
- if tok == fflib.FFTok_comma {
- if wantVal == true {
- // TODO(pquerna): this isn't an ideal error message, this handles
- // things like [,,,] as an array value.
- return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
- }
- continue
- } else {
- wantVal = true
- }
-
- /* handler: tmpJGIDs type=uint32 kind=uint32 quoted=false*/
-
- {
- if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for uint32", tok))
- }
- }
-
- {
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- tval, err := fflib.ParseUint(fs.Output.Bytes(), 10, 32)
-
- if err != nil {
- return fs.WrapErr(err)
- }
-
- tmpJGIDs = uint32(tval)
-
- }
- }
-
- j.GIDs = append(j.GIDs, tmpJGIDs)
-
- wantVal = false
- }
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_Flags:
-
- /* handler: j.Flags type=map[string]interface {} kind=map quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_left_bracket && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
- j.Flags = nil
- } else {
-
- j.Flags = make(map[string]interface{}, 0)
-
- wantVal := true
-
- for {
-
- var k string
-
- var tmpJFlags interface{}
-
- tok = fs.Scan()
- if tok == fflib.FFTok_error {
- goto tokerror
- }
- if tok == fflib.FFTok_right_bracket {
- break
- }
-
- if tok == fflib.FFTok_comma {
- if wantVal == true {
- // TODO(pquerna): this isn't an ideal error message, this handles
- // things like [,,,] as an array value.
- return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
- }
- continue
- } else {
- wantVal = true
- }
-
- /* handler: k type=string kind=string quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- outBuf := fs.Output.Bytes()
-
- k = string(string(outBuf))
-
- }
- }
-
- // Expect ':' after key
- tok = fs.Scan()
- if tok != fflib.FFTok_colon {
- return fs.WrapErr(fmt.Errorf("wanted colon token, but got token: %v", tok))
- }
-
- tok = fs.Scan()
- /* handler: tmpJFlags type=interface {} kind=interface quoted=false*/
-
- {
- /* Falling back. type=interface {} kind=interface */
- tbuf, err := fs.CaptureField(tok)
- if err != nil {
- return fs.WrapErr(err)
- }
-
- err = json.Unmarshal(tbuf, &tmpJFlags)
- if err != nil {
- return fs.WrapErr(err)
- }
- }
-
- j.Flags[k] = tmpJFlags
-
- wantVal = false
- }
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_UIDMap:
-
- /* handler: j.UIDMap type=[]idtools.IDMap kind=slice quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
- j.UIDMap = nil
- } else {
-
- j.UIDMap = []idtools.IDMap{}
-
- wantVal := true
-
- for {
-
- var tmpJUIDMap idtools.IDMap
-
- tok = fs.Scan()
- if tok == fflib.FFTok_error {
- goto tokerror
- }
- if tok == fflib.FFTok_right_brace {
- break
- }
-
- if tok == fflib.FFTok_comma {
- if wantVal == true {
- // TODO(pquerna): this isn't an ideal error message, this handles
- // things like [,,,] as an array value.
- return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
- }
- continue
- } else {
- wantVal = true
- }
-
- /* handler: tmpJUIDMap type=idtools.IDMap kind=struct quoted=false*/
-
- {
- /* Falling back. type=idtools.IDMap kind=struct */
- tbuf, err := fs.CaptureField(tok)
- if err != nil {
- return fs.WrapErr(err)
- }
-
- err = json.Unmarshal(tbuf, &tmpJUIDMap)
- if err != nil {
- return fs.WrapErr(err)
- }
- }
-
- j.UIDMap = append(j.UIDMap, tmpJUIDMap)
-
- wantVal = false
- }
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_GIDMap:
-
- /* handler: j.GIDMap type=[]idtools.IDMap kind=slice quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
- j.GIDMap = nil
- } else {
-
- j.GIDMap = []idtools.IDMap{}
-
- wantVal := true
-
- for {
-
- var tmpJGIDMap idtools.IDMap
-
- tok = fs.Scan()
- if tok == fflib.FFTok_error {
- goto tokerror
- }
- if tok == fflib.FFTok_right_brace {
- break
- }
-
- if tok == fflib.FFTok_comma {
- if wantVal == true {
- // TODO(pquerna): this isn't an ideal error message, this handles
- // things like [,,,] as an array value.
- return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
- }
- continue
- } else {
- wantVal = true
- }
-
- /* handler: tmpJGIDMap type=idtools.IDMap kind=struct quoted=false*/
-
- {
- /* Falling back. type=idtools.IDMap kind=struct */
- tbuf, err := fs.CaptureField(tok)
- if err != nil {
- return fs.WrapErr(err)
- }
-
- err = json.Unmarshal(tbuf, &tmpJGIDMap)
- if err != nil {
- return fs.WrapErr(err)
- }
- }
-
- j.GIDMap = append(j.GIDMap, tmpJGIDMap)
-
- wantVal = false
- }
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-wantedvalue:
- return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
-wrongtokenerror:
- return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
-tokerror:
- if fs.BigError != nil {
- return fs.WrapErr(fs.BigError)
- }
- err = fs.Error.ToError()
- if err != nil {
- return fs.WrapErr(err)
- }
- panic("ffjson-generated: unreachable, please report bug.")
-done:
-
- return nil
-}
-
-// MarshalJSON marshal bytes to json - template
-func (j *layerMountPoint) MarshalJSON() ([]byte, error) {
- var buf fflib.Buffer
- if j == nil {
- buf.WriteString("null")
- return buf.Bytes(), nil
- }
- err := j.MarshalJSONBuf(&buf)
- if err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
-}
-
-// MarshalJSONBuf marshal buff to json - template
-func (j *layerMountPoint) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
- if j == nil {
- buf.WriteString("null")
- return nil
- }
- var err error
- var obj []byte
- _ = obj
- _ = err
- buf.WriteString(`{"id":`)
- fflib.WriteJsonString(buf, string(j.ID))
- buf.WriteString(`,"path":`)
- fflib.WriteJsonString(buf, string(j.MountPoint))
- buf.WriteString(`,"count":`)
- fflib.FormatBits2(buf, uint64(j.MountCount), 10, j.MountCount < 0)
- buf.WriteByte('}')
- return nil
-}
-
-const (
- ffjtlayerMountPointbase = iota
- ffjtlayerMountPointnosuchkey
-
- ffjtlayerMountPointID
-
- ffjtlayerMountPointMountPoint
-
- ffjtlayerMountPointMountCount
-)
-
-var ffjKeylayerMountPointID = []byte("id")
-
-var ffjKeylayerMountPointMountPoint = []byte("path")
-
-var ffjKeylayerMountPointMountCount = []byte("count")
-
-// UnmarshalJSON umarshall json - template of ffjson
-func (j *layerMountPoint) UnmarshalJSON(input []byte) error {
- fs := fflib.NewFFLexer(input)
- return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
-}
-
-// UnmarshalJSONFFLexer fast json unmarshall - template ffjson
-func (j *layerMountPoint) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
- var err error
- currentKey := ffjtlayerMountPointbase
- _ = currentKey
- tok := fflib.FFTok_init
- wantedTok := fflib.FFTok_init
-
-mainparse:
- for {
- tok = fs.Scan()
- // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state))
- if tok == fflib.FFTok_error {
- goto tokerror
- }
-
- switch state {
-
- case fflib.FFParse_map_start:
- if tok != fflib.FFTok_left_bracket {
- wantedTok = fflib.FFTok_left_bracket
- goto wrongtokenerror
- }
- state = fflib.FFParse_want_key
- continue
-
- case fflib.FFParse_after_value:
- if tok == fflib.FFTok_comma {
- state = fflib.FFParse_want_key
- } else if tok == fflib.FFTok_right_bracket {
- goto done
- } else {
- wantedTok = fflib.FFTok_comma
- goto wrongtokenerror
- }
-
- case fflib.FFParse_want_key:
- // json {} ended. goto exit. woo.
- if tok == fflib.FFTok_right_bracket {
- goto done
- }
- if tok != fflib.FFTok_string {
- wantedTok = fflib.FFTok_string
- goto wrongtokenerror
- }
-
- kn := fs.Output.Bytes()
- if len(kn) <= 0 {
- // "" case. hrm.
- currentKey = ffjtlayerMountPointnosuchkey
- state = fflib.FFParse_want_colon
- goto mainparse
- } else {
- switch kn[0] {
-
- case 'c':
-
- if bytes.Equal(ffjKeylayerMountPointMountCount, kn) {
- currentKey = ffjtlayerMountPointMountCount
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case 'i':
-
- if bytes.Equal(ffjKeylayerMountPointID, kn) {
- currentKey = ffjtlayerMountPointID
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case 'p':
-
- if bytes.Equal(ffjKeylayerMountPointMountPoint, kn) {
- currentKey = ffjtlayerMountPointMountPoint
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- }
-
- if fflib.SimpleLetterEqualFold(ffjKeylayerMountPointMountCount, kn) {
- currentKey = ffjtlayerMountPointMountCount
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.SimpleLetterEqualFold(ffjKeylayerMountPointMountPoint, kn) {
- currentKey = ffjtlayerMountPointMountPoint
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- if fflib.SimpleLetterEqualFold(ffjKeylayerMountPointID, kn) {
- currentKey = ffjtlayerMountPointID
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- currentKey = ffjtlayerMountPointnosuchkey
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case fflib.FFParse_want_colon:
- if tok != fflib.FFTok_colon {
- wantedTok = fflib.FFTok_colon
- goto wrongtokenerror
- }
- state = fflib.FFParse_want_value
- continue
- case fflib.FFParse_want_value:
-
- if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
- switch currentKey {
-
- case ffjtlayerMountPointID:
- goto handle_ID
-
- case ffjtlayerMountPointMountPoint:
- goto handle_MountPoint
-
- case ffjtlayerMountPointMountCount:
- goto handle_MountCount
-
- case ffjtlayerMountPointnosuchkey:
- err = fs.SkipField(tok)
- if err != nil {
- return fs.WrapErr(err)
- }
- state = fflib.FFParse_after_value
- goto mainparse
- }
- } else {
- goto wantedvalue
- }
- }
- }
-
-handle_ID:
-
- /* handler: j.ID type=string kind=string quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- outBuf := fs.Output.Bytes()
-
- j.ID = string(string(outBuf))
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_MountPoint:
-
- /* handler: j.MountPoint type=string kind=string quoted=false*/
-
- {
-
- {
- if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
- }
- }
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- outBuf := fs.Output.Bytes()
-
- j.MountPoint = string(string(outBuf))
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-handle_MountCount:
-
- /* handler: j.MountCount type=int kind=int quoted=false*/
-
- {
- if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
- return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok))
- }
- }
-
- {
-
- if tok == fflib.FFTok_null {
-
- } else {
-
- tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
-
- if err != nil {
- return fs.WrapErr(err)
- }
-
- j.MountCount = int(tval)
-
- }
- }
-
- state = fflib.FFParse_after_value
- goto mainparse
-
-wantedvalue:
- return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
-wrongtokenerror:
- return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
-tokerror:
- if fs.BigError != nil {
- return fs.WrapErr(fs.BigError)
- }
- err = fs.Error.ToError()
- if err != nil {
- return fs.WrapErr(err)
- }
- panic("ffjson-generated: unreachable, please report bug.")
-done:
-
- return nil
-}
-
-// MarshalJSON marshal bytes to json - template
-func (j *layerStore) MarshalJSON() ([]byte, error) {
- var buf fflib.Buffer
- if j == nil {
- buf.WriteString("null")
- return buf.Bytes(), nil
- }
- err := j.MarshalJSONBuf(&buf)
- if err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
-}
-
-// MarshalJSONBuf marshal buff to json - template
-func (j *layerStore) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
- if j == nil {
- buf.WriteString("null")
- return nil
- }
- var err error
- var obj []byte
- _ = obj
- _ = err
- buf.WriteString(`{}`)
- return nil
-}
-
-const (
- ffjtlayerStorebase = iota
- ffjtlayerStorenosuchkey
-)
-
-// UnmarshalJSON umarshall json - template of ffjson
-func (j *layerStore) UnmarshalJSON(input []byte) error {
- fs := fflib.NewFFLexer(input)
- return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
-}
-
-// UnmarshalJSONFFLexer fast json unmarshall - template ffjson
-func (j *layerStore) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
- var err error
- currentKey := ffjtlayerStorebase
- _ = currentKey
- tok := fflib.FFTok_init
- wantedTok := fflib.FFTok_init
-
-mainparse:
- for {
- tok = fs.Scan()
- // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state))
- if tok == fflib.FFTok_error {
- goto tokerror
- }
-
- switch state {
-
- case fflib.FFParse_map_start:
- if tok != fflib.FFTok_left_bracket {
- wantedTok = fflib.FFTok_left_bracket
- goto wrongtokenerror
- }
- state = fflib.FFParse_want_key
- continue
-
- case fflib.FFParse_after_value:
- if tok == fflib.FFTok_comma {
- state = fflib.FFParse_want_key
- } else if tok == fflib.FFTok_right_bracket {
- goto done
- } else {
- wantedTok = fflib.FFTok_comma
- goto wrongtokenerror
- }
-
- case fflib.FFParse_want_key:
- // json {} ended. goto exit. woo.
- if tok == fflib.FFTok_right_bracket {
- goto done
- }
- if tok != fflib.FFTok_string {
- wantedTok = fflib.FFTok_string
- goto wrongtokenerror
- }
-
- kn := fs.Output.Bytes()
- if len(kn) <= 0 {
- // "" case. hrm.
- currentKey = ffjtlayerStorenosuchkey
- state = fflib.FFParse_want_colon
- goto mainparse
- } else {
- switch kn[0] {
-
- }
-
- currentKey = ffjtlayerStorenosuchkey
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case fflib.FFParse_want_colon:
- if tok != fflib.FFTok_colon {
- wantedTok = fflib.FFTok_colon
- goto wrongtokenerror
- }
- state = fflib.FFParse_want_value
- continue
- case fflib.FFParse_want_value:
-
- if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
- switch currentKey {
-
- case ffjtlayerStorenosuchkey:
- err = fs.SkipField(tok)
- if err != nil {
- return fs.WrapErr(err)
- }
- state = fflib.FFParse_after_value
- goto mainparse
- }
- } else {
- goto wantedvalue
- }
- }
- }
-
-wantedvalue:
- return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
-wrongtokenerror:
- return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
-tokerror:
- if fs.BigError != nil {
- return fs.WrapErr(fs.BigError)
- }
- err = fs.Error.ToError()
- if err != nil {
- return fs.WrapErr(err)
- }
- panic("ffjson-generated: unreachable, please report bug.")
-done:
-
- return nil
-}
-
-// MarshalJSON marshal bytes to json - template
-func (j *simpleGetCloser) MarshalJSON() ([]byte, error) {
- var buf fflib.Buffer
- if j == nil {
- buf.WriteString("null")
- return buf.Bytes(), nil
- }
- err := j.MarshalJSONBuf(&buf)
- if err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
-}
-
-// MarshalJSONBuf marshal buff to json - template
-func (j *simpleGetCloser) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
- if j == nil {
- buf.WriteString("null")
- return nil
- }
- var err error
- var obj []byte
- _ = obj
- _ = err
- buf.WriteString(`{}`)
- return nil
-}
-
-const (
- ffjtsimpleGetCloserbase = iota
- ffjtsimpleGetClosernosuchkey
-)
-
-// UnmarshalJSON umarshall json - template of ffjson
-func (j *simpleGetCloser) UnmarshalJSON(input []byte) error {
- fs := fflib.NewFFLexer(input)
- return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
-}
-
-// UnmarshalJSONFFLexer fast json unmarshall - template ffjson
-func (j *simpleGetCloser) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
- var err error
- currentKey := ffjtsimpleGetCloserbase
- _ = currentKey
- tok := fflib.FFTok_init
- wantedTok := fflib.FFTok_init
-
-mainparse:
- for {
- tok = fs.Scan()
- // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state))
- if tok == fflib.FFTok_error {
- goto tokerror
- }
-
- switch state {
-
- case fflib.FFParse_map_start:
- if tok != fflib.FFTok_left_bracket {
- wantedTok = fflib.FFTok_left_bracket
- goto wrongtokenerror
- }
- state = fflib.FFParse_want_key
- continue
-
- case fflib.FFParse_after_value:
- if tok == fflib.FFTok_comma {
- state = fflib.FFParse_want_key
- } else if tok == fflib.FFTok_right_bracket {
- goto done
- } else {
- wantedTok = fflib.FFTok_comma
- goto wrongtokenerror
- }
-
- case fflib.FFParse_want_key:
- // json {} ended. goto exit. woo.
- if tok == fflib.FFTok_right_bracket {
- goto done
- }
- if tok != fflib.FFTok_string {
- wantedTok = fflib.FFTok_string
- goto wrongtokenerror
- }
-
- kn := fs.Output.Bytes()
- if len(kn) <= 0 {
- // "" case. hrm.
- currentKey = ffjtsimpleGetClosernosuchkey
- state = fflib.FFParse_want_colon
- goto mainparse
- } else {
- switch kn[0] {
-
- }
-
- currentKey = ffjtsimpleGetClosernosuchkey
- state = fflib.FFParse_want_colon
- goto mainparse
- }
-
- case fflib.FFParse_want_colon:
- if tok != fflib.FFTok_colon {
- wantedTok = fflib.FFTok_colon
- goto wrongtokenerror
- }
- state = fflib.FFParse_want_value
- continue
- case fflib.FFParse_want_value:
-
- if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
- switch currentKey {
-
- case ffjtsimpleGetClosernosuchkey:
- err = fs.SkipField(tok)
- if err != nil {
- return fs.WrapErr(err)
- }
- state = fflib.FFParse_after_value
- goto mainparse
- }
- } else {
- goto wantedvalue
- }
- }
- }
-
-wantedvalue:
- return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
-wrongtokenerror:
- return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
-tokerror:
- if fs.BigError != nil {
- return fs.WrapErr(fs.BigError)
- }
- err = fs.Error.ToError()
- if err != nil {
- return fs.WrapErr(err)
- }
- panic("ffjson-generated: unreachable, please report bug.")
-done:
-
- return nil
-}
diff --git a/vendor/github.com/containers/storage/pkg/archive/archive.go b/vendor/github.com/containers/storage/pkg/archive/archive.go
index 6e2618d1e..d9a2e473c 100644
--- a/vendor/github.com/containers/storage/pkg/archive/archive.go
+++ b/vendor/github.com/containers/storage/pkg/archive/archive.go
@@ -68,6 +68,12 @@ type (
}
)
+const (
+ tarExt = "tar"
+ solaris = "solaris"
+ windows = "windows"
+)
+
// Archiver allows the reuse of most utility functions of this package with a
// pluggable Untar function. To facilitate the passing of specific id mappings
// for untar, an archiver can be created with maps which will then be passed to
@@ -325,15 +331,15 @@ func ReplaceFileTarWrapper(inputTarStream io.ReadCloser, mods map[string]TarModi
func (compression *Compression) Extension() string {
switch *compression {
case Uncompressed:
- return "tar"
+ return tarExt
case Bzip2:
- return "tar.bz2"
+ return tarExt + ".bz2"
case Gzip:
- return "tar.gz"
+ return tarExt + ".gz"
case Xz:
- return "tar.xz"
+ return tarExt + ".xz"
case Zstd:
- return "tar.zst"
+ return tarExt + ".zst"
}
return ""
}
@@ -670,7 +676,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
}
// Lchown is not supported on Windows.
- if Lchown && runtime.GOOS != "windows" {
+ if Lchown && runtime.GOOS != windows {
if chownOpts == nil {
chownOpts = &idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid}
}
diff --git a/vendor/github.com/containers/storage/pkg/archive/changes_unix.go b/vendor/github.com/containers/storage/pkg/archive/changes_unix.go
index 031ec341b..805fb960a 100644
--- a/vendor/github.com/containers/storage/pkg/archive/changes_unix.go
+++ b/vendor/github.com/containers/storage/pkg/archive/changes_unix.go
@@ -13,17 +13,17 @@ import (
func statDifferent(oldStat *system.StatT, oldInfo *FileInfo, newStat *system.StatT, newInfo *FileInfo) bool {
// Don't look at size for dirs, its not a good measure of change
- oldUid, oldGid := oldStat.UID(), oldStat.GID()
+ oldUID, oldGID := oldStat.UID(), oldStat.GID()
uid, gid := newStat.UID(), newStat.GID()
if cuid, cgid, err := newInfo.idMappings.ToContainer(idtools.IDPair{UID: int(uid), GID: int(gid)}); err == nil {
uid = uint32(cuid)
gid = uint32(cgid)
- if oldcuid, oldcgid, err := oldInfo.idMappings.ToContainer(idtools.IDPair{UID: int(oldUid), GID: int(oldGid)}); err == nil {
- oldUid = uint32(oldcuid)
- oldGid = uint32(oldcgid)
+ if oldcuid, oldcgid, err := oldInfo.idMappings.ToContainer(idtools.IDPair{UID: int(oldUID), GID: int(oldGID)}); err == nil {
+ oldUID = uint32(oldcuid)
+ oldGID = uint32(oldcgid)
}
}
- ownerChanged := uid != oldUid || gid != oldGid
+ ownerChanged := uid != oldUID || gid != oldGID
if oldStat.Mode() != newStat.Mode() ||
ownerChanged ||
oldStat.Rdev() != newStat.Rdev() ||
diff --git a/vendor/github.com/containers/storage/pkg/archive/diff.go b/vendor/github.com/containers/storage/pkg/archive/diff.go
index 3c2601dee..78e3d9102 100644
--- a/vendor/github.com/containers/storage/pkg/archive/diff.go
+++ b/vendor/github.com/containers/storage/pkg/archive/diff.go
@@ -68,7 +68,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
// specific or Linux-specific, this warning should be changed to an error
// to cater for the situation where someone does manage to upload a Linux
// image but have it tagged as Windows inadvertently.
- if runtime.GOOS == "windows" {
+ if runtime.GOOS == windows {
if strings.Contains(hdr.Name, ":") {
logrus.Warnf("Windows: Ignoring %s (is this a Linux image?)", hdr.Name)
continue
diff --git a/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go b/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go
index 388eaf9d5..dc2e0c199 100644
--- a/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go
+++ b/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go
@@ -226,8 +226,9 @@ func (p *Pattern) compile() error {
sl := string(os.PathSeparator)
escSL := sl
- if sl == `\` {
- escSL += `\`
+ const bs = `\`
+ if sl == bs {
+ escSL += bs
}
for scan.Peek() != scanner.EOF {
@@ -262,11 +263,11 @@ func (p *Pattern) compile() error {
} else if ch == '.' || ch == '$' {
// Escape some regexp special chars that have no meaning
// in golang's filepath.Match
- regStr += `\` + string(ch)
+ regStr += bs + string(ch)
} else if ch == '\\' {
// escape next char. Note that a trailing \ in the pattern
// will be left alone (but need to escape it)
- if sl == `\` {
+ if sl == bs {
// On windows map "\" to "\\", meaning an escaped backslash,
// and then just continue because filepath.Match on
// Windows doesn't allow escaping at all
@@ -274,9 +275,9 @@ func (p *Pattern) compile() error {
continue
}
if scan.Peek() != scanner.EOF {
- regStr += `\` + string(scan.Next())
+ regStr += bs + string(scan.Next())
} else {
- regStr += `\`
+ regStr += bs
}
} else {
regStr += string(ch)
diff --git a/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go b/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go
index 228c8cf24..302a523f5 100644
--- a/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go
+++ b/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go
@@ -77,14 +77,14 @@ func createLockerForPath(path string, ro bool) (Locker, error) {
// lock locks the lockfile via FCTNL(2) based on the specified type and
// command.
-func (l *lockfile) lock(l_type int16, recursive bool) {
+func (l *lockfile) lock(lType int16, recursive bool) {
lk := unix.Flock_t{
- Type: l_type,
+ Type: lType,
Whence: int16(os.SEEK_SET),
Start: 0,
Len: 0,
}
- switch l_type {
+ switch lType {
case unix.F_RDLCK:
l.rwMutex.RLock()
case unix.F_WRLCK:
@@ -96,7 +96,7 @@ func (l *lockfile) lock(l_type int16, recursive bool) {
l.rwMutex.Lock()
}
default:
- panic(fmt.Sprintf("attempted to acquire a file lock of unrecognized type %d", l_type))
+ panic(fmt.Sprintf("attempted to acquire a file lock of unrecognized type %d", lType))
}
l.stateMutex.Lock()
defer l.stateMutex.Unlock()
@@ -116,7 +116,7 @@ func (l *lockfile) lock(l_type int16, recursive bool) {
time.Sleep(10 * time.Millisecond)
}
}
- l.locktype = l_type
+ l.locktype = lType
l.locked = true
l.recursive = recursive
l.counter++
diff --git a/vendor/github.com/containers/storage/pkg/mount/flags_linux.go b/vendor/github.com/containers/storage/pkg/mount/flags_linux.go
index 0425d0dd6..a5dc5e287 100644
--- a/vendor/github.com/containers/storage/pkg/mount/flags_linux.go
+++ b/vendor/github.com/containers/storage/pkg/mount/flags_linux.go
@@ -82,6 +82,4 @@ const (
// it possible for the kernel to default to relatime or noatime but still
// allow userspace to override it.
STRICTATIME = unix.MS_STRICTATIME
-
- mntDetach = unix.MNT_DETACH
)
diff --git a/vendor/github.com/containers/storage/pkg/mount/mounter_linux.go b/vendor/github.com/containers/storage/pkg/mount/mounter_linux.go
index 39c36d472..de47c7af8 100644
--- a/vendor/github.com/containers/storage/pkg/mount/mounter_linux.go
+++ b/vendor/github.com/containers/storage/pkg/mount/mounter_linux.go
@@ -13,6 +13,8 @@ const (
// broflags is the combination of bind and read only
broflags = unix.MS_BIND | unix.MS_RDONLY
+
+ none = "none"
)
// isremount returns true if either device name or flags identify a remount request, false otherwise.
@@ -20,7 +22,7 @@ func isremount(device string, flags uintptr) bool {
switch {
// We treat device "" and "none" as a remount request to provide compatibility with
// requests that don't explicitly set MS_REMOUNT such as those manipulating bind mounts.
- case flags&unix.MS_REMOUNT != 0, device == "", device == "none":
+ case flags&unix.MS_REMOUNT != 0, device == "", device == none:
return true
default:
return false
diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go
index 272153e51..b84be4424 100644
--- a/vendor/github.com/containers/storage/store.go
+++ b/vendor/github.com/containers/storage/store.go
@@ -2783,18 +2783,24 @@ func (s *store) ContainerParentOwners(id string) ([]int, []int, error) {
}
func (s *store) Layers() ([]Layer, error) {
- var layers []Layer
lstore, err := s.LayerStore()
if err != nil {
return nil, err
}
+ if err := lstore.LoadLocked(); err != nil {
+ return nil, err
+ }
+ layers, err := lstore.Layers()
+ if err != nil {
+ return nil, err
+ }
lstores, err := s.ROLayerStores()
if err != nil {
return nil, err
}
- for _, s := range append([]ROLayerStore{lstore}, lstores...) {
+ for _, s := range lstores {
store := s
store.RLock()
defer store.Unlock()
diff --git a/vendor/github.com/containers/storage/utils.go b/vendor/github.com/containers/storage/utils.go
index 5aa7c0851..28e0a8d6d 100644
--- a/vendor/github.com/containers/storage/utils.go
+++ b/vendor/github.com/containers/storage/utils.go
@@ -69,8 +69,8 @@ func ParseIDMapping(UIDMapSlice, GIDMapSlice []string, subUIDMap, subGIDMap stri
}
// GetRootlessRuntimeDir returns the runtime directory when running as non root
-func GetRootlessRuntimeDir(rootlessUid int) (string, error) {
- path, err := getRootlessRuntimeDir(rootlessUid)
+func GetRootlessRuntimeDir(rootlessUID int) (string, error) {
+ path, err := getRootlessRuntimeDir(rootlessUID)
if err != nil {
return "", err
}
@@ -81,18 +81,18 @@ func GetRootlessRuntimeDir(rootlessUid int) (string, error) {
return path, nil
}
-func getRootlessRuntimeDir(rootlessUid int) (string, error) {
+func getRootlessRuntimeDir(rootlessUID int) (string, error) {
runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
if runtimeDir != "" {
return runtimeDir, nil
}
- tmpDir := fmt.Sprintf("/run/user/%d", rootlessUid)
+ tmpDir := fmt.Sprintf("/run/user/%d", rootlessUID)
st, err := system.Stat(tmpDir)
if err == nil && int(st.UID()) == os.Getuid() && st.Mode()&0700 == 0700 && st.Mode()&0066 == 0000 {
return tmpDir, nil
}
- tmpDir = fmt.Sprintf("%s/%d", os.TempDir(), rootlessUid)
+ tmpDir = fmt.Sprintf("%s/%d", os.TempDir(), rootlessUID)
if err := os.MkdirAll(tmpDir, 0700); err != nil {
logrus.Errorf("failed to create %s: %v", tmpDir, err)
} else {
@@ -111,8 +111,8 @@ func getRootlessRuntimeDir(rootlessUid int) (string, error) {
// getRootlessDirInfo returns the parent path of where the storage for containers and
// volumes will be in rootless mode
-func getRootlessDirInfo(rootlessUid int) (string, string, error) {
- rootlessRuntime, err := GetRootlessRuntimeDir(rootlessUid)
+func getRootlessDirInfo(rootlessUID int) (string, string, error) {
+ rootlessRuntime, err := GetRootlessRuntimeDir(rootlessUID)
if err != nil {
return "", "", err
}
@@ -135,10 +135,10 @@ func getRootlessDirInfo(rootlessUid int) (string, string, error) {
}
// getRootlessStorageOpts returns the storage opts for containers running as non root
-func getRootlessStorageOpts(rootlessUid int) (StoreOptions, error) {
+func getRootlessStorageOpts(rootlessUID int) (StoreOptions, error) {
var opts StoreOptions
- dataDir, rootlessRuntime, err := getRootlessDirInfo(rootlessUid)
+ dataDir, rootlessRuntime, err := getRootlessDirInfo(rootlessUID)
if err != nil {
return opts, err
}
@@ -153,10 +153,6 @@ func getRootlessStorageOpts(rootlessUid int) (StoreOptions, error) {
return opts, nil
}
-type tomlOptionsConfig struct {
- MountProgram string `toml:"mount_program"`
-}
-
func getTomlStorage(storeOptions *StoreOptions) *tomlConfig {
config := new(tomlConfig)
@@ -189,21 +185,21 @@ func DefaultStoreOptionsAutoDetectUID() (StoreOptions, error) {
}
// DefaultStoreOptions returns the default storage ops for containers
-func DefaultStoreOptions(rootless bool, rootlessUid int) (StoreOptions, error) {
+func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
var (
defaultRootlessRunRoot string
defaultRootlessGraphRoot string
err error
)
storageOpts := defaultStoreOptions
- if rootless && rootlessUid != 0 {
- storageOpts, err = getRootlessStorageOpts(rootlessUid)
+ if rootless && rootlessUID != 0 {
+ storageOpts, err = getRootlessStorageOpts(rootlessUID)
if err != nil {
return storageOpts, err
}
}
- storageConf, err := DefaultConfigFile(rootless && rootlessUid != 0)
+ storageConf, err := DefaultConfigFile(rootless && rootlessUID != 0)
if err != nil {
return storageOpts, err
}
@@ -218,7 +214,7 @@ func DefaultStoreOptions(rootless bool, rootlessUid int) (StoreOptions, error) {
ReloadConfigurationFile(storageConf, &storageOpts)
}
- if rootless && rootlessUid != 0 {
+ if rootless && rootlessUID != 0 {
if err == nil {
// If the file did not specify a graphroot or runroot,
// set sane defaults so we don't try and use root-owned
diff --git a/vendor/github.com/klauspost/compress/flate/deflate.go b/vendor/github.com/klauspost/compress/flate/deflate.go
index 20c94f596..d9948ab40 100644
--- a/vendor/github.com/klauspost/compress/flate/deflate.go
+++ b/vendor/github.com/klauspost/compress/flate/deflate.go
@@ -644,7 +644,7 @@ func (d *compressor) init(w io.Writer, level int) (err error) {
d.fill = (*compressor).fillBlock
d.step = (*compressor).store
case level == ConstantCompression:
- d.w.logReusePenalty = uint(4)
+ d.w.logNewTablePenalty = 4
d.window = make([]byte, maxStoreBlockSize)
d.fill = (*compressor).fillBlock
d.step = (*compressor).storeHuff
@@ -652,13 +652,13 @@ func (d *compressor) init(w io.Writer, level int) (err error) {
level = 5
fallthrough
case level >= 1 && level <= 6:
- d.w.logReusePenalty = uint(level + 1)
+ d.w.logNewTablePenalty = 6
d.fast = newFastEnc(level)
d.window = make([]byte, maxStoreBlockSize)
d.fill = (*compressor).fillBlock
d.step = (*compressor).storeFast
case 7 <= level && level <= 9:
- d.w.logReusePenalty = uint(level)
+ d.w.logNewTablePenalty = 10
d.state = &advancedState{}
d.compressionLevel = levels[level]
d.initDeflate()
diff --git a/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go
index dd74ffb87..9feea87a3 100644
--- a/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go
+++ b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go
@@ -93,12 +93,12 @@ type huffmanBitWriter struct {
err error
lastHeader int
// Set between 0 (reused block can be up to 2x the size)
- logReusePenalty uint
- lastHuffMan bool
- bytes [256]byte
- literalFreq [lengthCodesStart + 32]uint16
- offsetFreq [32]uint16
- codegenFreq [codegenCodeCount]uint16
+ logNewTablePenalty uint
+ lastHuffMan bool
+ bytes [256]byte
+ literalFreq [lengthCodesStart + 32]uint16
+ offsetFreq [32]uint16
+ codegenFreq [codegenCodeCount]uint16
// codegen must have an extra space for the final symbol.
codegen [literalCount + offsetCodeCount + 1]uint8
@@ -119,7 +119,7 @@ type huffmanBitWriter struct {
// If lastHuffMan is set, a table for outputting literals has been generated and offsets are invalid.
//
// An incoming block estimates the output size of a new table using a 'fresh' by calculating the
-// optimal size and adding a penalty in 'logReusePenalty'.
+// optimal size and adding a penalty in 'logNewTablePenalty'.
// A Huffman table is not optimal, which is why we add a penalty, and generating a new table
// is slower both for compression and decompression.
@@ -350,6 +350,13 @@ func (w *huffmanBitWriter) headerSize() (size, numCodegens int) {
}
// dynamicSize returns the size of dynamically encoded data in bits.
+func (w *huffmanBitWriter) dynamicReuseSize(litEnc, offEnc *huffmanEncoder) (size int) {
+ size = litEnc.bitLength(w.literalFreq[:]) +
+ offEnc.bitLength(w.offsetFreq[:])
+ return size
+}
+
+// dynamicSize returns the size of dynamically encoded data in bits.
func (w *huffmanBitWriter) dynamicSize(litEnc, offEnc *huffmanEncoder, extraBits int) (size, numCodegens int) {
header, numCodegens := w.headerSize()
size = header +
@@ -451,12 +458,12 @@ func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, n
i := 0
for {
- var codeWord int = int(w.codegen[i])
+ var codeWord = uint32(w.codegen[i])
i++
if codeWord == badCode {
break
}
- w.writeCode(w.codegenEncoding.codes[uint32(codeWord)])
+ w.writeCode(w.codegenEncoding.codes[codeWord])
switch codeWord {
case 16:
@@ -602,14 +609,14 @@ func (w *huffmanBitWriter) writeBlockDynamic(tokens *tokens, eof bool, input []b
var size int
// Check if we should reuse.
if w.lastHeader > 0 {
- // Estimate size for using a new table
+ // Estimate size for using a new table.
+ // Use the previous header size as the best estimate.
newSize := w.lastHeader + tokens.EstimatedBits()
+ newSize += newSize >> w.logNewTablePenalty
// The estimated size is calculated as an optimal table.
// We add a penalty to make it more realistic and re-use a bit more.
- newSize += newSize >> (w.logReusePenalty & 31)
- extra := w.extraBitSize()
- reuseSize, _ := w.dynamicSize(w.literalEncoding, w.offsetEncoding, extra)
+ reuseSize := w.dynamicReuseSize(w.literalEncoding, w.offsetEncoding) + w.extraBitSize()
// Check if a new table is better.
if newSize < reuseSize {
@@ -801,21 +808,30 @@ func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte, sync bool) {
}
// Add everything as literals
- estBits := histogramSize(input, w.literalFreq[:], !eof && !sync) + 15
+ // We have to estimate the header size.
+ // Assume header is around 70 bytes:
+ // https://stackoverflow.com/a/25454430
+ const guessHeaderSizeBits = 70 * 8
+ estBits, estExtra := histogramSize(input, w.literalFreq[:], !eof && !sync)
+ estBits += w.lastHeader + 15
+ if w.lastHeader == 0 {
+ estBits += guessHeaderSizeBits
+ }
+ estBits += estBits >> w.logNewTablePenalty
// Store bytes, if we don't get a reasonable improvement.
ssize, storable := w.storedSize(input)
- if storable && ssize < (estBits+estBits>>4) {
+ if storable && ssize < estBits {
w.writeStoredHeader(len(input), eof)
w.writeBytes(input)
return
}
if w.lastHeader > 0 {
- size, _ := w.dynamicSize(w.literalEncoding, huffOffset, w.lastHeader)
- estBits += estBits >> (w.logReusePenalty)
+ reuseSize := w.literalEncoding.bitLength(w.literalFreq[:256])
+ estBits += estExtra
- if estBits < size {
+ if estBits < reuseSize {
// We owe an EOB
w.writeCode(w.literalEncoding.codes[endBlockMarker])
w.lastHeader = 0
diff --git a/vendor/github.com/klauspost/compress/flate/huffman_code.go b/vendor/github.com/klauspost/compress/flate/huffman_code.go
index 1810c6898..9d8e81ad6 100644
--- a/vendor/github.com/klauspost/compress/flate/huffman_code.go
+++ b/vendor/github.com/klauspost/compress/flate/huffman_code.go
@@ -7,7 +7,6 @@ package flate
import (
"math"
"math/bits"
- "sort"
)
const (
@@ -25,8 +24,6 @@ type huffmanEncoder struct {
codes []hcode
freqcache []literalNode
bitCount [17]int32
- lns byLiteral // stored to avoid repeated allocation in generate
- lfs byFreq // stored to avoid repeated allocation in generate
}
type literalNode struct {
@@ -270,7 +267,7 @@ func (h *huffmanEncoder) assignEncodingAndSize(bitCount []int32, list []literalN
// assigned in literal order (not frequency order).
chunk := list[len(list)-int(bits):]
- h.lns.sort(chunk)
+ sortByLiteral(chunk)
for _, node := range chunk {
h.codes[node.literal] = hcode{code: reverseBits(code, uint8(n)), len: uint16(n)}
code++
@@ -315,7 +312,7 @@ func (h *huffmanEncoder) generate(freq []uint16, maxBits int32) {
}
return
}
- h.lfs.sort(list)
+ sortByFreq(list)
// Get the number of literals for each bit count
bitCount := h.bitCounts(list, maxBits)
@@ -323,59 +320,44 @@ func (h *huffmanEncoder) generate(freq []uint16, maxBits int32) {
h.assignEncodingAndSize(bitCount, list)
}
-type byLiteral []literalNode
-
-func (s *byLiteral) sort(a []literalNode) {
- *s = byLiteral(a)
- sort.Sort(s)
-}
-
-func (s byLiteral) Len() int { return len(s) }
-
-func (s byLiteral) Less(i, j int) bool {
- return s[i].literal < s[j].literal
-}
-
-func (s byLiteral) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-
-type byFreq []literalNode
-
-func (s *byFreq) sort(a []literalNode) {
- *s = byFreq(a)
- sort.Sort(s)
-}
-
-func (s byFreq) Len() int { return len(s) }
-
-func (s byFreq) Less(i, j int) bool {
- if s[i].freq == s[j].freq {
- return s[i].literal < s[j].literal
+func atLeastOne(v float32) float32 {
+ if v < 1 {
+ return 1
}
- return s[i].freq < s[j].freq
+ return v
}
-func (s byFreq) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-
// histogramSize accumulates a histogram of b in h.
// An estimated size in bits is returned.
// Unassigned values are assigned '1' in the histogram.
// len(h) must be >= 256, and h's elements must be all zeroes.
-func histogramSize(b []byte, h []uint16, fill bool) int {
+func histogramSize(b []byte, h []uint16, fill bool) (int, int) {
h = h[:256]
for _, t := range b {
h[t]++
}
- invTotal := 1.0 / float64(len(b))
- shannon := 0.0
- single := math.Ceil(-math.Log2(invTotal))
- for i, v := range h[:] {
- if v > 0 {
- n := float64(v)
- shannon += math.Ceil(-math.Log2(n*invTotal) * n)
- } else if fill {
- shannon += single
- h[i] = 1
+ invTotal := 1.0 / float32(len(b))
+ shannon := float32(0.0)
+ var extra float32
+ if fill {
+ oneBits := atLeastOne(-mFastLog2(invTotal))
+ for i, v := range h[:] {
+ if v > 0 {
+ n := float32(v)
+ shannon += atLeastOne(-mFastLog2(n*invTotal)) * n
+ } else {
+ h[i] = 1
+ extra += oneBits
+ }
+ }
+ } else {
+ for _, v := range h[:] {
+ if v > 0 {
+ n := float32(v)
+ shannon += atLeastOne(-mFastLog2(n*invTotal)) * n
+ }
}
}
- return int(shannon + 0.99)
+
+ return int(shannon + 0.99), int(extra + 0.99)
}
diff --git a/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go b/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go
new file mode 100644
index 000000000..207780299
--- /dev/null
+++ b/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go
@@ -0,0 +1,178 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package flate
+
+// Sort sorts data.
+// It makes one call to data.Len to determine n, and O(n*log(n)) calls to
+// data.Less and data.Swap. The sort is not guaranteed to be stable.
+func sortByFreq(data []literalNode) {
+ n := len(data)
+ quickSortByFreq(data, 0, n, maxDepth(n))
+}
+
+func quickSortByFreq(data []literalNode, a, b, maxDepth int) {
+ for b-a > 12 { // Use ShellSort for slices <= 12 elements
+ if maxDepth == 0 {
+ heapSort(data, a, b)
+ return
+ }
+ maxDepth--
+ mlo, mhi := doPivotByFreq(data, a, b)
+ // Avoiding recursion on the larger subproblem guarantees
+ // a stack depth of at most lg(b-a).
+ if mlo-a < b-mhi {
+ quickSortByFreq(data, a, mlo, maxDepth)
+ a = mhi // i.e., quickSortByFreq(data, mhi, b)
+ } else {
+ quickSortByFreq(data, mhi, b, maxDepth)
+ b = mlo // i.e., quickSortByFreq(data, a, mlo)
+ }
+ }
+ if b-a > 1 {
+ // Do ShellSort pass with gap 6
+ // It could be written in this simplified form cause b-a <= 12
+ for i := a + 6; i < b; i++ {
+ if data[i].freq == data[i-6].freq && data[i].literal < data[i-6].literal || data[i].freq < data[i-6].freq {
+ data[i], data[i-6] = data[i-6], data[i]
+ }
+ }
+ insertionSortByFreq(data, a, b)
+ }
+}
+
+// siftDownByFreq implements the heap property on data[lo, hi).
+// first is an offset into the array where the root of the heap lies.
+func siftDownByFreq(data []literalNode, lo, hi, first int) {
+ root := lo
+ for {
+ child := 2*root + 1
+ if child >= hi {
+ break
+ }
+ if child+1 < hi && (data[first+child].freq == data[first+child+1].freq && data[first+child].literal < data[first+child+1].literal || data[first+child].freq < data[first+child+1].freq) {
+ child++
+ }
+ if data[first+root].freq == data[first+child].freq && data[first+root].literal > data[first+child].literal || data[first+root].freq > data[first+child].freq {
+ return
+ }
+ data[first+root], data[first+child] = data[first+child], data[first+root]
+ root = child
+ }
+}
+func doPivotByFreq(data []literalNode, lo, hi int) (midlo, midhi int) {
+ m := int(uint(lo+hi) >> 1) // Written like this to avoid integer overflow.
+ if hi-lo > 40 {
+ // Tukey's ``Ninther,'' median of three medians of three.
+ s := (hi - lo) / 8
+ medianOfThreeSortByFreq(data, lo, lo+s, lo+2*s)
+ medianOfThreeSortByFreq(data, m, m-s, m+s)
+ medianOfThreeSortByFreq(data, hi-1, hi-1-s, hi-1-2*s)
+ }
+ medianOfThreeSortByFreq(data, lo, m, hi-1)
+
+ // Invariants are:
+ // data[lo] = pivot (set up by ChoosePivot)
+ // data[lo < i < a] < pivot
+ // data[a <= i < b] <= pivot
+ // data[b <= i < c] unexamined
+ // data[c <= i < hi-1] > pivot
+ // data[hi-1] >= pivot
+ pivot := lo
+ a, c := lo+1, hi-1
+
+ for ; a < c && (data[a].freq == data[pivot].freq && data[a].literal < data[pivot].literal || data[a].freq < data[pivot].freq); a++ {
+ }
+ b := a
+ for {
+ for ; b < c && (data[pivot].freq == data[b].freq && data[pivot].literal > data[b].literal || data[pivot].freq > data[b].freq); b++ { // data[b] <= pivot
+ }
+ for ; b < c && (data[pivot].freq == data[c-1].freq && data[pivot].literal < data[c-1].literal || data[pivot].freq < data[c-1].freq); c-- { // data[c-1] > pivot
+ }
+ if b >= c {
+ break
+ }
+ // data[b] > pivot; data[c-1] <= pivot
+ data[b], data[c-1] = data[c-1], data[b]
+ b++
+ c--
+ }
+ // If hi-c<3 then there are duplicates (by property of median of nine).
+ // Let's be a bit more conservative, and set border to 5.
+ protect := hi-c < 5
+ if !protect && hi-c < (hi-lo)/4 {
+ // Lets test some points for equality to pivot
+ dups := 0
+ if data[pivot].freq == data[hi-1].freq && data[pivot].literal > data[hi-1].literal || data[pivot].freq > data[hi-1].freq { // data[hi-1] = pivot
+ data[c], data[hi-1] = data[hi-1], data[c]
+ c++
+ dups++
+ }
+ if data[b-1].freq == data[pivot].freq && data[b-1].literal > data[pivot].literal || data[b-1].freq > data[pivot].freq { // data[b-1] = pivot
+ b--
+ dups++
+ }
+ // m-lo = (hi-lo)/2 > 6
+ // b-lo > (hi-lo)*3/4-1 > 8
+ // ==> m < b ==> data[m] <= pivot
+ if data[m].freq == data[pivot].freq && data[m].literal > data[pivot].literal || data[m].freq > data[pivot].freq { // data[m] = pivot
+ data[m], data[b-1] = data[b-1], data[m]
+ b--
+ dups++
+ }
+ // if at least 2 points are equal to pivot, assume skewed distribution
+ protect = dups > 1
+ }
+ if protect {
+ // Protect against a lot of duplicates
+ // Add invariant:
+ // data[a <= i < b] unexamined
+ // data[b <= i < c] = pivot
+ for {
+ for ; a < b && (data[b-1].freq == data[pivot].freq && data[b-1].literal > data[pivot].literal || data[b-1].freq > data[pivot].freq); b-- { // data[b] == pivot
+ }
+ for ; a < b && (data[a].freq == data[pivot].freq && data[a].literal < data[pivot].literal || data[a].freq < data[pivot].freq); a++ { // data[a] < pivot
+ }
+ if a >= b {
+ break
+ }
+ // data[a] == pivot; data[b-1] < pivot
+ data[a], data[b-1] = data[b-1], data[a]
+ a++
+ b--
+ }
+ }
+ // Swap pivot into middle
+ data[pivot], data[b-1] = data[b-1], data[pivot]
+ return b - 1, c
+}
+
+// Insertion sort
+func insertionSortByFreq(data []literalNode, a, b int) {
+ for i := a + 1; i < b; i++ {
+ for j := i; j > a && (data[j].freq == data[j-1].freq && data[j].literal < data[j-1].literal || data[j].freq < data[j-1].freq); j-- {
+ data[j], data[j-1] = data[j-1], data[j]
+ }
+ }
+}
+
+// quickSortByFreq, loosely following Bentley and McIlroy,
+// ``Engineering a Sort Function,'' SP&E November 1993.
+
+// medianOfThreeSortByFreq moves the median of the three values data[m0], data[m1], data[m2] into data[m1].
+func medianOfThreeSortByFreq(data []literalNode, m1, m0, m2 int) {
+ // sort 3 elements
+ if data[m1].freq == data[m0].freq && data[m1].literal < data[m0].literal || data[m1].freq < data[m0].freq {
+ data[m1], data[m0] = data[m0], data[m1]
+ }
+ // data[m0] <= data[m1]
+ if data[m2].freq == data[m1].freq && data[m2].literal < data[m1].literal || data[m2].freq < data[m1].freq {
+ data[m2], data[m1] = data[m1], data[m2]
+ // data[m0] <= data[m2] && data[m1] < data[m2]
+ if data[m1].freq == data[m0].freq && data[m1].literal < data[m0].literal || data[m1].freq < data[m0].freq {
+ data[m1], data[m0] = data[m0], data[m1]
+ }
+ }
+ // now data[m0] <= data[m1] <= data[m2]
+}
diff --git a/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go b/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go
new file mode 100644
index 000000000..93f1aea10
--- /dev/null
+++ b/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go
@@ -0,0 +1,201 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package flate
+
+// Sort sorts data.
+// It makes one call to data.Len to determine n, and O(n*log(n)) calls to
+// data.Less and data.Swap. The sort is not guaranteed to be stable.
+func sortByLiteral(data []literalNode) {
+ n := len(data)
+ quickSort(data, 0, n, maxDepth(n))
+}
+
+func quickSort(data []literalNode, a, b, maxDepth int) {
+ for b-a > 12 { // Use ShellSort for slices <= 12 elements
+ if maxDepth == 0 {
+ heapSort(data, a, b)
+ return
+ }
+ maxDepth--
+ mlo, mhi := doPivot(data, a, b)
+ // Avoiding recursion on the larger subproblem guarantees
+ // a stack depth of at most lg(b-a).
+ if mlo-a < b-mhi {
+ quickSort(data, a, mlo, maxDepth)
+ a = mhi // i.e., quickSort(data, mhi, b)
+ } else {
+ quickSort(data, mhi, b, maxDepth)
+ b = mlo // i.e., quickSort(data, a, mlo)
+ }
+ }
+ if b-a > 1 {
+ // Do ShellSort pass with gap 6
+ // It could be written in this simplified form cause b-a <= 12
+ for i := a + 6; i < b; i++ {
+ if data[i].literal < data[i-6].literal {
+ data[i], data[i-6] = data[i-6], data[i]
+ }
+ }
+ insertionSort(data, a, b)
+ }
+}
+func heapSort(data []literalNode, a, b int) {
+ first := a
+ lo := 0
+ hi := b - a
+
+ // Build heap with greatest element at top.
+ for i := (hi - 1) / 2; i >= 0; i-- {
+ siftDown(data, i, hi, first)
+ }
+
+ // Pop elements, largest first, into end of data.
+ for i := hi - 1; i >= 0; i-- {
+ data[first], data[first+i] = data[first+i], data[first]
+ siftDown(data, lo, i, first)
+ }
+}
+
+// siftDown implements the heap property on data[lo, hi).
+// first is an offset into the array where the root of the heap lies.
+func siftDown(data []literalNode, lo, hi, first int) {
+ root := lo
+ for {
+ child := 2*root + 1
+ if child >= hi {
+ break
+ }
+ if child+1 < hi && data[first+child].literal < data[first+child+1].literal {
+ child++
+ }
+ if data[first+root].literal > data[first+child].literal {
+ return
+ }
+ data[first+root], data[first+child] = data[first+child], data[first+root]
+ root = child
+ }
+}
+func doPivot(data []literalNode, lo, hi int) (midlo, midhi int) {
+ m := int(uint(lo+hi) >> 1) // Written like this to avoid integer overflow.
+ if hi-lo > 40 {
+ // Tukey's ``Ninther,'' median of three medians of three.
+ s := (hi - lo) / 8
+ medianOfThree(data, lo, lo+s, lo+2*s)
+ medianOfThree(data, m, m-s, m+s)
+ medianOfThree(data, hi-1, hi-1-s, hi-1-2*s)
+ }
+ medianOfThree(data, lo, m, hi-1)
+
+ // Invariants are:
+ // data[lo] = pivot (set up by ChoosePivot)
+ // data[lo < i < a] < pivot
+ // data[a <= i < b] <= pivot
+ // data[b <= i < c] unexamined
+ // data[c <= i < hi-1] > pivot
+ // data[hi-1] >= pivot
+ pivot := lo
+ a, c := lo+1, hi-1
+
+ for ; a < c && data[a].literal < data[pivot].literal; a++ {
+ }
+ b := a
+ for {
+ for ; b < c && data[pivot].literal > data[b].literal; b++ { // data[b] <= pivot
+ }
+ for ; b < c && data[pivot].literal < data[c-1].literal; c-- { // data[c-1] > pivot
+ }
+ if b >= c {
+ break
+ }
+ // data[b] > pivot; data[c-1] <= pivot
+ data[b], data[c-1] = data[c-1], data[b]
+ b++
+ c--
+ }
+ // If hi-c<3 then there are duplicates (by property of median of nine).
+ // Let's be a bit more conservative, and set border to 5.
+ protect := hi-c < 5
+ if !protect && hi-c < (hi-lo)/4 {
+ // Lets test some points for equality to pivot
+ dups := 0
+ if data[pivot].literal > data[hi-1].literal { // data[hi-1] = pivot
+ data[c], data[hi-1] = data[hi-1], data[c]
+ c++
+ dups++
+ }
+ if data[b-1].literal > data[pivot].literal { // data[b-1] = pivot
+ b--
+ dups++
+ }
+ // m-lo = (hi-lo)/2 > 6
+ // b-lo > (hi-lo)*3/4-1 > 8
+ // ==> m < b ==> data[m] <= pivot
+ if data[m].literal > data[pivot].literal { // data[m] = pivot
+ data[m], data[b-1] = data[b-1], data[m]
+ b--
+ dups++
+ }
+ // if at least 2 points are equal to pivot, assume skewed distribution
+ protect = dups > 1
+ }
+ if protect {
+ // Protect against a lot of duplicates
+ // Add invariant:
+ // data[a <= i < b] unexamined
+ // data[b <= i < c] = pivot
+ for {
+ for ; a < b && data[b-1].literal > data[pivot].literal; b-- { // data[b] == pivot
+ }
+ for ; a < b && data[a].literal < data[pivot].literal; a++ { // data[a] < pivot
+ }
+ if a >= b {
+ break
+ }
+ // data[a] == pivot; data[b-1] < pivot
+ data[a], data[b-1] = data[b-1], data[a]
+ a++
+ b--
+ }
+ }
+ // Swap pivot into middle
+ data[pivot], data[b-1] = data[b-1], data[pivot]
+ return b - 1, c
+}
+
+// Insertion sort
+func insertionSort(data []literalNode, a, b int) {
+ for i := a + 1; i < b; i++ {
+ for j := i; j > a && data[j].literal < data[j-1].literal; j-- {
+ data[j], data[j-1] = data[j-1], data[j]
+ }
+ }
+}
+
+// maxDepth returns a threshold at which quicksort should switch
+// to heapsort. It returns 2*ceil(lg(n+1)).
+func maxDepth(n int) int {
+ var depth int
+ for i := n; i > 0; i >>= 1 {
+ depth++
+ }
+ return depth * 2
+}
+
+// medianOfThree moves the median of the three values data[m0], data[m1], data[m2] into data[m1].
+func medianOfThree(data []literalNode, m1, m0, m2 int) {
+ // sort 3 elements
+ if data[m1].literal < data[m0].literal {
+ data[m1], data[m0] = data[m0], data[m1]
+ }
+ // data[m0] <= data[m1]
+ if data[m2].literal < data[m1].literal {
+ data[m2], data[m1] = data[m1], data[m2]
+ // data[m0] <= data[m2] && data[m1] < data[m2]
+ if data[m1].literal < data[m0].literal {
+ data[m1], data[m0] = data[m0], data[m1]
+ }
+ }
+ // now data[m0] <= data[m1] <= data[m2]
+}
diff --git a/vendor/github.com/klauspost/compress/flate/token.go b/vendor/github.com/klauspost/compress/flate/token.go
index b3df0d894..099c0ddbc 100644
--- a/vendor/github.com/klauspost/compress/flate/token.go
+++ b/vendor/github.com/klauspost/compress/flate/token.go
@@ -184,9 +184,7 @@ func (t *tokens) indexTokens(in []token) {
t.Reset()
for _, tok := range in {
if tok < matchType {
- t.tokens[t.n] = tok
- t.litHist[tok]++
- t.n++
+ t.AddLiteral(tok.literal())
continue
}
t.AddMatch(uint32(tok.length()), tok.offset())
@@ -211,43 +209,53 @@ func (t *tokens) AddLiteral(lit byte) {
t.nLits++
}
+// from https://stackoverflow.com/a/28730362
+func mFastLog2(val float32) float32 {
+ ux := int32(math.Float32bits(val))
+ log2 := (float32)(((ux >> 23) & 255) - 128)
+ ux &= -0x7f800001
+ ux += 127 << 23
+ uval := math.Float32frombits(uint32(ux))
+ log2 += ((-0.34484843)*uval+2.02466578)*uval - 0.67487759
+ return log2
+}
+
// EstimatedBits will return an minimum size estimated by an *optimal*
// compression of the block.
// The size of the block
func (t *tokens) EstimatedBits() int {
- shannon := float64(0)
+ shannon := float32(0)
bits := int(0)
nMatches := 0
if t.nLits > 0 {
- invTotal := 1.0 / float64(t.nLits)
+ invTotal := 1.0 / float32(t.nLits)
for _, v := range t.litHist[:] {
if v > 0 {
- n := float64(v)
- shannon += math.Ceil(-math.Log2(n*invTotal) * n)
+ n := float32(v)
+ shannon += -mFastLog2(n*invTotal) * n
}
}
// Just add 15 for EOB
shannon += 15
- for _, v := range t.extraHist[1 : literalCount-256] {
+ for i, v := range t.extraHist[1 : literalCount-256] {
if v > 0 {
- n := float64(v)
- shannon += math.Ceil(-math.Log2(n*invTotal) * n)
- bits += int(lengthExtraBits[v&31]) * int(v)
+ n := float32(v)
+ shannon += -mFastLog2(n*invTotal) * n
+ bits += int(lengthExtraBits[i&31]) * int(v)
nMatches += int(v)
}
}
}
if nMatches > 0 {
- invTotal := 1.0 / float64(nMatches)
- for _, v := range t.offHist[:offsetCodeCount] {
+ invTotal := 1.0 / float32(nMatches)
+ for i, v := range t.offHist[:offsetCodeCount] {
if v > 0 {
- n := float64(v)
- shannon += math.Ceil(-math.Log2(n*invTotal) * n)
- bits += int(offsetExtraBits[v&31]) * int(n)
+ n := float32(v)
+ shannon += -mFastLog2(n*invTotal) * n
+ bits += int(offsetExtraBits[i&31]) * int(v)
}
}
}
-
return int(shannon) + bits
}
diff --git a/vendor/github.com/mattn/go-shellwords/go.mod b/vendor/github.com/mattn/go-shellwords/go.mod
index 8d96dbd5f..927c8c7d6 100644
--- a/vendor/github.com/mattn/go-shellwords/go.mod
+++ b/vendor/github.com/mattn/go-shellwords/go.mod
@@ -1 +1,3 @@
module github.com/mattn/go-shellwords
+
+go 1.13
diff --git a/vendor/github.com/mattn/go-shellwords/shellwords.go b/vendor/github.com/mattn/go-shellwords/shellwords.go
index ff5e73091..ef080861a 100644
--- a/vendor/github.com/mattn/go-shellwords/shellwords.go
+++ b/vendor/github.com/mattn/go-shellwords/shellwords.go
@@ -88,9 +88,17 @@ loop:
backtick += string(r)
} else if got {
if p.ParseEnv {
- buf = replaceEnv(p.Getenv, buf)
+ parser := &Parser{ParseEnv: false, ParseBacktick: false, Position: 0, Dir: p.Dir}
+ strs, err := parser.Parse(replaceEnv(p.Getenv, buf))
+ if err != nil {
+ return nil, err
+ }
+ for _, str := range strs {
+ args = append(args, str)
+ }
+ } else {
+ args = append(args, buf)
}
- args = append(args, buf)
buf = ""
got = false
}
@@ -144,7 +152,7 @@ loop:
}
case '"':
if !singleQuoted && !dollarQuote {
- if doubleQuoted && buf == "" {
+ if doubleQuoted {
got = true
}
doubleQuoted = !doubleQuoted
@@ -152,7 +160,7 @@ loop:
}
case '\'':
if !doubleQuoted && !dollarQuote {
- if singleQuoted && buf == "" {
+ if singleQuoted {
got = true
}
singleQuoted = !singleQuoted
@@ -180,9 +188,17 @@ loop:
if got {
if p.ParseEnv {
- buf = replaceEnv(p.Getenv, buf)
+ parser := &Parser{ParseEnv: false, ParseBacktick: false, Position: 0, Dir: p.Dir}
+ strs, err := parser.Parse(replaceEnv(p.Getenv, buf))
+ if err != nil {
+ return nil, err
+ }
+ for _, str := range strs {
+ args = append(args, str)
+ }
+ } else {
+ args = append(args, buf)
}
- args = append(args, buf)
}
if escaped || singleQuoted || doubleQuoted || backQuote || dollarQuote {
diff --git a/vendor/github.com/mtrmac/gpgme/.appveyor.yml b/vendor/github.com/mtrmac/gpgme/.appveyor.yml
new file mode 100644
index 000000000..2fdc09ab5
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/.appveyor.yml
@@ -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 \ No newline at end of file
diff --git a/vendor/github.com/mtrmac/gpgme/.travis.yml b/vendor/github.com/mtrmac/gpgme/.travis.yml
new file mode 100644
index 000000000..619e33721
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/.travis.yml
@@ -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
diff --git a/vendor/github.com/mtrmac/gpgme/data.go b/vendor/github.com/mtrmac/gpgme/data.go
index eebc97263..eee32c032 100644
--- a/vendor/github.com/mtrmac/gpgme/data.go
+++ b/vendor/github.com/mtrmac/gpgme/data.go
@@ -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
}
diff --git a/vendor/github.com/mtrmac/gpgme/go.mod b/vendor/github.com/mtrmac/gpgme/go.mod
new file mode 100644
index 000000000..3dd09c9fb
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/go.mod
@@ -0,0 +1,3 @@
+module github.com/mtrmac/gpgme
+
+go 1.11
diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.c b/vendor/github.com/mtrmac/gpgme/go_gpgme.c
index b887574e0..00da3ab30 100644
--- a/vendor/github.com/mtrmac/gpgme/go_gpgme.c
+++ b/vendor/github.com/mtrmac/gpgme/go_gpgme.c
@@ -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;
}
diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.h b/vendor/github.com/mtrmac/gpgme/go_gpgme.h
index a3678b127..d4826ab36 100644
--- a/vendor/github.com/mtrmac/gpgme/go_gpgme.h
+++ b/vendor/github.com/mtrmac/gpgme/go_gpgme.h
@@ -6,12 +6,24 @@
#include <gpgme.h>
+/* GPGME_VERSION_NUMBER was introduced in 1.4.0 */
+#if !defined(GPGME_VERSION_NUMBER) || GPGME_VERSION_NUMBER < 0x010402
+typedef off_t gpgme_off_t; /* Introduced in 1.4.2 */
+#endif
+
extern ssize_t gogpgme_readfunc(void *handle, void *buffer, size_t size);
extern ssize_t gogpgme_writefunc(void *handle, void *buffer, size_t size);
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);
diff --git a/vendor/github.com/mtrmac/gpgme/gpgme.go b/vendor/github.com/mtrmac/gpgme/gpgme.go
index 20aad737c..c19b9aebc 100644
--- a/vendor/github.com/mtrmac/gpgme/gpgme.go
+++ b/vendor/github.com/mtrmac/gpgme/gpgme.go
@@ -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 (e *EngineInfo) Next() *EngineInfo {
- if e.info.next == nil {
- return nil
+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 &EngineInfo{info: e.info.next}
+ return res
+}
+
+func (e *EngineInfo) Next() *EngineInfo {
+ 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)
-}
diff --git a/vendor/github.com/mtrmac/gpgme/unset_agent_info.go b/vendor/github.com/mtrmac/gpgme/unset_agent_info.go
new file mode 100644
index 000000000..986aca59f
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/unset_agent_info.go
@@ -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)
+}
diff --git a/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go b/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
new file mode 100644
index 000000000..431ec86d3
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
@@ -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)
+}
diff --git a/vendor/github.com/onsi/ginkgo/.travis.yml b/vendor/github.com/onsi/ginkgo/.travis.yml
index b454d643c..65dc3002b 100644
--- a/vendor/github.com/onsi/ginkgo/.travis.yml
+++ b/vendor/github.com/onsi/ginkgo/.travis.yml
@@ -4,14 +4,22 @@ go:
- 1.13.x
- tip
+cache:
+ directories:
+ - $GOPATH/pkg/mod
+
# allow internal package imports, necessary for forked repositories
go_import_path: github.com/onsi/ginkgo
install:
- - go get -v -t ./...
- - go get golang.org/x/tools/cmd/cover
- - go get github.com/onsi/gomega
- - go install github.com/onsi/ginkgo/ginkgo
+ - GO111MODULE="off" go get -v -t ./...
+ - GO111MODULE="off" go get golang.org/x/tools/cmd/cover
+ - GO111MODULE="off" go get github.com/onsi/gomega
+ - GO111MODULE="off" go install github.com/onsi/ginkgo/ginkgo
- export PATH=$PATH:$HOME/gopath/bin
-script: $HOME/gopath/bin/ginkgo -r --randomizeAllSpecs --randomizeSuites --race --trace && go vet
+script:
+ - GO111MODULE="on" go mod tidy
+ - diff -u <(echo -n) <(git diff go.mod)
+ - diff -u <(echo -n) <(git diff go.sum)
+ - $HOME/gopath/bin/ginkgo -r --randomizeAllSpecs --randomizeSuites --race --trace && go vet
diff --git a/vendor/github.com/onsi/ginkgo/CHANGELOG.md b/vendor/github.com/onsi/ginkgo/CHANGELOG.md
index 96f03ad7c..84b479404 100644
--- a/vendor/github.com/onsi/ginkgo/CHANGELOG.md
+++ b/vendor/github.com/onsi/ginkgo/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 1.12.0
+
+### Features
+- Add module definition (#630) [78916ab]
+
## 1.11.0
### Features
diff --git a/vendor/github.com/onsi/ginkgo/config/config.go b/vendor/github.com/onsi/ginkgo/config/config.go
index 14c82ec3a..949f8130f 100644
--- a/vendor/github.com/onsi/ginkgo/config/config.go
+++ b/vendor/github.com/onsi/ginkgo/config/config.go
@@ -20,7 +20,7 @@ import (
"fmt"
)
-const VERSION = "1.11.0"
+const VERSION = "1.12.0"
type GinkgoConfigType struct {
RandomSeed int64
diff --git a/vendor/github.com/onsi/ginkgo/go.mod b/vendor/github.com/onsi/ginkgo/go.mod
new file mode 100644
index 000000000..15a4ab571
--- /dev/null
+++ b/vendor/github.com/onsi/ginkgo/go.mod
@@ -0,0 +1,9 @@
+module github.com/onsi/ginkgo
+
+require (
+ github.com/hpcloud/tail v1.0.0
+ github.com/onsi/gomega v1.7.1
+ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e
+)
+
+go 1.12
diff --git a/vendor/github.com/onsi/ginkgo/go.sum b/vendor/github.com/onsi/ginkgo/go.sum
new file mode 100644
index 000000000..29adce41a
--- /dev/null
+++ b/vendor/github.com/onsi/ginkgo/go.sum
@@ -0,0 +1,26 @@
+github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/vendor/github.com/onsi/gomega/CHANGELOG.md b/vendor/github.com/onsi/gomega/CHANGELOG.md
index 59ad384aa..3e9b5961b 100644
--- a/vendor/github.com/onsi/gomega/CHANGELOG.md
+++ b/vendor/github.com/onsi/gomega/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 1.9.0
+
+### Features
+- Add ContainElements matcher (#370) [2f57380]
+- Output missing and extra elements in ConsistOf failure message [a31eda7]
+- Document method LargestMatching [7c5a280]
+
## 1.8.1
### Fixes
diff --git a/vendor/github.com/onsi/gomega/gomega_dsl.go b/vendor/github.com/onsi/gomega/gomega_dsl.go
index 4cb94d22f..0ab35bc7a 100644
--- a/vendor/github.com/onsi/gomega/gomega_dsl.go
+++ b/vendor/github.com/onsi/gomega/gomega_dsl.go
@@ -24,7 +24,7 @@ import (
"github.com/onsi/gomega/types"
)
-const GOMEGA_VERSION = "1.8.1"
+const GOMEGA_VERSION = "1.9.0"
const nilFailHandlerPanic = `You are trying to make an assertion, but Gomega's fail handler is nil.
If you're using Ginkgo then you probably forgot to put your assertion in an It().
diff --git a/vendor/github.com/onsi/gomega/matchers.go b/vendor/github.com/onsi/gomega/matchers.go
index 9ec8893cb..11f5b1070 100644
--- a/vendor/github.com/onsi/gomega/matchers.go
+++ b/vendor/github.com/onsi/gomega/matchers.go
@@ -306,6 +306,20 @@ func ConsistOf(elements ...interface{}) types.GomegaMatcher {
}
}
+//ContainElements succeeds if actual contains the passed in elements. The ordering of the elements does not matter.
+//By default ContainElements() uses Equal() to match the elements, however custom matchers can be passed in instead. Here are some examples:
+//
+// Expect([]string{"Foo", "FooBar"}).Should(ContainElements("FooBar"))
+// Expect([]string{"Foo", "FooBar"}).Should(ContainElements(ContainSubstring("Bar"), "Foo"))
+//
+//Actual must be an array, slice or map.
+//For maps, ContainElements searches through the map's values.
+func ContainElements(elements ...interface{}) types.GomegaMatcher {
+ return &matchers.ContainElementsMatcher{
+ Elements: elements,
+ }
+}
+
//HaveKey succeeds if actual is a map with the passed in key.
//By default HaveKey uses Equal() to perform the match, however a
//matcher can be passed in instead:
diff --git a/vendor/github.com/onsi/gomega/matchers/consist_of.go b/vendor/github.com/onsi/gomega/matchers/consist_of.go
index cbbf61802..e453b22d1 100644
--- a/vendor/github.com/onsi/gomega/matchers/consist_of.go
+++ b/vendor/github.com/onsi/gomega/matchers/consist_of.go
@@ -11,7 +11,9 @@ import (
)
type ConsistOfMatcher struct {
- Elements []interface{}
+ Elements []interface{}
+ missingElements []interface{}
+ extraElements []interface{}
}
func (matcher *ConsistOfMatcher) Match(actual interface{}) (success bool, err error) {
@@ -19,44 +21,63 @@ func (matcher *ConsistOfMatcher) Match(actual interface{}) (success bool, err er
return false, fmt.Errorf("ConsistOf matcher expects an array/slice/map. Got:\n%s", format.Object(actual, 1))
}
- elements := matcher.Elements
- if len(matcher.Elements) == 1 && isArrayOrSlice(matcher.Elements[0]) {
- elements = []interface{}{}
- value := reflect.ValueOf(matcher.Elements[0])
- for i := 0; i < value.Len(); i++ {
- elements = append(elements, value.Index(i).Interface())
- }
+ matchers := matchers(matcher.Elements)
+ values := valuesOf(actual)
+
+ bipartiteGraph, err := bipartitegraph.NewBipartiteGraph(values, matchers, neighbours)
+ if err != nil {
+ return false, err
}
- matchers := []interface{}{}
- for _, element := range elements {
- matcher, isMatcher := element.(omegaMatcher)
- if !isMatcher {
- matcher = &EqualMatcher{Expected: element}
- }
- matchers = append(matchers, matcher)
+ edges := bipartiteGraph.LargestMatching()
+ if len(edges) == len(values) && len(edges) == len(matchers) {
+ return true, nil
}
- values := matcher.valuesOf(actual)
+ var missingMatchers []interface{}
+ matcher.extraElements, missingMatchers = bipartiteGraph.FreeLeftRight(edges)
+ matcher.missingElements = equalMatchersToElements(missingMatchers)
- if len(values) != len(matchers) {
- return false, nil
- }
+ return false, nil
+}
- neighbours := func(v, m interface{}) (bool, error) {
- match, err := m.(omegaMatcher).Match(v)
- return match && err == nil, nil
+func neighbours(value, matcher interface{}) (bool, error) {
+ match, err := matcher.(omegaMatcher).Match(value)
+ return match && err == nil, nil
+}
+
+func equalMatchersToElements(matchers []interface{}) (elements []interface{}) {
+ for _, matcher := range matchers {
+ equalMatcher, ok := matcher.(*EqualMatcher)
+ if ok {
+ matcher = equalMatcher.Expected
+ }
+ elements = append(elements, matcher)
}
+ return
+}
- bipartiteGraph, err := bipartitegraph.NewBipartiteGraph(values, matchers, neighbours)
- if err != nil {
- return false, err
+func matchers(expectedElems []interface{}) (matchers []interface{}) {
+ elems := expectedElems
+ if len(expectedElems) == 1 && isArrayOrSlice(expectedElems[0]) {
+ elems = []interface{}{}
+ value := reflect.ValueOf(expectedElems[0])
+ for i := 0; i < value.Len(); i++ {
+ elems = append(elems, value.Index(i).Interface())
+ }
}
- return len(bipartiteGraph.LargestMatching()) == len(values), nil
+ for _, e := range elems {
+ matcher, isMatcher := e.(omegaMatcher)
+ if !isMatcher {
+ matcher = &EqualMatcher{Expected: e}
+ }
+ matchers = append(matchers, matcher)
+ }
+ return
}
-func (matcher *ConsistOfMatcher) valuesOf(actual interface{}) []interface{} {
+func valuesOf(actual interface{}) []interface{} {
value := reflect.ValueOf(actual)
values := []interface{}{}
if isMap(actual) {
@@ -74,7 +95,21 @@ func (matcher *ConsistOfMatcher) valuesOf(actual interface{}) []interface{} {
}
func (matcher *ConsistOfMatcher) FailureMessage(actual interface{}) (message string) {
- return format.Message(actual, "to consist of", matcher.Elements)
+ message = format.Message(actual, "to consist of", matcher.Elements)
+ message = appendMissingElements(message, matcher.missingElements)
+ if len(matcher.extraElements) > 0 {
+ message = fmt.Sprintf("%s\nthe extra elements were\n%s", message,
+ format.Object(matcher.extraElements, 1))
+ }
+ return
+}
+
+func appendMissingElements(message string, missingElements []interface{}) string {
+ if len(missingElements) == 0 {
+ return message
+ }
+ return fmt.Sprintf("%s\nthe missing elements were\n%s", message,
+ format.Object(missingElements, 1))
}
func (matcher *ConsistOfMatcher) NegatedFailureMessage(actual interface{}) (message string) {
diff --git a/vendor/github.com/onsi/gomega/matchers/contain_elements_matcher.go b/vendor/github.com/onsi/gomega/matchers/contain_elements_matcher.go
new file mode 100644
index 000000000..19a9e78f8
--- /dev/null
+++ b/vendor/github.com/onsi/gomega/matchers/contain_elements_matcher.go
@@ -0,0 +1,44 @@
+package matchers
+
+import (
+ "fmt"
+
+ "github.com/onsi/gomega/format"
+ "github.com/onsi/gomega/matchers/support/goraph/bipartitegraph"
+)
+
+type ContainElementsMatcher struct {
+ Elements []interface{}
+ missingElements []interface{}
+}
+
+func (matcher *ContainElementsMatcher) Match(actual interface{}) (success bool, err error) {
+ if !isArrayOrSlice(actual) && !isMap(actual) {
+ return false, fmt.Errorf("ContainElements matcher expects an array/slice/map. Got:\n%s", format.Object(actual, 1))
+ }
+
+ matchers := matchers(matcher.Elements)
+ bipartiteGraph, err := bipartitegraph.NewBipartiteGraph(valuesOf(actual), matchers, neighbours)
+ if err != nil {
+ return false, err
+ }
+
+ edges := bipartiteGraph.LargestMatching()
+ if len(edges) == len(matchers) {
+ return true, nil
+ }
+
+ _, missingMatchers := bipartiteGraph.FreeLeftRight(edges)
+ matcher.missingElements = equalMatchersToElements(missingMatchers)
+
+ return false, nil
+}
+
+func (matcher *ContainElementsMatcher) FailureMessage(actual interface{}) (message string) {
+ message = format.Message(actual, "to contain elements", matcher.Elements)
+ return appendMissingElements(message, matcher.missingElements)
+}
+
+func (matcher *ContainElementsMatcher) NegatedFailureMessage(actual interface{}) (message string) {
+ return format.Message(actual, "not to contain elements", matcher.Elements)
+}
diff --git a/vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph/bipartitegraph.go b/vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph/bipartitegraph.go
index 108f28586..830e30827 100644
--- a/vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph/bipartitegraph.go
+++ b/vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph/bipartitegraph.go
@@ -13,13 +13,13 @@ type BipartiteGraph struct {
func NewBipartiteGraph(leftValues, rightValues []interface{}, neighbours func(interface{}, interface{}) (bool, error)) (*BipartiteGraph, error) {
left := NodeOrderedSet{}
- for i := range leftValues {
- left = append(left, Node{Id: i})
+ for i, v := range leftValues {
+ left = append(left, Node{ID: i, Value: v})
}
right := NodeOrderedSet{}
- for j := range rightValues {
- right = append(right, Node{Id: j + len(left)})
+ for j, v := range rightValues {
+ right = append(right, Node{ID: j + len(left), Value: v})
}
edges := EdgeSet{}
@@ -31,10 +31,26 @@ func NewBipartiteGraph(leftValues, rightValues []interface{}, neighbours func(in
}
if neighbours {
- edges = append(edges, Edge{Node1: left[i], Node2: right[j]})
+ edges = append(edges, Edge{Node1: left[i].ID, Node2: right[j].ID})
}
}
}
return &BipartiteGraph{left, right, edges}, nil
}
+
+// FreeLeftRight returns left node values and right node values
+// of the BipartiteGraph's nodes which are not part of the given edges.
+func (bg *BipartiteGraph) FreeLeftRight(edges EdgeSet) (leftValues, rightValues []interface{}) {
+ for _, node := range bg.Left {
+ if edges.Free(node) {
+ leftValues = append(leftValues, node.Value)
+ }
+ }
+ for _, node := range bg.Right {
+ if edges.Free(node) {
+ rightValues = append(rightValues, node.Value)
+ }
+ }
+ return
+}
diff --git a/vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph/bipartitegraphmatching.go b/vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph/bipartitegraphmatching.go
index 8181f43a4..1c54edd8f 100644
--- a/vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph/bipartitegraphmatching.go
+++ b/vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph/bipartitegraphmatching.go
@@ -1,9 +1,14 @@
package bipartitegraph
-import . "github.com/onsi/gomega/matchers/support/goraph/node"
-import . "github.com/onsi/gomega/matchers/support/goraph/edge"
-import "github.com/onsi/gomega/matchers/support/goraph/util"
-
+import (
+ . "github.com/onsi/gomega/matchers/support/goraph/edge"
+ . "github.com/onsi/gomega/matchers/support/goraph/node"
+ "github.com/onsi/gomega/matchers/support/goraph/util"
+)
+
+// LargestMatching implements the Hopcroft–Karp algorithm taking as input a bipartite graph
+// and outputting a maximum cardinality matching, i.e. a set of as many edges as possible
+// with the property that no two edges share an endpoint.
func (bg *BipartiteGraph) LargestMatching() (matching EdgeSet) {
paths := bg.maximalDisjointSLAPCollection(matching)
@@ -23,7 +28,7 @@ func (bg *BipartiteGraph) maximalDisjointSLAPCollection(matching EdgeSet) (resul
return
}
- used := make(map[Node]bool)
+ used := make(map[int]bool)
for _, u := range guideLayers[len(guideLayers)-1] {
slap, found := bg.findDisjointSLAP(u, matching, guideLayers, used)
@@ -43,7 +48,7 @@ func (bg *BipartiteGraph) findDisjointSLAP(
start Node,
matching EdgeSet,
guideLayers []NodeOrderedSet,
- used map[Node]bool,
+ used map[int]bool,
) ([]Edge, bool) {
return bg.findDisjointSLAPHelper(start, EdgeSet{}, len(guideLayers)-1, matching, guideLayers, used)
}
@@ -54,16 +59,16 @@ func (bg *BipartiteGraph) findDisjointSLAPHelper(
currentLevel int,
matching EdgeSet,
guideLayers []NodeOrderedSet,
- used map[Node]bool,
+ used map[int]bool,
) (EdgeSet, bool) {
- used[currentNode] = true
+ used[currentNode.ID] = true
if currentLevel == 0 {
return currentSLAP, true
}
for _, nextNode := range guideLayers[currentLevel-1] {
- if used[nextNode] {
+ if used[nextNode.ID] {
continue
}
@@ -84,17 +89,17 @@ func (bg *BipartiteGraph) findDisjointSLAPHelper(
currentSLAP = currentSLAP[:len(currentSLAP)-1]
}
- used[currentNode] = false
+ used[currentNode.ID] = false
return nil, false
}
func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers []NodeOrderedSet) {
- used := make(map[Node]bool)
+ used := make(map[int]bool)
currentLayer := NodeOrderedSet{}
for _, node := range bg.Left {
if matching.Free(node) {
- used[node] = true
+ used[node.ID] = true
currentLayer = append(currentLayer, node)
}
}
@@ -113,7 +118,7 @@ func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers [
if util.Odd(len(guideLayers)) {
for _, leftNode := range lastLayer {
for _, rightNode := range bg.Right {
- if used[rightNode] {
+ if used[rightNode.ID] {
continue
}
@@ -123,7 +128,7 @@ func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers [
}
currentLayer = append(currentLayer, rightNode)
- used[rightNode] = true
+ used[rightNode.ID] = true
if matching.Free(rightNode) {
done = true
@@ -133,7 +138,7 @@ func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers [
} else {
for _, rightNode := range lastLayer {
for _, leftNode := range bg.Left {
- if used[leftNode] {
+ if used[leftNode.ID] {
continue
}
@@ -143,7 +148,7 @@ func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers [
}
currentLayer = append(currentLayer, leftNode)
- used[leftNode] = true
+ used[leftNode.ID] = true
}
}
diff --git a/vendor/github.com/onsi/gomega/matchers/support/goraph/edge/edge.go b/vendor/github.com/onsi/gomega/matchers/support/goraph/edge/edge.go
index 4fd15cc06..8c38411b2 100644
--- a/vendor/github.com/onsi/gomega/matchers/support/goraph/edge/edge.go
+++ b/vendor/github.com/onsi/gomega/matchers/support/goraph/edge/edge.go
@@ -3,15 +3,15 @@ package edge
import . "github.com/onsi/gomega/matchers/support/goraph/node"
type Edge struct {
- Node1 Node
- Node2 Node
+ Node1 int
+ Node2 int
}
type EdgeSet []Edge
func (ec EdgeSet) Free(node Node) bool {
for _, e := range ec {
- if e.Node1 == node || e.Node2 == node {
+ if e.Node1 == node.ID || e.Node2 == node.ID {
return false
}
}
@@ -31,7 +31,7 @@ func (ec EdgeSet) Contains(edge Edge) bool {
func (ec EdgeSet) FindByNodes(node1, node2 Node) (Edge, bool) {
for _, e := range ec {
- if (e.Node1 == node1 && e.Node2 == node2) || (e.Node1 == node2 && e.Node2 == node1) {
+ if (e.Node1 == node1.ID && e.Node2 == node2.ID) || (e.Node1 == node2.ID && e.Node2 == node1.ID) {
return e, true
}
}
diff --git a/vendor/github.com/onsi/gomega/matchers/support/goraph/node/node.go b/vendor/github.com/onsi/gomega/matchers/support/goraph/node/node.go
index 800c2ea8c..cd597a2f2 100644
--- a/vendor/github.com/onsi/gomega/matchers/support/goraph/node/node.go
+++ b/vendor/github.com/onsi/gomega/matchers/support/goraph/node/node.go
@@ -1,7 +1,8 @@
package node
type Node struct {
- Id int
+ ID int
+ Value interface{}
}
type NodeOrderedSet []Node
diff --git a/vendor/github.com/vbauerster/mpb/v4/bar_option.go b/vendor/github.com/vbauerster/mpb/v4/bar_option.go
index bb79ac6a4..7fb152562 100644
--- a/vendor/github.com/vbauerster/mpb/v4/bar_option.go
+++ b/vendor/github.com/vbauerster/mpb/v4/bar_option.go
@@ -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()...)
diff --git a/vendor/github.com/vbauerster/mpb/v4/decor/decorator.go b/vendor/github.com/vbauerster/mpb/v4/decor/decorator.go
index 5c0d16880..2271cbbe1 100644
--- a/vendor/github.com/vbauerster/mpb/v4/decor/decorator.go
+++ b/vendor/github.com/vbauerster/mpb/v4/decor/decorator.go
@@ -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
diff --git a/vendor/github.com/vbauerster/mpb/v4/decor/merge.go b/vendor/github.com/vbauerster/mpb/v4/decor/merge.go
index fdf9e107b..723869209 100644
--- a/vendor/github.com/vbauerster/mpb/v4/decor/merge.go
+++ b/vendor/github.com/vbauerster/mpb/v4/decor/merge.go
@@ -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
+ if (d.wc.C & DextraSpace) != 0 {
+ msgLen++
}
- d.wc.wsync <- msgLen - space
+ var total int
+ max := utf8.RuneCountInString(d.placeHolders[0].FormatMsg(""))
+ total += max
+ pw := (msgLen - max) / len(d.placeHolders)
+ rem := (msgLen - max) % len(d.placeHolders)
- max := <-d.wc.wsync
- if (d.wc.C & DextraSpace) != 0 {
- max++
+ 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
}
- return fmt.Sprintf(fmt.Sprintf(d.wc.dynFormat, max+space), msg)
+
+ 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 ""
}
diff --git a/vendor/github.com/vbauerster/mpb/v4/go.mod b/vendor/github.com/vbauerster/mpb/v4/go.mod
index 0c5ce51f1..9e7287d5d 100644
--- a/vendor/github.com/vbauerster/mpb/v4/go.mod
+++ b/vendor/github.com/vbauerster/mpb/v4/go.mod
@@ -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
)
diff --git a/vendor/github.com/vbauerster/mpb/v4/go.sum b/vendor/github.com/vbauerster/mpb/v4/go.sum
index 94a9f1a28..5a1316274 100644
--- a/vendor/github.com/vbauerster/mpb/v4/go.sum
+++ b/vendor/github.com/vbauerster/mpb/v4/go.sum
@@ -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=
diff --git a/vendor/github.com/vbauerster/mpb/v4/proxyreader.go b/vendor/github.com/vbauerster/mpb/v4/proxyreader.go
index 736142412..0e4b51f09 100644
--- a/vendor/github.com/vbauerster/mpb/v4/proxyreader.go
+++ b/vendor/github.com/vbauerster/mpb/v4/proxyreader.go
@@ -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
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 4d96788a8..771e06635 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -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
@@ -138,7 +141,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process
-# github.com/containers/storage v1.15.7
+# github.com/containers/storage v1.15.8
github.com/containers/storage
github.com/containers/storage/drivers
github.com/containers/storage/drivers/aufs
@@ -312,7 +315,7 @@ github.com/inconshreveable/mousetrap
github.com/ishidawataru/sctp
# github.com/json-iterator/go v1.1.9
github.com/json-iterator/go
-# github.com/klauspost/compress v1.9.7
+# github.com/klauspost/compress v1.9.8
github.com/klauspost/compress/flate
github.com/klauspost/compress/fse
github.com/klauspost/compress/huff0
@@ -323,7 +326,7 @@ github.com/klauspost/compress/zstd/internal/xxhash
github.com/klauspost/pgzip
# github.com/konsorten/go-windows-terminal-sequences v1.0.2
github.com/konsorten/go-windows-terminal-sequences
-# github.com/mattn/go-shellwords v1.0.7
+# github.com/mattn/go-shellwords v1.0.9
github.com/mattn/go-shellwords
# github.com/matttproud/golang_protobuf_extensions v1.0.1
github.com/matttproud/golang_protobuf_extensions/pbutil
@@ -337,9 +340,9 @@ 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.2
github.com/mtrmac/gpgme
-# github.com/onsi/ginkgo v1.11.0
+# github.com/onsi/ginkgo v1.12.0
github.com/onsi/ginkgo
github.com/onsi/ginkgo/config
github.com/onsi/ginkgo/extensions/table
@@ -366,7 +369,7 @@ github.com/onsi/ginkgo/reporters/stenographer
github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable
github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty
github.com/onsi/ginkgo/types
-# github.com/onsi/gomega v1.8.1
+# github.com/onsi/gomega v1.9.0
github.com/onsi/gomega
github.com/onsi/gomega/format
github.com/onsi/gomega/gbytes
@@ -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