diff --git a/cmd/skopeo/copy.go b/cmd/skopeo/copy.go index 68ea5a2e..3ffce4db 100644 --- a/cmd/skopeo/copy.go +++ b/cmd/skopeo/copy.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "strings" + commonFlag "github.com/containers/common/pkg/flag" "github.com/containers/common/pkg/retry" "github.com/containers/image/v5/copy" "github.com/containers/image/v5/docker/reference" @@ -24,16 +25,16 @@ type copyOptions struct { srcImage *imageOptions destImage *imageDestOptions retryOpts *retry.RetryOptions - additionalTags []string // For docker-archive: destinations, in addition to the name:tag specified as destination, also add these - removeSignatures bool // Do not copy signatures from the source image - signByFingerprint string // Sign the image using a GPG key with the specified fingerprint - digestFile string // Write digest to this file - format optionalString // Force conversion of the image to a specified format - quiet bool // Suppress output information when copying images - all bool // Copy all of the images if the source is a list - encryptLayer []int // The list of layers to encrypt - encryptionKeys []string // Keys needed to encrypt the image - decryptionKeys []string // Keys needed to decrypt the image + additionalTags []string // For docker-archive: destinations, in addition to the name:tag specified as destination, also add these + removeSignatures bool // Do not copy signatures from the source image + signByFingerprint string // Sign the image using a GPG key with the specified fingerprint + digestFile string // Write digest to this file + format commonFlag.OptionalString // Force conversion of the image to a specified format + quiet bool // Suppress output information when copying images + all bool // Copy all of the images if the source is a list + encryptLayer []int // The list of layers to encrypt + encryptionKeys []string // Keys needed to encrypt the image + decryptionKeys []string // Keys needed to decrypt the image } func copyCmd(global *globalOptions) *cobra.Command { @@ -74,7 +75,7 @@ See skopeo(1) section "IMAGE NAMES" for the expected format flags.BoolVar(&opts.removeSignatures, "remove-signatures", false, "Do not copy signatures from SOURCE-IMAGE") flags.StringVar(&opts.signByFingerprint, "sign-by", "", "Sign the image using a GPG key with the specified `FINGERPRINT`") flags.StringVar(&opts.digestFile, "digestfile", "", "Write the digest of the pushed image to the specified file") - flags.VarP(newOptionalStringValue(&opts.format), "format", "f", `MANIFEST TYPE (oci, v2s1, or v2s2) to use in the destination (default is manifest type of source, with fallbacks)`) + flags.VarP(commonFlag.NewOptionalStringValue(&opts.format), "format", "f", `MANIFEST TYPE (oci, v2s1, or v2s2) to use in the destination (default is manifest type of source, with fallbacks)`) flags.StringSliceVar(&opts.encryptionKeys, "encryption-key", []string{}, "*Experimental* key with the encryption protocol to use needed to encrypt the image (e.g. jwe:/path/to/key.pem)") flags.IntSliceVar(&opts.encryptLayer, "encrypt-layer", []int{}, "*Experimental* the 0-indexed layer indices, with support for negative indexing (e.g. 0 is the first layer, -1 is the last layer)") flags.StringSliceVar(&opts.decryptionKeys, "decryption-key", []string{}, "*Experimental* key needed to decrypt the image") @@ -117,8 +118,8 @@ func (opts *copyOptions) run(args []string, stdout io.Writer) error { } var manifestType string - if opts.format.present { - manifestType, err = parseManifestFormat(opts.format.value) + if opts.format.Present() { + manifestType, err = parseManifestFormat(opts.format.Value()) if err != nil { return err } diff --git a/cmd/skopeo/flag_test.go b/cmd/skopeo/flag_test.go deleted file mode 100644 index 6c132f86..00000000 --- a/cmd/skopeo/flag_test.go +++ /dev/null @@ -1,222 +0,0 @@ -package main - -import ( - "testing" - - "github.com/spf13/cobra" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestOptionalBoolSet(t *testing.T) { - for _, c := range []struct { - input string - accepted bool - value bool - }{ - // Valid inputs documented for strconv.ParseBool == flag.BoolVar - {"1", true, true}, - {"t", true, true}, - {"T", true, true}, - {"TRUE", true, true}, - {"true", true, true}, - {"True", true, true}, - {"0", true, false}, - {"f", true, false}, - {"F", true, false}, - {"FALSE", true, false}, - {"false", true, false}, - {"False", true, false}, - // A few invalid inputs - {"", false, false}, - {"yes", false, false}, - {"no", false, false}, - {"2", false, false}, - } { - var ob optionalBool - v := internalNewOptionalBoolValue(&ob) - require.False(t, ob.present) - err := v.Set(c.input) - if c.accepted { - assert.NoError(t, err, c.input) - assert.Equal(t, c.value, ob.value) - } else { - assert.Error(t, err, c.input) - assert.False(t, ob.present) // Just to be extra paranoid. - } - } - - // Nothing actually explicitly says that .Set() is never called when the flag is not present on the command line; - // so, check that it is not being called, at least in the straightforward case (it's not possible to test that it - // is not called in any possible situation). - var globalOB, commandOB optionalBool - actionRun := false - app := &cobra.Command{ - Use: "app", - } - optionalBoolFlag(app.PersistentFlags(), &globalOB, "global-OB", "") - cmd := &cobra.Command{ - Use: "cmd", - RunE: func(cmd *cobra.Command, args []string) error { - assert.False(t, globalOB.present) - assert.False(t, commandOB.present) - actionRun = true - return nil - }, - } - optionalBoolFlag(cmd.Flags(), &commandOB, "command-OB", "") - app.AddCommand(cmd) - app.SetArgs([]string{"cmd"}) - err := app.Execute() - require.NoError(t, err) - assert.True(t, actionRun) -} - -func TestOptionalBoolString(t *testing.T) { - for _, c := range []struct { - input optionalBool - expected string - }{ - {optionalBool{present: true, value: true}, "true"}, - {optionalBool{present: true, value: false}, "false"}, - {optionalBool{present: false, value: true}, ""}, - {optionalBool{present: false, value: false}, ""}, - } { - var ob optionalBool - v := internalNewOptionalBoolValue(&ob) - ob = c.input - res := v.String() - assert.Equal(t, c.expected, res) - } -} - -func TestOptionalBoolIsBoolFlag(t *testing.T) { - // IsBoolFlag means that the argument value must either be part of the same argument, with =; - // if there is no =, the value is set to true. - // This differs form other flags, where the argument is required and may be either separated with = or supplied in the next argument. - for _, c := range []struct { - input []string - expectedOB optionalBool - expectedArgs []string - }{ - {[]string{"1", "2"}, optionalBool{present: false}, []string{"1", "2"}}, // Flag not present - {[]string{"--OB=true", "1", "2"}, optionalBool{present: true, value: true}, []string{"1", "2"}}, // --OB=true - {[]string{"--OB=false", "1", "2"}, optionalBool{present: true, value: false}, []string{"1", "2"}}, // --OB=false - {[]string{"--OB", "true", "1", "2"}, optionalBool{present: true, value: true}, []string{"true", "1", "2"}}, // --OB true - {[]string{"--OB", "false", "1", "2"}, optionalBool{present: true, value: true}, []string{"false", "1", "2"}}, // --OB false - } { - var ob optionalBool - actionRun := false - app := &cobra.Command{Use: "app"} - cmd := &cobra.Command{ - Use: "cmd", - RunE: func(cmd *cobra.Command, args []string) error { - assert.Equal(t, c.expectedOB, ob) - assert.Equal(t, c.expectedArgs, args) - actionRun = true - return nil - }, - } - optionalBoolFlag(cmd.Flags(), &ob, "OB", "") - app.AddCommand(cmd) - - app.SetArgs(append([]string{"cmd"}, c.input...)) - err := app.Execute() - require.NoError(t, err) - assert.True(t, actionRun) - } -} - -func TestOptionalStringSet(t *testing.T) { - // Really just a smoke test, but differentiating between not present and empty. - for _, c := range []string{"", "hello"} { - var os optionalString - v := newOptionalStringValue(&os) - require.False(t, os.present) - err := v.Set(c) - assert.NoError(t, err, c) - assert.Equal(t, c, os.value) - } - - // Nothing actually explicitly says that .Set() is never called when the flag is not present on the command line; - // so, check that it is not being called, at least in the straightforward case (it's not possible to test that it - // is not called in any possible situation). - var globalOS, commandOS optionalString - actionRun := false - app := &cobra.Command{ - Use: "app", - } - app.PersistentFlags().Var(newOptionalStringValue(&globalOS), "global-OS", "") - cmd := &cobra.Command{ - Use: "cmd", - RunE: func(cmd *cobra.Command, args []string) error { - assert.False(t, globalOS.present) - assert.False(t, commandOS.present) - actionRun = true - return nil - }, - } - cmd.Flags().Var(newOptionalStringValue(&commandOS), "command-OS", "") - app.AddCommand(cmd) - app.SetArgs([]string{"cmd"}) - err := app.Execute() - require.NoError(t, err) - assert.True(t, actionRun) -} - -func TestOptionalStringString(t *testing.T) { - for _, c := range []struct { - input optionalString - expected string - }{ - {optionalString{present: true, value: "hello"}, "hello"}, - {optionalString{present: true, value: ""}, ""}, - {optionalString{present: false, value: "hello"}, ""}, - {optionalString{present: false, value: ""}, ""}, - } { - var os optionalString - v := newOptionalStringValue(&os) - os = c.input - res := v.String() - assert.Equal(t, c.expected, res) - } -} - -func TestOptionalStringIsBoolFlag(t *testing.T) { - // NOTE: optionalStringValue does not implement IsBoolFlag! - // IsBoolFlag means that the argument value must either be part of the same argument, with =; - // if there is no =, the value is set to true. - // This differs form other flags, where the argument is required and may be either separated with = or supplied in the next argument. - for _, c := range []struct { - input []string - expectedOS optionalString - expectedArgs []string - }{ - {[]string{"1", "2"}, optionalString{present: false}, []string{"1", "2"}}, // Flag not present - {[]string{"--OS=hello", "1", "2"}, optionalString{present: true, value: "hello"}, []string{"1", "2"}}, // --OS=true - {[]string{"--OS=", "1", "2"}, optionalString{present: true, value: ""}, []string{"1", "2"}}, // --OS=false - {[]string{"--OS", "hello", "1", "2"}, optionalString{present: true, value: "hello"}, []string{"1", "2"}}, // --OS true - {[]string{"--OS", "", "1", "2"}, optionalString{present: true, value: ""}, []string{"1", "2"}}, // --OS false - } { - var os optionalString - actionRun := false - app := &cobra.Command{ - Use: "app", - } - cmd := &cobra.Command{ - Use: "cmd", - RunE: func(cmd *cobra.Command, args []string) error { - assert.Equal(t, c.expectedOS, os) - assert.Equal(t, c.expectedArgs, args) - actionRun = true - return nil - }, - } - cmd.Flags().Var(newOptionalStringValue(&os), "OS", "") - app.AddCommand(cmd) - app.SetArgs(append([]string{"cmd"}, c.input...)) - err := app.Execute() - require.NoError(t, err) - assert.True(t, actionRun) - } -} diff --git a/cmd/skopeo/login.go b/cmd/skopeo/login.go index 0f0f6c26..efaf3539 100644 --- a/cmd/skopeo/login.go +++ b/cmd/skopeo/login.go @@ -5,6 +5,7 @@ import ( "os" "github.com/containers/common/pkg/auth" + commonFlag "github.com/containers/common/pkg/flag" "github.com/containers/image/v5/types" "github.com/spf13/cobra" ) @@ -12,7 +13,7 @@ import ( type loginOptions struct { global *globalOptions loginOpts auth.LoginOptions - tlsVerify optionalBool + tlsVerify commonFlag.OptionalBool } func loginCmd(global *globalOptions) *cobra.Command { @@ -28,7 +29,7 @@ func loginCmd(global *globalOptions) *cobra.Command { } adjustUsage(cmd) flags := cmd.Flags() - optionalBoolFlag(flags, &opts.tlsVerify, "tls-verify", "require HTTPS and verify certificates when accessing the registry") + commonFlag.OptionalBoolFlag(flags, &opts.tlsVerify, "tls-verify", "require HTTPS and verify certificates when accessing the registry") flags.AddFlagSet(auth.GetLoginFlags(&opts.loginOpts)) return cmd } @@ -40,8 +41,8 @@ func (opts *loginOptions) run(args []string, stdout io.Writer) error { opts.loginOpts.Stdin = os.Stdin opts.loginOpts.AcceptRepositories = true sys := opts.global.newSystemContext() - if opts.tlsVerify.present { - sys.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.tlsVerify.value) + if opts.tlsVerify.Present() { + sys.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.tlsVerify.Value()) } return auth.Login(ctx, sys, &opts.loginOpts, args) } diff --git a/cmd/skopeo/logout.go b/cmd/skopeo/logout.go index 3d49f60c..a694d57c 100644 --- a/cmd/skopeo/logout.go +++ b/cmd/skopeo/logout.go @@ -4,6 +4,7 @@ import ( "io" "github.com/containers/common/pkg/auth" + commonFlag "github.com/containers/common/pkg/flag" "github.com/containers/image/v5/types" "github.com/spf13/cobra" ) @@ -11,7 +12,7 @@ import ( type logoutOptions struct { global *globalOptions logoutOpts auth.LogoutOptions - tlsVerify optionalBool + tlsVerify commonFlag.OptionalBool } func logoutCmd(global *globalOptions) *cobra.Command { @@ -27,7 +28,7 @@ func logoutCmd(global *globalOptions) *cobra.Command { } adjustUsage(cmd) flags := cmd.Flags() - optionalBoolFlag(flags, &opts.tlsVerify, "tls-verify", "require HTTPS and verify certificates when accessing the registry") + commonFlag.OptionalBoolFlag(flags, &opts.tlsVerify, "tls-verify", "require HTTPS and verify certificates when accessing the registry") flags.AddFlagSet(auth.GetLogoutFlags(&opts.logoutOpts)) return cmd } @@ -36,8 +37,8 @@ func (opts *logoutOptions) run(args []string, stdout io.Writer) error { opts.logoutOpts.Stdout = stdout opts.logoutOpts.AcceptRepositories = true sys := opts.global.newSystemContext() - if opts.tlsVerify.present { - sys.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.tlsVerify.value) + if opts.tlsVerify.Present() { + sys.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.tlsVerify.Value()) } return auth.Logout(sys, &opts.logoutOpts, args) } diff --git a/cmd/skopeo/main.go b/cmd/skopeo/main.go index d5d2c69b..d9a4b2ea 100644 --- a/cmd/skopeo/main.go +++ b/cmd/skopeo/main.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + commonFlag "github.com/containers/common/pkg/flag" "github.com/containers/image/v5/signature" "github.com/containers/image/v5/types" "github.com/containers/skopeo/version" @@ -20,17 +21,17 @@ var gitCommit = "" var defaultUserAgent = "skopeo/" + version.Version type globalOptions struct { - debug bool // Enable debug output - tlsVerify optionalBool // Require HTTPS and verify certificates (for docker: and docker-daemon:) - policyPath string // Path to a signature verification policy file - insecurePolicy bool // Use an "allow everything" signature verification policy - registriesDirPath string // Path to a "registries.d" registry configuration directory - overrideArch string // Architecture to use for choosing images, instead of the runtime one - overrideOS string // OS to use for choosing images, instead of the runtime one - overrideVariant string // Architecture variant to use for choosing images, instead of the runtime one - commandTimeout time.Duration // Timeout for the command execution - registriesConfPath string // Path to the "registries.conf" file - tmpDir string // Path to use for big temporary files + debug bool // Enable debug output + tlsVerify commonFlag.OptionalBool // Require HTTPS and verify certificates (for docker: and docker-daemon:) + policyPath string // Path to a signature verification policy file + insecurePolicy bool // Use an "allow everything" signature verification policy + registriesDirPath string // Path to a "registries.d" registry configuration directory + overrideArch string // Architecture to use for choosing images, instead of the runtime one + overrideOS string // OS to use for choosing images, instead of the runtime one + overrideVariant string // Architecture variant to use for choosing images, instead of the runtime one + commandTimeout time.Duration // Timeout for the command execution + registriesConfPath string // Path to the "registries.conf" file + tmpDir string // Path to use for big temporary files } // createApp returns a cobra.Command, and the underlying globalOptions object, to be run or tested. @@ -78,7 +79,7 @@ func createApp() (*cobra.Command, *globalOptions) { logrus.Fatal("unable to mark registries-conf flag as hidden") } rootCommand.PersistentFlags().StringVar(&opts.tmpDir, "tmpdir", "", "directory used to store temporary files") - flag := optionalBoolFlag(rootCommand.Flags(), &opts.tlsVerify, "tls-verify", "Require HTTPS and verify certificates when accessing the registry") + flag := commonFlag.OptionalBoolFlag(rootCommand.Flags(), &opts.tlsVerify, "tls-verify", "Require HTTPS and verify certificates when accessing the registry") flag.Hidden = true rootCommand.AddCommand( copyCmd(&opts), @@ -103,7 +104,7 @@ func (opts *globalOptions) before(cmd *cobra.Command) error { if opts.debug { logrus.SetLevel(logrus.DebugLevel) } - if opts.tlsVerify.present { + if opts.tlsVerify.Present() { logrus.Warn("'--tls-verify' is deprecated, please set this on the specific subcommand") } return nil @@ -160,8 +161,8 @@ func (opts *globalOptions) newSystemContext() *types.SystemContext { DockerRegistryUserAgent: defaultUserAgent, } // DEPRECATED: We support this for backward compatibility, but override it if a per-image flag is provided. - if opts.tlsVerify.present { - ctx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.tlsVerify.value) + if opts.tlsVerify.Present() { + ctx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.tlsVerify.Value()) } return ctx } diff --git a/cmd/skopeo/sync.go b/cmd/skopeo/sync.go index 06949550..ef688fd2 100644 --- a/cmd/skopeo/sync.go +++ b/cmd/skopeo/sync.go @@ -11,6 +11,7 @@ import ( "regexp" "strings" + commonFlag "github.com/containers/common/pkg/flag" "github.com/containers/common/pkg/retry" "github.com/containers/image/v5/copy" "github.com/containers/image/v5/directory" @@ -32,14 +33,14 @@ type syncOptions struct { srcImage *imageOptions // Source image options destImage *imageDestOptions // Destination image options retryOpts *retry.RetryOptions - removeSignatures bool // Do not copy signatures from the source image - signByFingerprint string // Sign the image using a GPG key with the specified fingerprint - format optionalString // Force conversion of the image to a specified format - source string // Source repository name - destination string // Destination registry name - scoped bool // When true, namespace copied images at destination using the source repository name - all bool // Copy all of the images if an image in the source is a list - keepGoing bool // Whether or not to abort the sync if there are any errors during syncing the images + removeSignatures bool // Do not copy signatures from the source image + signByFingerprint string // Sign the image using a GPG key with the specified fingerprint + format commonFlag.OptionalString // Force conversion of the image to a specified format + source string // Source repository name + destination string // Destination registry name + scoped bool // When true, namespace copied images at destination using the source repository name + all bool // Copy all of the images if an image in the source is a list + keepGoing bool // Whether or not to abort the sync if there are any errors during syncing the images } // repoDescriptor contains information of a single repository used as a sync source. @@ -100,7 +101,7 @@ See skopeo-sync(1) for details. flags := cmd.Flags() flags.BoolVar(&opts.removeSignatures, "remove-signatures", false, "Do not copy signatures from SOURCE images") flags.StringVar(&opts.signByFingerprint, "sign-by", "", "Sign the image using a GPG key with the specified `FINGERPRINT`") - flags.VarP(newOptionalStringValue(&opts.format), "format", "f", `MANIFEST TYPE (oci, v2s1, or v2s2) to use when syncing image(s) to a destination (default is manifest type of source, with fallbacks)`) + flags.VarP(commonFlag.NewOptionalStringValue(&opts.format), "format", "f", `MANIFEST TYPE (oci, v2s1, or v2s2) to use when syncing image(s) to a destination (default is manifest type of source, with fallbacks)`) flags.StringVarP(&opts.source, "src", "s", "", "SOURCE transport type") flags.StringVarP(&opts.destination, "dest", "d", "", "DESTINATION transport type") flags.BoolVar(&opts.scoped, "scoped", false, "Images at DESTINATION are prefix using the full source image path as scope") @@ -545,8 +546,8 @@ func (opts *syncOptions) run(args []string, stdout io.Writer) error { } var manifestType string - if opts.format.present { - manifestType, err = parseManifestFormat(opts.format.value) + if opts.format.Present() { + manifestType, err = parseManifestFormat(opts.format.Value()) if err != nil { return err } diff --git a/cmd/skopeo/utils.go b/cmd/skopeo/utils.go index 3cb61aac..15450562 100644 --- a/cmd/skopeo/utils.go +++ b/cmd/skopeo/utils.go @@ -7,6 +7,7 @@ import ( "os" "strings" + commonFlag "github.com/containers/common/pkg/flag" "github.com/containers/common/pkg/retry" "github.com/containers/image/v5/manifest" "github.com/containers/image/v5/pkg/compression" @@ -45,7 +46,7 @@ func commandAction(handler func(args []string, stdout io.Writer) error) func(cmd // whether or not the value actually ends up being used. // DO NOT ADD ANY NEW USES OF THIS; just call dockerImageFlags with an appropriate, possibly empty, flagPrefix. type deprecatedTLSVerifyOption struct { - tlsVerify optionalBool // FIXME FIXME: Warn if this is used, or even if it is ignored. + tlsVerify commonFlag.OptionalBool // FIXME FIXME: Warn if this is used, or even if it is ignored. } // warnIfUsed warns if tlsVerify was set by the user, and suggests alternatives (which should @@ -53,7 +54,7 @@ type deprecatedTLSVerifyOption struct { // Every user should call this as part of handling the CLI, whether or not the value actually // ends up being used. func (opts *deprecatedTLSVerifyOption) warnIfUsed(alternatives []string) { - if opts.tlsVerify.present { + if opts.tlsVerify.Present() { logrus.Warnf("'--tls-verify' is deprecated, instead use: %s", strings.Join(alternatives, ", ")) } } @@ -63,7 +64,7 @@ func (opts *deprecatedTLSVerifyOption) warnIfUsed(alternatives []string) { func deprecatedTLSVerifyFlags() (pflag.FlagSet, *deprecatedTLSVerifyOption) { opts := deprecatedTLSVerifyOption{} fs := pflag.FlagSet{} - flag := optionalBoolFlag(&fs, &opts.tlsVerify, "tls-verify", "require HTTPS and verify certificates when accessing the container registry") + flag := commonFlag.OptionalBoolFlag(&fs, &opts.tlsVerify, "tls-verify", "require HTTPS and verify certificates when accessing the container registry") flag.Hidden = true return fs, &opts } @@ -89,13 +90,13 @@ type dockerImageOptions struct { global *globalOptions // May be shared across several imageOptions instances. shared *sharedImageOptions // May be shared across several imageOptions instances. deprecatedTLSVerify *deprecatedTLSVerifyOption // May be shared across several imageOptions instances, or nil. - authFilePath optionalString // Path to a */containers/auth.json (prefixed version to override shared image option). - credsOption optionalString // username[:password] for accessing a registry - userName optionalString // username for accessing a registry - password optionalString // password for accessing a registry - registryToken optionalString // token to be used directly as a Bearer token when accessing the registry + authFilePath commonFlag.OptionalString // Path to a */containers/auth.json (prefixed version to override shared image option). + credsOption commonFlag.OptionalString // username[:password] for accessing a registry + userName commonFlag.OptionalString // username for accessing a registry + password commonFlag.OptionalString // password for accessing a registry + registryToken commonFlag.OptionalString // token to be used directly as a Bearer token when accessing the registry dockerCertPath string // A directory using Docker-like *.{crt,cert,key} files for connecting to a registry or a daemon - tlsVerify optionalBool // Require HTTPS and verify certificates (for docker: and docker-daemon:) + tlsVerify commonFlag.OptionalBool // Require HTTPS and verify certificates (for docker: and docker-daemon:) noCreds bool // Access the registry anonymously } @@ -121,20 +122,20 @@ func dockerImageFlags(global *globalOptions, shared *sharedImageOptions, depreca fs := pflag.FlagSet{} if flagPrefix != "" { // the non-prefixed flag is handled by a shared flag. - fs.Var(newOptionalStringValue(&flags.authFilePath), flagPrefix+"authfile", "path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json") + fs.Var(commonFlag.NewOptionalStringValue(&flags.authFilePath), flagPrefix+"authfile", "path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json") } - fs.Var(newOptionalStringValue(&flags.credsOption), flagPrefix+"creds", "Use `USERNAME[:PASSWORD]` for accessing the registry") - fs.Var(newOptionalStringValue(&flags.userName), flagPrefix+"username", "Username for accessing the registry") - fs.Var(newOptionalStringValue(&flags.password), flagPrefix+"password", "Password for accessing the registry") + fs.Var(commonFlag.NewOptionalStringValue(&flags.credsOption), flagPrefix+"creds", "Use `USERNAME[:PASSWORD]` for accessing the registry") + fs.Var(commonFlag.NewOptionalStringValue(&flags.userName), flagPrefix+"username", "Username for accessing the registry") + fs.Var(commonFlag.NewOptionalStringValue(&flags.password), flagPrefix+"password", "Password for accessing the registry") if credsOptionAlias != "" { // This is horribly ugly, but we need to support the old option forms of (skopeo copy) for compatibility. // Don't add any more cases like this. - f := fs.VarPF(newOptionalStringValue(&flags.credsOption), credsOptionAlias, "", "Use `USERNAME[:PASSWORD]` for accessing the registry") + f := fs.VarPF(commonFlag.NewOptionalStringValue(&flags.credsOption), credsOptionAlias, "", "Use `USERNAME[:PASSWORD]` for accessing the registry") f.Hidden = true } - fs.Var(newOptionalStringValue(&flags.registryToken), flagPrefix+"registry-token", "Provide a Bearer token for accessing the registry") + fs.Var(commonFlag.NewOptionalStringValue(&flags.registryToken), flagPrefix+"registry-token", "Provide a Bearer token for accessing the registry") fs.StringVar(&flags.dockerCertPath, flagPrefix+"cert-dir", "", "use certificates at `PATH` (*.crt, *.cert, *.key) to connect to the registry or daemon") - optionalBoolFlag(&fs, &flags.tlsVerify, flagPrefix+"tls-verify", "require HTTPS and verify certificates when talking to the container registry or daemon") + commonFlag.OptionalBoolFlag(&fs, &flags.tlsVerify, flagPrefix+"tls-verify", "require HTTPS and verify certificates when talking to the container registry or daemon") fs.BoolVar(&flags.noCreds, flagPrefix+"no-creds", false, "Access the registry anonymously") return fs, &flags } @@ -168,49 +169,49 @@ func (opts *imageOptions) newSystemContext() (*types.SystemContext, error) { ctx.AuthFilePath = opts.shared.authFilePath ctx.DockerDaemonHost = opts.dockerDaemonHost ctx.DockerDaemonCertPath = opts.dockerCertPath - if opts.dockerImageOptions.authFilePath.present { - ctx.AuthFilePath = opts.dockerImageOptions.authFilePath.value + if opts.dockerImageOptions.authFilePath.Present() { + ctx.AuthFilePath = opts.dockerImageOptions.authFilePath.Value() } - if opts.deprecatedTLSVerify != nil && opts.deprecatedTLSVerify.tlsVerify.present { + if opts.deprecatedTLSVerify != nil && opts.deprecatedTLSVerify.tlsVerify.Present() { // If both this deprecated option and a non-deprecated option is present, we use the latter value. - ctx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.deprecatedTLSVerify.tlsVerify.value) + ctx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.deprecatedTLSVerify.tlsVerify.Value()) } - if opts.tlsVerify.present { - ctx.DockerDaemonInsecureSkipTLSVerify = !opts.tlsVerify.value + if opts.tlsVerify.Present() { + ctx.DockerDaemonInsecureSkipTLSVerify = !opts.tlsVerify.Value() } - if opts.tlsVerify.present { - ctx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.tlsVerify.value) + if opts.tlsVerify.Present() { + ctx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.tlsVerify.Value()) } - if opts.credsOption.present && opts.noCreds { + if opts.credsOption.Present() && opts.noCreds { return nil, errors.New("creds and no-creds cannot be specified at the same time") } - if opts.userName.present && opts.noCreds { + if opts.userName.Present() && opts.noCreds { return nil, errors.New("username and no-creds cannot be specified at the same time") } - if opts.credsOption.present && opts.userName.present { + if opts.credsOption.Present() && opts.userName.Present() { return nil, errors.New("creds and username cannot be specified at the same time") } // if any of username or password is present, then both are expected to be present - if opts.userName.present != opts.password.present { - if opts.userName.present { + if opts.userName.Present() != opts.password.Present() { + if opts.userName.Present() { return nil, errors.New("password must be specified when username is specified") } return nil, errors.New("username must be specified when password is specified") } - if opts.credsOption.present { + if opts.credsOption.Present() { var err error - ctx.DockerAuthConfig, err = getDockerAuth(opts.credsOption.value) + ctx.DockerAuthConfig, err = getDockerAuth(opts.credsOption.Value()) if err != nil { return nil, err } - } else if opts.userName.present { + } else if opts.userName.Present() { ctx.DockerAuthConfig = &types.DockerAuthConfig{ - Username: opts.userName.value, - Password: opts.password.value, + Username: opts.userName.Value(), + Password: opts.password.Value(), } } - if opts.registryToken.present { - ctx.DockerBearerRegistryToken = opts.registryToken.value + if opts.registryToken.Present() { + ctx.DockerBearerRegistryToken = opts.registryToken.Value() } if opts.noCreds { ctx.DockerAuthConfig = &types.DockerAuthConfig{} @@ -222,12 +223,12 @@ func (opts *imageOptions) newSystemContext() (*types.SystemContext, error) { // imageDestOptions is a superset of imageOptions specialized for image destinations. type imageDestOptions struct { *imageOptions - dirForceCompression bool // Compress layers when saving to the dir: transport - dirForceDecompression bool // Decompress layers when saving to the dir: transport - ociAcceptUncompressedLayers bool // Whether to accept uncompressed layers in the oci: transport - compressionFormat string // Format to use for the compression - compressionLevel optionalInt // Level to use for the compression - precomputeDigests bool // Precompute digests to dedup layers when saving to the docker: transport + dirForceCompression bool // Compress layers when saving to the dir: transport + dirForceDecompression bool // Decompress layers when saving to the dir: transport + ociAcceptUncompressedLayers bool // Whether to accept uncompressed layers in the oci: transport + compressionFormat string // Format to use for the compression + compressionLevel commonFlag.OptionalInt // Level to use for the compression + precomputeDigests bool // Precompute digests to dedup layers when saving to the docker: transport } // imageDestFlags prepares a collection of CLI flags writing into imageDestOptions, and the managed imageDestOptions structure. @@ -240,7 +241,7 @@ func imageDestFlags(global *globalOptions, shared *sharedImageOptions, deprecate fs.BoolVar(&opts.dirForceDecompression, flagPrefix+"decompress", false, "Decompress tarball image layers when saving to directory using the 'dir' transport. (default is same compression type as source)") fs.BoolVar(&opts.ociAcceptUncompressedLayers, flagPrefix+"oci-accept-uncompressed-layers", false, "Allow uncompressed image layers when saving to an OCI image using the 'oci' transport. (default is to compress things that aren't compressed)") fs.StringVar(&opts.compressionFormat, flagPrefix+"compress-format", "", "`FORMAT` to use for the compression") - fs.Var(newOptionalIntValue(&opts.compressionLevel), flagPrefix+"compress-level", "`LEVEL` to use for the compression") + fs.Var(commonFlag.NewOptionalIntValue(&opts.compressionLevel), flagPrefix+"compress-level", "`LEVEL` to use for the compression") fs.BoolVar(&opts.precomputeDigests, flagPrefix+"precompute-digests", false, "Precompute digests to prevent uploading layers already on the registry using the 'docker' transport.") return fs, &opts } @@ -263,8 +264,9 @@ func (opts *imageDestOptions) newSystemContext() (*types.SystemContext, error) { } ctx.CompressionFormat = &cf } - if opts.compressionLevel.present { - ctx.CompressionLevel = &opts.compressionLevel.value + if opts.compressionLevel.Present() { + value := opts.compressionLevel.Value() + ctx.CompressionLevel = &value } ctx.DockerRegistryPushPrecomputeDigests = opts.precomputeDigests return ctx, err diff --git a/go.mod b/go.mod index 61926627..631e7063 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,11 @@ module github.com/containers/skopeo go 1.12 require ( - github.com/containers/common v0.46.0 + github.com/containers/common v0.46.1-0.20211026130826-7abfd453c86f github.com/containers/image/v5 v5.16.2-0.20211021181114-25411654075f github.com/containers/ocicrypt v1.1.2 github.com/containers/storage v1.37.0 - github.com/docker/docker v20.10.9+incompatible + github.com/docker/docker v20.10.10+incompatible github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283 diff --git a/go.sum b/go.sum index 7336d0ca..37e028ac 100644 --- a/go.sum +++ b/go.sum @@ -74,7 +74,7 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3 github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim v0.8.18/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim v0.8.22 h1:CulZ3GW8sNJExknToo+RWD+U+6ZM5kkNfuxywSDPd08= github.com/Microsoft/hcsshim v0.8.22/go.mod h1:91uVCVzvX2QD16sMCenoxxXo6L1wJnLMX2PSufFMtF0= @@ -174,6 +174,7 @@ github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= +github.com/containerd/containerd v1.5.4/go.mod h1:sx18RgvW6ABJ4iYUw7Q5x7bgFOAB9B6G7+yO0XBc4zw= github.com/containerd/containerd v1.5.7 h1:rQyoYtj4KddB3bxG6SAqd4+08gePNyJjRqvOIfV3rkM= github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -203,7 +204,6 @@ github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJ github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/stargz-snapshotter/estargz v0.8.0/go.mod h1:mwIwuwb+D8FX2t45Trwi0hmWmZm5VW7zPP/rekwhWQU= github.com/containerd/stargz-snapshotter/estargz v0.9.0 h1:PkB6BSTfOKX23erT2GkoUKkJEcXfNcyKskIViK770v8= github.com/containerd/stargz-snapshotter/estargz v0.9.0/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= @@ -225,9 +225,9 @@ github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containers/common v0.46.0 h1:95zB7kYBQJW+aK5xxZnaobCwoPyYOf85Y0yUx0E5aRg= -github.com/containers/common v0.46.0/go.mod h1:zxv7KjdYddSGoWuLUVp6eSb++Ow1zmSMB2jwxuNB4cU= -github.com/containers/image/v5 v5.16.0/go.mod h1:XgTpfAPLRGOd1XYyCU5cISFr777bLmOerCSpt/v7+Q4= +github.com/containers/common v0.46.1-0.20211026130826-7abfd453c86f h1:jFFIV8QvsPgwkJHh3tjfREFRwSeMq5M8lt8vklkZaOk= +github.com/containers/common v0.46.1-0.20211026130826-7abfd453c86f/go.mod h1:pVvmLTLCOZE300e4rex/QDmpnRmEM/5aZ/YfCkkjgZo= +github.com/containers/image/v5 v5.16.1/go.mod h1:mCvIFdzyyP1B0NBcZ80OIuaYqFn/OpFpaOMOMn1kU2M= github.com/containers/image/v5 v5.16.2-0.20211021181114-25411654075f h1:gqeQG8jumo9u6TmyUPrSCuflSjkQX+zFa5bRJAZYz2g= github.com/containers/image/v5 v5.16.2-0.20211021181114-25411654075f/go.mod h1:ERFkrXC5lLXov65ia/NiKBKfEeHgiItB9bQz6fReQ7g= github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE= @@ -237,8 +237,6 @@ github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgU github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/containers/ocicrypt v1.1.2 h1:Ez+GAMP/4GLix5Ywo/fL7O0nY771gsBIigiqUm1aXz0= github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/containers/storage v1.35.0/go.mod h1:qzYhasQP2/V9D9XdO+vRwkHBhsBO0oznMLzzRDQ8s20= -github.com/containers/storage v1.36.0/go.mod h1:vbd3SKVQNHdmU5qQI6hTEcKPxnZkGqydG4f6uwrI5a8= github.com/containers/storage v1.37.0 h1:HVhDsur6sx889ZIZ1d1kEiOzv3gsr5q0diX2VZmOdSg= github.com/containers/storage v1.37.0/go.mod h1:kqeJeS0b7DO2ZT1nVWs0XufrmPFbgV3c+Q/45RlH6r4= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -281,8 +279,9 @@ github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.9+incompatible h1:JlsVnETOjM2RLQa0Cc1XCIspUdXW3Zenq9P54uXBm6k= github.com/docker/docker v20.10.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.10+incompatible h1:GKkP0T7U4ks6X3lmmHKC2QDprnpRJor2Z5a8m62R9ZM= +github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= @@ -395,7 +394,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -513,8 +511,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= @@ -606,8 +602,9 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= 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 v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -647,7 +644,6 @@ github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pK github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= -github.com/opencontainers/selinux v1.8.4/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo= github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo= github.com/opencontainers/selinux v1.9.1 h1:b4VPEF3O5JLZgdTDBmGepaaIbAo0GqoF6EBRq5f/g3Y= github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= @@ -786,7 +782,6 @@ github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= -github.com/vbauerster/mpb/v7 v7.1.3/go.mod h1:X5GlohZw2fIpypMXWaKart+HGSAjpz49skxkDk+ZL7c= github.com/vbauerster/mpb/v7 v7.1.5 h1:vtUEUfQHmNeJETyF4AcRCOV6RC4wqFwNORy52UMXPbQ= github.com/vbauerster/mpb/v7 v7.1.5/go.mod h1:4M8+qAoQqV60WDNktBM5k05i1iTrXE7rjKOHEVkVlec= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= @@ -1052,7 +1047,6 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211004093028-2c5d950f24ef h1:fPxZ3Umkct3LZ8gK9nbk+DWDJ9fstZa2grBn+lWVKPs= diff --git a/cmd/skopeo/flag.go b/vendor/github.com/containers/common/pkg/flag/flag.go similarity index 56% rename from cmd/skopeo/flag.go rename to vendor/github.com/containers/common/pkg/flag/flag.go index f91f75f5..52eb50da 100644 --- a/cmd/skopeo/flag.go +++ b/vendor/github.com/containers/common/pkg/flag/flag.go @@ -1,4 +1,4 @@ -package main +package flag import ( "strconv" @@ -6,19 +6,31 @@ import ( "github.com/spf13/pflag" ) -// optionalBool is a boolean with a separate presence flag. -type optionalBool struct { +// OptionalBool is a boolean with a separate presence flag and value. +type OptionalBool struct { present bool value bool } +// Present returns the bool's presence flag. +func (ob *OptionalBool) Present() bool { + return ob.present +} + +// Present returns the bool's value. Should only be used if Present() is true. +func (ob *OptionalBool) Value() bool { + return ob.value +} + // optionalBool is a cli.Generic == flag.Value implementation equivalent to // the one underlying flag.Bool, except that it records whether the flag has been set. // This is distinct from optionalBool to (pretend to) force callers to use // optionalBoolFlag -type optionalBoolValue optionalBool +type optionalBoolValue OptionalBool -func optionalBoolFlag(fs *pflag.FlagSet, p *optionalBool, name, usage string) *pflag.Flag { +// OptionalBoolFlag creates new flag for an optional in the specified flag with +// the specified name and usage. +func OptionalBoolFlag(fs *pflag.FlagSet, p *OptionalBool, name, usage string) *pflag.Flag { flag := fs.VarPF(internalNewOptionalBoolValue(p), name, "", usage) flag.NoOptDefVal = "true" flag.DefValue = "false" @@ -27,11 +39,12 @@ func optionalBoolFlag(fs *pflag.FlagSet, p *optionalBool, name, usage string) *p // WARNING: Do not directly use this method to define optionalBool flag. // Caller should use optionalBoolFlag -func internalNewOptionalBoolValue(p *optionalBool) pflag.Value { +func internalNewOptionalBoolValue(p *OptionalBool) pflag.Value { p.present = false return (*optionalBoolValue)(p) } +// Set parses the string to a bool and sets it. func (ob *optionalBoolValue) Set(s string) error { v, err := strconv.ParseBool(s) if err != nil { @@ -42,6 +55,7 @@ func (ob *optionalBoolValue) Set(s string) error { return nil } +// String returns the string representation of the string. func (ob *optionalBoolValue) String() string { if !ob.present { return "" // This is, sadly, not round-trip safe: --flag is interpreted as --flag=true @@ -49,37 +63,52 @@ func (ob *optionalBoolValue) String() string { return strconv.FormatBool(ob.value) } +// Type returns the type. func (ob *optionalBoolValue) Type() string { return "bool" } +// IsBoolFlag indicates that it's a bool flag. func (ob *optionalBoolValue) IsBoolFlag() bool { return true } -// optionalString is a string with a separate presence flag. -type optionalString struct { +// OptionalString is a string with a separate presence flag. +type OptionalString struct { present bool value string } +// Present returns the strings's presence flag. +func (os *OptionalString) Present() bool { + return os.present +} + +// Present returns the string's value. Should only be used if Present() is true. +func (os *OptionalString) Value() string { + return os.value +} + // optionalString is a cli.Generic == flag.Value implementation equivalent to // the one underlying flag.String, except that it records whether the flag has been set. // This is distinct from optionalString to (pretend to) force callers to use // newoptionalString -type optionalStringValue optionalString +type optionalStringValue OptionalString -func newOptionalStringValue(p *optionalString) pflag.Value { +// NewOptionalStringValue returns a pflag.Value fo the string. +func NewOptionalStringValue(p *OptionalString) pflag.Value { p.present = false return (*optionalStringValue)(p) } +// Set sets the string. func (ob *optionalStringValue) Set(s string) error { ob.value = s ob.present = true return nil } +// String returns the string if present. func (ob *optionalStringValue) String() string { if !ob.present { return "" // This is, sadly, not round-trip safe: --flag= is interpreted as {present:true, value:""} @@ -87,27 +116,40 @@ func (ob *optionalStringValue) String() string { return ob.value } +// Type returns the string type. func (ob *optionalStringValue) Type() string { return "string" } -// optionalInt is a int with a separate presence flag. -type optionalInt struct { +// OptionalInt is a int with a separate presence flag. +type OptionalInt struct { present bool value int } +// Present returns the int's presence flag. +func (oi *OptionalInt) Present() bool { + return oi.present +} + +// Present returns the int's value. Should only be used if Present() is true. +func (oi *OptionalInt) Value() int { + return oi.value +} + // optionalInt is a cli.Generic == flag.Value implementation equivalent to // the one underlying flag.Int, except that it records whether the flag has been set. // This is distinct from optionalInt to (pretend to) force callers to use // newoptionalIntValue -type optionalIntValue optionalInt +type optionalIntValue OptionalInt -func newOptionalIntValue(p *optionalInt) pflag.Value { +// NewOptionalIntValue returns the pflag.Value of the int. +func NewOptionalIntValue(p *OptionalInt) pflag.Value { p.present = false return (*optionalIntValue)(p) } +// Set parses the string to an int and sets it. func (ob *optionalIntValue) Set(s string) error { v, err := strconv.ParseInt(s, 0, strconv.IntSize) if err != nil { @@ -118,6 +160,7 @@ func (ob *optionalIntValue) Set(s string) error { return nil } +// String returns the string representation of the int. func (ob *optionalIntValue) String() string { if !ob.present { return "" // If the value is not present, just return an empty string, any other value wouldn't make sense. @@ -125,6 +168,7 @@ func (ob *optionalIntValue) String() string { return strconv.Itoa(int(ob.value)) } +// Type returns the int's type. func (ob *optionalIntValue) Type() string { return "int" } diff --git a/vendor/github.com/containers/common/pkg/retry/retry.go b/vendor/github.com/containers/common/pkg/retry/retry.go index 8eb2da97..43e3a668 100644 --- a/vendor/github.com/containers/common/pkg/retry/retry.go +++ b/vendor/github.com/containers/common/pkg/retry/retry.go @@ -30,7 +30,7 @@ func RetryIfNecessary(ctx context.Context, operation func() error, retryOptions if retryOptions.Delay != 0 { delay = retryOptions.Delay } - logrus.Warnf("failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, retryOptions.MaxRetry, err) + logrus.Warnf("Failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, retryOptions.MaxRetry, err) select { case <-time.After(delay): break diff --git a/vendor/modules.txt b/vendor/modules.txt index e6c5053e..6135f4ea 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -45,10 +45,11 @@ github.com/containerd/containerd/platforms # github.com/containerd/stargz-snapshotter/estargz v0.9.0 github.com/containerd/stargz-snapshotter/estargz github.com/containerd/stargz-snapshotter/estargz/errorutil -# github.com/containers/common v0.46.0 +# github.com/containers/common v0.46.1-0.20211026130826-7abfd453c86f github.com/containers/common/pkg/auth github.com/containers/common/pkg/capabilities github.com/containers/common/pkg/completion +github.com/containers/common/pkg/flag github.com/containers/common/pkg/report github.com/containers/common/pkg/report/camelcase github.com/containers/common/pkg/retry @@ -176,7 +177,7 @@ github.com/docker/distribution/registry/client/auth/challenge github.com/docker/distribution/registry/client/transport github.com/docker/distribution/registry/storage/cache github.com/docker/distribution/registry/storage/cache/memory -# github.com/docker/docker v20.10.9+incompatible +# github.com/docker/docker v20.10.10+incompatible github.com/docker/docker/api github.com/docker/docker/api/types github.com/docker/docker/api/types/blkiodev