From 67dbde6970bbfc2d67368d1bcd6bdc031d7ddb29 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Tue, 11 Feb 2025 18:14:49 +0100 Subject: [PATCH] Revert "vendor: github.com/docker/cli/v28.0.0-rc.1" This reverts commit 7216086b8cf9eaabcd63ce681ebf59974645464d. Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 +- .../docker/cli/cli-plugins/hooks/printer.go | 4 +- .../docker/cli/cli-plugins/manager/cobra.go | 3 +- .../docker/cli/cli-plugins/plugin/plugin.go | 24 ++-- vendor/github.com/docker/cli/cli/cobra.go | 6 +- .../github.com/docker/cli/cli/command/cli.go | 8 +- .../cli/cli/command/formatter/container.go | 20 ++- .../cli/cli/command/formatter/disk_usage.go | 38 +++--- .../docker/cli/cli/command/registry.go | 8 +- .../docker/cli/cli/command/telemetry.go | 2 +- .../docker/cli/cli/command/utils.go | 2 +- .../docker/cli/cli/config/config.go | 2 +- .../cli/cli/config/credentials/file_store.go | 36 ++---- .../cli/cli/context/store/metadatastore.go | 4 +- .../docker/cli/cli/context/store/tlsstore.go | 4 +- vendor/github.com/docker/cli/cli/error.go | 38 +++--- .../docker/cli/cli/flags/options.go | 2 +- .../github.com/docker/cli/cli/hints/hints.go | 4 +- .../cli/cli/registry/client/endpoint.go | 7 +- vendor/github.com/docker/cli/cli/required.go | 40 +++--- .../docker/cli/internal/tui/chip.go | 12 -- .../docker/cli/internal/tui/colors.go | 33 ----- .../docker/cli/internal/tui/count.go | 70 ----------- .../docker/cli/internal/tui/note.go | 39 ------ .../docker/cli/internal/tui/output.go | 62 --------- .../github.com/docker/cli/internal/tui/str.go | 19 --- vendor/github.com/docker/cli/opts/network.go | 8 -- .../pkg/ioutils/fswriters_deprecated.go | 44 +++++++ .../docker/docker/pkg/ioutils/readers.go | 118 ++++++++++++++++++ .../docker/docker/pkg/ioutils/writeflusher.go | 96 ++++++++++++++ .../docker/docker/pkg/ioutils/writers.go | 28 +++++ vendor/modules.txt | 4 +- 33 files changed, 408 insertions(+), 383 deletions(-) delete mode 100644 vendor/github.com/docker/cli/internal/tui/chip.go delete mode 100644 vendor/github.com/docker/cli/internal/tui/colors.go delete mode 100644 vendor/github.com/docker/cli/internal/tui/count.go delete mode 100644 vendor/github.com/docker/cli/internal/tui/note.go delete mode 100644 vendor/github.com/docker/cli/internal/tui/output.go delete mode 100644 vendor/github.com/docker/cli/internal/tui/str.go create mode 100644 vendor/github.com/docker/docker/pkg/ioutils/fswriters_deprecated.go create mode 100644 vendor/github.com/docker/docker/pkg/ioutils/readers.go create mode 100644 vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go create mode 100644 vendor/github.com/docker/docker/pkg/ioutils/writers.go diff --git a/go.mod b/go.mod index 9f71b218..efc66164 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/creack/pty v1.1.24 github.com/davecgh/go-spew v1.1.1 github.com/distribution/reference v0.6.0 - github.com/docker/cli v28.0.0-rc.1+incompatible + github.com/docker/cli v27.5.1+incompatible github.com/docker/cli-docs-tool v0.9.0 github.com/docker/docker v28.0.0-rc.1+incompatible github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index 5e24ec79..557bc725 100644 --- a/go.sum +++ b/go.sum @@ -122,8 +122,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v28.0.0-rc.1+incompatible h1:4Xkn+JKnvVqDfyL/pZCWaPM9jzPtAJvNu7qKBkotv3I= -github.com/docker/cli v28.0.0-rc.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.5.1+incompatible h1:JB9cieUT9YNiMITtIsguaN55PLOHhBSz3LKVc6cqWaY= +github.com/docker/cli v27.5.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli-docs-tool v0.9.0 h1:CVwQbE+ZziwlPqrJ7LRyUF6GvCA+6gj7MTCsayaK9t0= github.com/docker/cli-docs-tool v0.9.0/go.mod h1:ClrwlNW+UioiRyH9GiAOe1o3J/TsY3Tr1ipoypjAUtc= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= diff --git a/vendor/github.com/docker/cli/cli-plugins/hooks/printer.go b/vendor/github.com/docker/cli/cli-plugins/hooks/printer.go index f6d4b28e..bedc87f9 100644 --- a/vendor/github.com/docker/cli/cli-plugins/hooks/printer.go +++ b/vendor/github.com/docker/cli/cli-plugins/hooks/printer.go @@ -11,8 +11,8 @@ func PrintNextSteps(out io.Writer, messages []string) { if len(messages) == 0 { return } - _, _ = fmt.Fprintln(out, aec.Bold.Apply("\nWhat's next:")) + fmt.Fprintln(out, aec.Bold.Apply("\nWhat's next:")) for _, n := range messages { - _, _ = fmt.Fprintln(out, " ", n) + _, _ = fmt.Fprintf(out, " %s\n", n) } } diff --git a/vendor/github.com/docker/cli/cli-plugins/manager/cobra.go b/vendor/github.com/docker/cli/cli-plugins/manager/cobra.go index 4bfa06fa..feff8a8f 100644 --- a/vendor/github.com/docker/cli/cli-plugins/manager/cobra.go +++ b/vendor/github.com/docker/cli/cli-plugins/manager/cobra.go @@ -52,6 +52,7 @@ func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) (err e return } for _, p := range plugins { + p := p vendor := p.Vendor if vendor == "" { vendor = "unknown" @@ -81,7 +82,7 @@ func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) (err e cmd.HelpFunc()(rootCmd, args) return nil } - return fmt.Errorf("docker: unknown command: docker %s\n\nRun 'docker --help' for more information", cmd.Name()) + return fmt.Errorf("docker: '%s' is not a docker command.\nSee 'docker --help'", cmd.Name()) }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // Delegate completion to plugin diff --git a/vendor/github.com/docker/cli/cli-plugins/plugin/plugin.go b/vendor/github.com/docker/cli/cli-plugins/plugin/plugin.go index cf57aad5..8cce73d9 100644 --- a/vendor/github.com/docker/cli/cli-plugins/plugin/plugin.go +++ b/vendor/github.com/docker/cli/cli-plugins/plugin/plugin.go @@ -3,7 +3,6 @@ package plugin import ( "context" "encoding/json" - "errors" "fmt" "os" "sync" @@ -35,7 +34,7 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta manager var persistentPreRunOnce sync.Once PersistentPreRunE = func(cmd *cobra.Command, _ []string) error { - var retErr error + var err error persistentPreRunOnce.Do(func() { ctx, cancel := context.WithCancel(cmd.Context()) cmd.SetContext(ctx) @@ -47,7 +46,7 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta manager opts = append(opts, withPluginClientConn(plugin.Name())) } opts = append(opts, command.WithEnableGlobalMeterProvider(), command.WithEnableGlobalTracerProvider()) - retErr = tcmd.Initialize(opts...) + err = tcmd.Initialize(opts...) ogRunE := cmd.RunE if ogRunE == nil { ogRun := cmd.Run @@ -67,7 +66,7 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta manager return err } }) - return retErr + return err } cmd, args, err := tcmd.HandleGlobalFlags() @@ -93,17 +92,18 @@ func Run(makeCmd func(command.Cli) *cobra.Command, meta manager.Metadata) { plugin := makeCmd(dockerCli) if err := RunPlugin(dockerCli, plugin, meta); err != nil { - var stErr cli.StatusError - if errors.As(err, &stErr) { + if sterr, ok := err.(cli.StatusError); ok { + if sterr.Status != "" { + fmt.Fprintln(dockerCli.Err(), sterr.Status) + } // StatusError should only be used for errors, and all errors should // have a non-zero exit status, so never exit with 0 - if stErr.StatusCode == 0 { // FIXME(thaJeztah): this should never be used with a zero status-code. Check if we do this anywhere. - stErr.StatusCode = 1 + if sterr.StatusCode == 0 { + os.Exit(1) } - _, _ = fmt.Fprintln(dockerCli.Err(), stErr) - os.Exit(stErr.StatusCode) + os.Exit(sterr.StatusCode) } - _, _ = fmt.Fprintln(dockerCli.Err(), err) + fmt.Fprintln(dockerCli.Err(), err) os.Exit(1) } } @@ -158,7 +158,7 @@ func newPluginCommand(dockerCli *command.DockerCli, plugin *cobra.Command, meta CompletionOptions: cobra.CompletionOptions{ DisableDefaultCmd: false, HiddenDefaultCmd: true, - DisableDescriptions: os.Getenv("DOCKER_CLI_DISABLE_COMPLETION_DESCRIPTION") != "", + DisableDescriptions: true, }, } opts, _ := cli.SetupPluginRootCommand(cmd) diff --git a/vendor/github.com/docker/cli/cli/cobra.go b/vendor/github.com/docker/cli/cli/cobra.go index feab2b4a..f6a69ae0 100644 --- a/vendor/github.com/docker/cli/cli/cobra.go +++ b/vendor/github.com/docker/cli/cli/cobra.go @@ -92,8 +92,12 @@ func FlagErrorFunc(cmd *cobra.Command, err error) error { return nil } + usage := "" + if cmd.HasSubCommands() { + usage = "\n\n" + cmd.UsageString() + } return StatusError{ - Status: fmt.Sprintf("%s\n\nUsage: %s\n\nRun '%s --help' for more information", err, cmd.UseLine(), cmd.CommandPath()), + Status: fmt.Sprintf("%s\nSee '%s --help'.%s", err, cmd.CommandPath(), usage), StatusCode: 125, } } diff --git a/vendor/github.com/docker/cli/cli/command/cli.go b/vendor/github.com/docker/cli/cli/command/cli.go index a8cfd58e..da0802d5 100644 --- a/vendor/github.com/docker/cli/cli/command/cli.go +++ b/vendor/github.com/docker/cli/cli/command/cli.go @@ -114,7 +114,7 @@ func (cli *DockerCli) CurrentVersion() string { // Client returns the APIClient func (cli *DockerCli) Client() client.APIClient { if err := cli.initialize(); err != nil { - _, _ = fmt.Fprintln(cli.Err(), "Failed to initialize:", err) + _, _ = fmt.Fprintf(cli.Err(), "Failed to initialize: %s\n", err) os.Exit(1) } return cli.client @@ -272,7 +272,7 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption) debug.Enable() } if opts.Context != "" && len(opts.Hosts) > 0 { - return errors.New("conflicting options: cannot specify both --host and --context") + return errors.New("conflicting options: either specify --host or --context, not both") } cli.options = opts @@ -299,7 +299,7 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption) // NewAPIClientFromFlags creates a new APIClient from command line flags func NewAPIClientFromFlags(opts *cliflags.ClientOptions, configFile *configfile.ConfigFile) (client.APIClient, error) { if opts.Context != "" && len(opts.Hosts) > 0 { - return nil, errors.New("conflicting options: cannot specify both --host and --context") + return nil, errors.New("conflicting options: either specify --host or --context, not both") } storeConfig := DefaultContextStoreConfig() @@ -475,7 +475,7 @@ func (cli *DockerCli) DockerEndpoint() docker.Endpoint { if err := cli.initialize(); err != nil { // Note that we're not terminating here, as this function may be used // in cases where we're able to continue. - _, _ = fmt.Fprintln(cli.Err(), cli.initErr) + _, _ = fmt.Fprintf(cli.Err(), "%v\n", cli.initErr) } return cli.dockerEndpoint } diff --git a/vendor/github.com/docker/cli/cli/command/formatter/container.go b/vendor/github.com/docker/cli/cli/command/formatter/container.go index ba62efb2..10d4e4b4 100644 --- a/vendor/github.com/docker/cli/cli/command/formatter/container.go +++ b/vendor/github.com/docker/cli/cli/command/formatter/container.go @@ -12,7 +12,7 @@ import ( "time" "github.com/distribution/reference" - "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types" "github.com/docker/docker/pkg/stringid" "github.com/docker/go-units" ) @@ -67,10 +67,10 @@ ports: {{- pad .Ports 1 0}} } // ContainerWrite renders the context for a list of containers -func ContainerWrite(ctx Context, containers []container.Summary) error { +func ContainerWrite(ctx Context, containers []types.Container) error { render := func(format func(subContext SubContext) error) error { - for _, ctr := range containers { - err := format(&ContainerContext{trunc: ctx.Trunc, c: ctr}) + for _, container := range containers { + err := format(&ContainerContext{trunc: ctx.Trunc, c: container}) if err != nil { return err } @@ -84,7 +84,7 @@ func ContainerWrite(ctx Context, containers []container.Summary) error { type ContainerContext struct { HeaderContext trunc bool - c container.Summary + c types.Container // FieldsUsed is used in the pre-processing step to detect which fields are // used in the template. It's currently only used to detect use of the .Size @@ -193,9 +193,7 @@ func (c *ContainerContext) Command() string { return strconv.Quote(command) } -// CreatedAt returns the formatted string representing the container's creation date/time. -// The format may include nanoseconds if present. -// e.g. "2006-01-02 15:04:05.999999999 -0700 MST" or "2006-01-02 15:04:05 -0700 MST" +// CreatedAt returns the "Created" date/time of the container as a unix timestamp. func (c *ContainerContext) CreatedAt() string { return time.Unix(c.c.Created, 0).String() } @@ -316,7 +314,7 @@ func (c *ContainerContext) Networks() string { // DisplayablePorts returns formatted string representing open ports of container // e.g. "0.0.0.0:80->9090/tcp, 9988/tcp" // it's used by command 'docker ps' -func DisplayablePorts(ports []container.Port) string { +func DisplayablePorts(ports []types.Port) string { type portGroup struct { first uint16 last uint16 @@ -377,12 +375,12 @@ func formGroup(key string, start, last uint16) string { group = fmt.Sprintf("%s-%d", group, last) } if ip != "" { - group = fmt.Sprintf("%s->%s", net.JoinHostPort(ip, group), group) + group = fmt.Sprintf("%s:%s->%s", ip, group, group) } return group + "/" + groupType } -func comparePorts(i, j container.Port) bool { +func comparePorts(i, j types.Port) bool { if i.PrivatePort != j.PrivatePort { return i.PrivatePort < j.PrivatePort } diff --git a/vendor/github.com/docker/cli/cli/command/formatter/disk_usage.go b/vendor/github.com/docker/cli/cli/command/formatter/disk_usage.go index 18d79d08..d91df2fc 100644 --- a/vendor/github.com/docker/cli/cli/command/formatter/disk_usage.go +++ b/vendor/github.com/docker/cli/cli/command/formatter/disk_usage.go @@ -9,7 +9,6 @@ import ( "github.com/distribution/reference" "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/volume" units "github.com/docker/go-units" @@ -37,7 +36,7 @@ type DiskUsageContext struct { Verbose bool LayersSize int64 Images []*image.Summary - Containers []*container.Summary + Containers []*types.Container Volumes []*volume.Volume BuildCache []*types.BuildCache BuilderSize int64 @@ -125,7 +124,7 @@ func (ctx *DiskUsageContext) Write() (err error) { return err } - diskUsageContainersCtx := diskUsageContainersContext{containers: []*container.Summary{}} + diskUsageContainersCtx := diskUsageContainersContext{containers: []*types.Container{}} diskUsageContainersCtx.Header = SubHeaderContext{ "Type": typeHeader, "TotalCount": totalHeader, @@ -237,7 +236,7 @@ func (ctx *DiskUsageContext) verboseWriteTable(duc *diskUsageContext) error { if err != nil { return err } - _, _ = ctx.Output.Write([]byte("\nLocal Volumes space usage:\n\n")) + ctx.Output.Write([]byte("\nLocal Volumes space usage:\n\n")) for _, v := range duc.Volumes { if err := ctx.contextFormat(tmpl, v); err != nil { return err @@ -249,7 +248,7 @@ func (ctx *DiskUsageContext) verboseWriteTable(duc *diskUsageContext) error { if err != nil { return err } - _, _ = fmt.Fprintf(ctx.Output, "\nBuild cache usage: %s\n\n", units.HumanSize(float64(ctx.BuilderSize))) + fmt.Fprintf(ctx.Output, "\nBuild cache usage: %s\n\n", units.HumanSize(float64(ctx.BuilderSize))) for _, v := range duc.BuildCache { if err := ctx.contextFormat(tmpl, v); err != nil { return err @@ -314,7 +313,7 @@ func (c *diskUsageImagesContext) Reclaimable() string { type diskUsageContainersContext struct { HeaderContext - containers []*container.Summary + containers []*types.Container } func (c *diskUsageContainersContext) MarshalJSON() ([]byte, error) { @@ -329,16 +328,16 @@ func (c *diskUsageContainersContext) TotalCount() string { return strconv.Itoa(len(c.containers)) } -func (c *diskUsageContainersContext) isActive(ctr container.Summary) bool { - return strings.Contains(ctr.State, "running") || - strings.Contains(ctr.State, "paused") || - strings.Contains(ctr.State, "restarting") +func (c *diskUsageContainersContext) isActive(container types.Container) bool { + return strings.Contains(container.State, "running") || + strings.Contains(container.State, "paused") || + strings.Contains(container.State, "restarting") } func (c *diskUsageContainersContext) Active() string { used := 0 - for _, ctr := range c.containers { - if c.isActive(*ctr) { + for _, container := range c.containers { + if c.isActive(*container) { used++ } } @@ -349,21 +348,22 @@ func (c *diskUsageContainersContext) Active() string { func (c *diskUsageContainersContext) Size() string { var size int64 - for _, ctr := range c.containers { - size += ctr.SizeRw + for _, container := range c.containers { + size += container.SizeRw } return units.HumanSize(float64(size)) } func (c *diskUsageContainersContext) Reclaimable() string { - var reclaimable, totalSize int64 + var reclaimable int64 + var totalSize int64 - for _, ctr := range c.containers { - if !c.isActive(*ctr) { - reclaimable += ctr.SizeRw + for _, container := range c.containers { + if !c.isActive(*container) { + reclaimable += container.SizeRw } - totalSize += ctr.SizeRw + totalSize += container.SizeRw } if totalSize > 0 { diff --git a/vendor/github.com/docker/cli/cli/command/registry.go b/vendor/github.com/docker/cli/cli/command/registry.go index e2581d57..cb966be1 100644 --- a/vendor/github.com/docker/cli/cli/command/registry.go +++ b/vendor/github.com/docker/cli/cli/command/registry.go @@ -13,10 +13,9 @@ import ( configtypes "github.com/docker/cli/cli/config/types" "github.com/docker/cli/cli/hints" "github.com/docker/cli/cli/streams" - "github.com/docker/cli/internal/tui" + "github.com/docker/docker/api/types" registrytypes "github.com/docker/docker/api/types/registry" "github.com/docker/docker/registry" - "github.com/morikuni/aec" "github.com/pkg/errors" ) @@ -30,7 +29,7 @@ const ( // RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info // for the given command. -func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInfo, cmdName string) registrytypes.RequestAuthConfig { +func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInfo, cmdName string) types.RequestPrivilegeFunc { return func(ctx context.Context) (string, error) { _, _ = fmt.Fprintf(cli.Out(), "\nLogin prior to %s:\n", cmdName) indexServer := registry.GetAuthConfigKey(index) @@ -180,9 +179,6 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword } }() - out := tui.NewOutput(cli.Err()) - out.PrintNote("A Personal Access Token (PAT) can be used instead.\n" + - "To create a PAT, visit " + aec.Underline.Apply("https://app.docker.com/settings") + "\n\n") argPassword, err = PromptForInput(ctx, cli.In(), cli.Out(), "Password: ") if err != nil { return registrytypes.AuthConfig{}, err diff --git a/vendor/github.com/docker/cli/cli/command/telemetry.go b/vendor/github.com/docker/cli/cli/command/telemetry.go index d8985234..d18d94d4 100644 --- a/vendor/github.com/docker/cli/cli/command/telemetry.go +++ b/vendor/github.com/docker/cli/cli/command/telemetry.go @@ -14,7 +14,7 @@ import ( "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.26.0" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" "go.opentelemetry.io/otel/trace" ) diff --git a/vendor/github.com/docker/cli/cli/command/utils.go b/vendor/github.com/docker/cli/cli/command/utils.go index 8a8368fb..2b4a885e 100644 --- a/vendor/github.com/docker/cli/cli/command/utils.go +++ b/vendor/github.com/docker/cli/cli/command/utils.go @@ -199,7 +199,7 @@ func PruneFilters(dockerCli Cli, pruneFilters filters.Args) filters.Args { // AddPlatformFlag adds `platform` to a set of flags for API version 1.32 and later. func AddPlatformFlag(flags *pflag.FlagSet, target *string) { flags.StringVar(target, "platform", os.Getenv("DOCKER_DEFAULT_PLATFORM"), "Set platform if server is multi-platform capable") - _ = flags.SetAnnotation("platform", "version", []string{"1.32"}) + flags.SetAnnotation("platform", "version", []string{"1.32"}) } // ValidateOutputPath validates the output paths of the `export` and `save` commands. diff --git a/vendor/github.com/docker/cli/cli/config/config.go b/vendor/github.com/docker/cli/cli/config/config.go index 910b3c00..5a518432 100644 --- a/vendor/github.com/docker/cli/cli/config/config.go +++ b/vendor/github.com/docker/cli/cli/config/config.go @@ -143,7 +143,7 @@ func load(configDir string) (*configfile.ConfigFile, error) { defer file.Close() err = configFile.LoadFromReader(file) if err != nil { - err = errors.Wrapf(err, "parsing config file (%s)", filename) + err = errors.Wrapf(err, "loading config file: %s: ", filename) } return configFile, err } diff --git a/vendor/github.com/docker/cli/cli/config/credentials/file_store.go b/vendor/github.com/docker/cli/cli/config/credentials/file_store.go index c69312b0..95406281 100644 --- a/vendor/github.com/docker/cli/cli/config/credentials/file_store.go +++ b/vendor/github.com/docker/cli/cli/config/credentials/file_store.go @@ -1,12 +1,9 @@ package credentials import ( - "fmt" "net" "net/url" - "os" "strings" - "sync/atomic" "github.com/docker/cli/cli/config/types" ) @@ -60,21 +57,6 @@ func (c *fileStore) GetAll() (map[string]types.AuthConfig, error) { return c.file.GetAuthConfigs(), nil } -// unencryptedWarning warns the user when using an insecure credential storage. -// After a deprecation period, user will get prompted if stdin and stderr are a terminal. -// Otherwise, we'll assume they want it (sadly), because people may have been scripting -// insecure logins and we don't want to break them. Maybe they'll see the warning in their -// logs and fix things. -const unencryptedWarning = ` -WARNING! Your credentials are stored unencrypted in '%s'. -Configure a credential helper to remove this warning. See -https://docs.docker.com/go/credential-store/ -` - -// alreadyPrinted ensures that we only print the unencryptedWarning once per -// CLI invocation (no need to warn the user multiple times per command). -var alreadyPrinted atomic.Bool - // Store saves the given credentials in the file store. This function is // idempotent and does not update the file if credentials did not change. func (c *fileStore) Store(authConfig types.AuthConfig) error { @@ -84,19 +66,15 @@ func (c *fileStore) Store(authConfig types.AuthConfig) error { return nil } authConfigs[authConfig.ServerAddress] = authConfig - if err := c.file.Save(); err != nil { - return err - } + return c.file.Save() +} - if !alreadyPrinted.Load() && authConfig.Password != "" { - // Display a warning if we're storing the users password (not a token). - // - // FIXME(thaJeztah): make output configurable instead of hardcoding to os.Stderr - _, _ = fmt.Fprintln(os.Stderr, fmt.Sprintf(unencryptedWarning, c.file.GetFilename())) - alreadyPrinted.Store(true) - } +func (c *fileStore) GetFilename() string { + return c.file.GetFilename() +} - return nil +func (c *fileStore) IsFileStore() bool { + return true } // ConvertToHostname converts a registry url which has http|https prepended diff --git a/vendor/github.com/docker/cli/cli/context/store/metadatastore.go b/vendor/github.com/docker/cli/cli/context/store/metadatastore.go index e8b25675..6b8975a4 100644 --- a/vendor/github.com/docker/cli/cli/context/store/metadatastore.go +++ b/vendor/github.com/docker/cli/cli/context/store/metadatastore.go @@ -12,7 +12,7 @@ import ( "sort" "github.com/docker/docker/errdefs" - "github.com/docker/docker/pkg/atomicwriter" + "github.com/docker/docker/pkg/ioutils" "github.com/fvbommel/sortorder" "github.com/pkg/errors" ) @@ -40,7 +40,7 @@ func (s *metadataStore) createOrUpdate(meta Metadata) error { if err != nil { return err } - return atomicwriter.WriteFile(filepath.Join(contextDir, metaFile), bytes, 0o644) + return ioutils.AtomicWriteFile(filepath.Join(contextDir, metaFile), bytes, 0o644) } func parseTypedOrMap(payload []byte, getter TypeGetter) (any, error) { diff --git a/vendor/github.com/docker/cli/cli/context/store/tlsstore.go b/vendor/github.com/docker/cli/cli/context/store/tlsstore.go index 3cbfe627..ffbbde7c 100644 --- a/vendor/github.com/docker/cli/cli/context/store/tlsstore.go +++ b/vendor/github.com/docker/cli/cli/context/store/tlsstore.go @@ -5,7 +5,7 @@ import ( "path/filepath" "github.com/docker/docker/errdefs" - "github.com/docker/docker/pkg/atomicwriter" + "github.com/docker/docker/pkg/ioutils" "github.com/pkg/errors" ) @@ -32,7 +32,7 @@ func (s *tlsStore) createOrUpdate(name, endpointName, filename string, data []by if err := os.MkdirAll(endpointDir, 0o700); err != nil { return err } - return atomicwriter.WriteFile(filepath.Join(endpointDir, filename), data, 0o600) + return ioutils.AtomicWriteFile(filepath.Join(endpointDir, filename), data, 0o600) } func (s *tlsStore) getData(name, endpointName, filename string) ([]byte, error) { diff --git a/vendor/github.com/docker/cli/cli/error.go b/vendor/github.com/docker/cli/cli/error.go index 1d35b4e7..a821f9e5 100644 --- a/vendor/github.com/docker/cli/cli/error.go +++ b/vendor/github.com/docker/cli/cli/error.go @@ -1,29 +1,35 @@ package cli import ( - "strconv" + "fmt" + "strings" ) +// Errors is a list of errors. +// Useful in a loop if you don't want to return the error right away and you want to display after the loop, +// all the errors that happened during the loop. +// +// Deprecated: use [errors.Join] instead; will be removed in the next release. +type Errors []error + +func (errList Errors) Error() string { + if len(errList) < 1 { + return "" + } + + out := make([]string, len(errList)) + for i := range errList { + out[i] = errList[i].Error() + } + return strings.Join(out, ", ") +} + // StatusError reports an unsuccessful exit by a command. type StatusError struct { - Cause error Status string StatusCode int } -// Error formats the error for printing. If a custom Status is provided, -// it is returned as-is, otherwise it generates a generic error-message -// based on the StatusCode. func (e StatusError) Error() string { - if e.Status != "" { - return e.Status - } - if e.Cause != nil { - return e.Cause.Error() - } - return "exit status " + strconv.Itoa(e.StatusCode) -} - -func (e StatusError) Unwrap() error { - return e.Cause + return fmt.Sprintf("Status: %s, Code: %d", e.Status, e.StatusCode) } diff --git a/vendor/github.com/docker/cli/cli/flags/options.go b/vendor/github.com/docker/cli/cli/flags/options.go index fc168984..5a6df9c8 100644 --- a/vendor/github.com/docker/cli/cli/flags/options.go +++ b/vendor/github.com/docker/cli/cli/flags/options.go @@ -138,7 +138,7 @@ func SetLogLevel(logLevel string) { if logLevel != "" { lvl, err := logrus.ParseLevel(logLevel) if err != nil { - _, _ = fmt.Fprintln(os.Stderr, "Unable to parse logging level:", logLevel) + fmt.Fprintf(os.Stderr, "Unable to parse logging level: %s\n", logLevel) os.Exit(1) } logrus.SetLevel(lvl) diff --git a/vendor/github.com/docker/cli/cli/hints/hints.go b/vendor/github.com/docker/cli/cli/hints/hints.go index aed35778..f99df8fd 100644 --- a/vendor/github.com/docker/cli/cli/hints/hints.go +++ b/vendor/github.com/docker/cli/cli/hints/hints.go @@ -5,9 +5,7 @@ import ( "strconv" ) -// Enabled returns whether cli hints are enabled or not. Hints are enabled by -// default, but can be disabled through the "DOCKER_CLI_HINTS" environment -// variable. +// Enabled returns whether cli hints are enabled or not func Enabled() bool { if v := os.Getenv("DOCKER_CLI_HINTS"); v != "" { enabled, err := strconv.ParseBool(v) diff --git a/vendor/github.com/docker/cli/cli/registry/client/endpoint.go b/vendor/github.com/docker/cli/cli/registry/client/endpoint.go index 2446da85..e06bfea5 100644 --- a/vendor/github.com/docker/cli/cli/registry/client/endpoint.go +++ b/vendor/github.com/docker/cli/cli/registry/client/endpoint.go @@ -22,7 +22,12 @@ type repositoryEndpoint struct { // Name returns the repository name func (r repositoryEndpoint) Name() string { - return reference.Path(r.info.Name) + repoName := r.info.Name.Name() + // If endpoint does not support CanonicalName, use the RemoteName instead + if r.endpoint.TrimHostname { + repoName = reference.Path(r.info.Name) + } + return repoName } // BaseURL returns the endpoint url diff --git a/vendor/github.com/docker/cli/cli/required.go b/vendor/github.com/docker/cli/cli/required.go index 6455e886..e8edcaaf 100644 --- a/vendor/github.com/docker/cli/cli/required.go +++ b/vendor/github.com/docker/cli/cli/required.go @@ -1,6 +1,8 @@ package cli import ( + "strings" + "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -12,20 +14,15 @@ func NoArgs(cmd *cobra.Command, args []string) error { } if cmd.HasSubCommands() { - return errors.Errorf( - "%[1]s: unknown command: %[2]s %[3]s\n\nUsage: %[4]s\n\nRun '%[2]s --help' for more information", - binName(cmd), - cmd.CommandPath(), - args[0], - cmd.UseLine(), - ) + return errors.New("\n" + strings.TrimRight(cmd.UsageString(), "\n")) } return errors.Errorf( - "%[1]s: '%[2]s' accepts no arguments\n\nUsage: %[3]s\n\nRun '%[2]s --help' for more information", - binName(cmd), + "%q accepts no arguments.\nSee '%s --help'.\n\nUsage: %s\n\n%s", + cmd.CommandPath(), cmd.CommandPath(), cmd.UseLine(), + cmd.Short, ) } @@ -36,12 +33,13 @@ func RequiresMinArgs(minArgs int) cobra.PositionalArgs { return nil } return errors.Errorf( - "%[1]s: '%[2]s' requires at least %[3]d %[4]s\n\nUsage: %[5]s\n\nSee '%[2]s --help' for more information", - binName(cmd), + "%q requires at least %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s", cmd.CommandPath(), minArgs, pluralize("argument", minArgs), + cmd.CommandPath(), cmd.UseLine(), + cmd.Short, ) } } @@ -53,12 +51,13 @@ func RequiresMaxArgs(maxArgs int) cobra.PositionalArgs { return nil } return errors.Errorf( - "%[1]s: '%[2]s' requires at most %[3]d %[4]s\n\nUsage: %[5]s\n\nSRun '%[2]s --help' for more information", - binName(cmd), + "%q requires at most %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s", cmd.CommandPath(), maxArgs, pluralize("argument", maxArgs), + cmd.CommandPath(), cmd.UseLine(), + cmd.Short, ) } } @@ -70,13 +69,14 @@ func RequiresRangeArgs(minArgs int, maxArgs int) cobra.PositionalArgs { return nil } return errors.Errorf( - "%[1]s: '%[2]s' requires at least %[3]d and at most %[4]d %[5]s\n\nUsage: %[6]s\n\nRun '%[2]s --help' for more information", - binName(cmd), + "%q requires at least %d and at most %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s", cmd.CommandPath(), minArgs, maxArgs, pluralize("argument", maxArgs), + cmd.CommandPath(), cmd.UseLine(), + cmd.Short, ) } } @@ -88,21 +88,17 @@ func ExactArgs(number int) cobra.PositionalArgs { return nil } return errors.Errorf( - "%[1]s: '%[2]s' requires %[3]d %[4]s\n\nUsage: %[5]s\n\nRun '%[2]s --help' for more information", - binName(cmd), + "%q requires exactly %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s", cmd.CommandPath(), number, pluralize("argument", number), + cmd.CommandPath(), cmd.UseLine(), + cmd.Short, ) } } -// binName returns the name of the binary / root command (usually 'docker'). -func binName(cmd *cobra.Command) string { - return cmd.Root().Name() -} - //nolint:unparam func pluralize(word string, number int) string { if number == 1 { diff --git a/vendor/github.com/docker/cli/internal/tui/chip.go b/vendor/github.com/docker/cli/internal/tui/chip.go deleted file mode 100644 index bb383109..00000000 --- a/vendor/github.com/docker/cli/internal/tui/chip.go +++ /dev/null @@ -1,12 +0,0 @@ -// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: -//go:build go1.22 - -package tui - -import "strconv" - -func Chip(fg, bg int, content string) string { - fgAnsi := "\x1b[38;5;" + strconv.Itoa(fg) + "m" - bgAnsi := "\x1b[48;5;" + strconv.Itoa(bg) + "m" - return fgAnsi + bgAnsi + content + "\x1b[0m" -} diff --git a/vendor/github.com/docker/cli/internal/tui/colors.go b/vendor/github.com/docker/cli/internal/tui/colors.go deleted file mode 100644 index c36dfabc..00000000 --- a/vendor/github.com/docker/cli/internal/tui/colors.go +++ /dev/null @@ -1,33 +0,0 @@ -// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: -//go:build go1.22 - -package tui - -import ( - "github.com/morikuni/aec" -) - -var ( - ColorTitle = aec.NewBuilder(aec.DefaultF, aec.Bold).ANSI - ColorPrimary = aec.NewBuilder(aec.DefaultF, aec.Bold).ANSI - ColorSecondary = aec.DefaultF - ColorTertiary = aec.NewBuilder(aec.DefaultF, aec.Faint).ANSI - ColorLink = aec.NewBuilder(aec.LightCyanF, aec.Underline).ANSI - ColorWarning = aec.LightYellowF - ColorFlag = aec.NewBuilder(aec.Bold).ANSI - ColorNone = aec.ANSI(noColor{}) -) - -type noColor struct{} - -func (a noColor) With(_ ...aec.ANSI) aec.ANSI { - return a -} - -func (a noColor) Apply(s string) string { - return s -} - -func (a noColor) String() string { - return "" -} diff --git a/vendor/github.com/docker/cli/internal/tui/count.go b/vendor/github.com/docker/cli/internal/tui/count.go deleted file mode 100644 index 319776e1..00000000 --- a/vendor/github.com/docker/cli/internal/tui/count.go +++ /dev/null @@ -1,70 +0,0 @@ -// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: -//go:build go1.22 - -package tui - -import ( - "strings" - - "github.com/mattn/go-runewidth" -) - -func cleanANSI(s string) string { - for { - start := strings.Index(s, "\x1b") - if start == -1 { - return s - } - end := strings.Index(s[start:], "m") - if end == -1 { - return s - } - s = s[:start] + s[start+end+1:] - } -} - -// Width returns the width of the string, ignoring ANSI escape codes. -// Not all ANSI escape codes are supported yet. -func Width(s string) int { - return runewidth.StringWidth(cleanANSI(s)) -} - -// Ellipsis truncates a string to a given number of runes with an ellipsis at the end. -// It tries to persist the ANSI escape sequences. -func Ellipsis(s string, length int) string { - out := make([]rune, 0, length) - ln := 0 - inEscape := false - tooLong := false - - for _, r := range s { - if r == '\x1b' { - out = append(out, r) - inEscape = true - continue - } - if inEscape { - out = append(out, r) - if r == 'm' { - inEscape = false - if tooLong { - break - } - } - continue - } - - ln += 1 - if ln == length { - tooLong = true - } - if !tooLong { - out = append(out, r) - } - } - - if tooLong { - return string(out) + "…" - } - return string(out) -} diff --git a/vendor/github.com/docker/cli/internal/tui/note.go b/vendor/github.com/docker/cli/internal/tui/note.go deleted file mode 100644 index c955b8cd..00000000 --- a/vendor/github.com/docker/cli/internal/tui/note.go +++ /dev/null @@ -1,39 +0,0 @@ -// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: -//go:build go1.22 - -package tui - -import ( - "fmt" - "strings" - - "github.com/morikuni/aec" -) - -var InfoHeader = Str{ - Plain: " Info -> ", - Fancy: aec.Bold.Apply(aec.LightCyanB.Apply(aec.BlackF.Apply("i")) + " " + aec.LightCyanF.Apply("Info → ")), -} - -func (o Output) PrintNote(format string, args ...any) { - if o.isTerminal { - // TODO: Handle all flags - format = strings.ReplaceAll(format, "--platform", ColorFlag.Apply("--platform")) - } - - header := o.Sprint(InfoHeader) - - _, _ = fmt.Fprint(o, "\n", header) - s := fmt.Sprintf(format, args...) - for idx, line := range strings.Split(s, "\n") { - if idx > 0 { - _, _ = fmt.Fprint(o, strings.Repeat(" ", Width(header))) - } - - l := line - if o.isTerminal { - l = aec.Italic.Apply(l) - } - _, _ = fmt.Fprintln(o, l) - } -} diff --git a/vendor/github.com/docker/cli/internal/tui/output.go b/vendor/github.com/docker/cli/internal/tui/output.go deleted file mode 100644 index 7fc194ac..00000000 --- a/vendor/github.com/docker/cli/internal/tui/output.go +++ /dev/null @@ -1,62 +0,0 @@ -// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: -//go:build go1.22 - -package tui - -import ( - "fmt" - - "github.com/docker/cli/cli/streams" - "github.com/morikuni/aec" -) - -type Output struct { - *streams.Out - isTerminal bool -} - -type terminalPrintable interface { - String(isTerminal bool) string -} - -func NewOutput(out *streams.Out) Output { - return Output{ - Out: out, - isTerminal: out.IsTerminal(), - } -} - -func (o Output) Color(clr aec.ANSI) aec.ANSI { - if o.isTerminal { - return clr - } - return ColorNone -} - -func (o Output) Sprint(all ...any) string { - var out []any - for _, p := range all { - if s, ok := p.(terminalPrintable); ok { - out = append(out, s.String(o.isTerminal)) - } else { - out = append(out, p) - } - } - return fmt.Sprint(out...) -} - -func (o Output) PrintlnWithColor(clr aec.ANSI, args ...any) { - msg := o.Sprint(args...) - if o.isTerminal { - msg = clr.Apply(msg) - } - _, _ = fmt.Fprintln(o.Out, msg) -} - -func (o Output) Println(p ...any) { - _, _ = fmt.Fprintln(o.Out, o.Sprint(p...)) -} - -func (o Output) Print(p ...any) { - _, _ = fmt.Print(o.Out, o.Sprint(p...)) -} diff --git a/vendor/github.com/docker/cli/internal/tui/str.go b/vendor/github.com/docker/cli/internal/tui/str.go deleted file mode 100644 index 490e474f..00000000 --- a/vendor/github.com/docker/cli/internal/tui/str.go +++ /dev/null @@ -1,19 +0,0 @@ -// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: -//go:build go1.22 - -package tui - -type Str struct { - // Fancy is the fancy string representation of the string. - Fancy string - - // Plain is the plain string representation of the string. - Plain string -} - -func (p Str) String(isTerminal bool) string { - if isTerminal { - return p.Fancy - } - return p.Plain -} diff --git a/vendor/github.com/docker/cli/opts/network.go b/vendor/github.com/docker/cli/opts/network.go index 2ce5dff1..413aec7b 100644 --- a/vendor/github.com/docker/cli/opts/network.go +++ b/vendor/github.com/docker/cli/opts/network.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "regexp" - "strconv" "strings" ) @@ -17,7 +16,6 @@ const ( networkOptMacAddress = "mac-address" networkOptLinkLocalIP = "link-local-ip" driverOpt = "driver-opt" - gwPriorityOpt = "gw-priority" ) // NetworkAttachmentOpts represents the network options for endpoint creation @@ -30,7 +28,6 @@ type NetworkAttachmentOpts struct { IPv6Address string LinkLocalIPs []string MacAddress string - GwPriority int } // NetworkOpt represents a network config in swarm mode. @@ -86,11 +83,6 @@ func (n *NetworkOpt) Set(value string) error { //nolint:gocyclo netOpt.DriverOpts = make(map[string]string) } netOpt.DriverOpts[key] = val - case gwPriorityOpt: - netOpt.GwPriority, err = strconv.Atoi(val) - if err != nil { - return fmt.Errorf("invalid gw-priority: %w", err) - } default: return errors.New("invalid field key " + key) } diff --git a/vendor/github.com/docker/docker/pkg/ioutils/fswriters_deprecated.go b/vendor/github.com/docker/docker/pkg/ioutils/fswriters_deprecated.go new file mode 100644 index 00000000..c3cee16d --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/ioutils/fswriters_deprecated.go @@ -0,0 +1,44 @@ +package ioutils + +import ( + "io" + "os" + + "github.com/docker/docker/pkg/atomicwriter" +) + +// NewAtomicFileWriter returns WriteCloser so that writing to it writes to a +// temporary file and closing it atomically changes the temporary file to +// destination path. Writing and closing concurrently is not allowed. +// NOTE: umask is not considered for the file's permissions. +// +// Deprecated: use [atomicwriter.New] instead. +func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, error) { + return atomicwriter.New(filename, perm) +} + +// AtomicWriteFile atomically writes data to a file named by filename and with the specified permission bits. +// NOTE: umask is not considered for the file's permissions. +// +// Deprecated: use [atomicwriter.WriteFile] instead. +func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error { + return atomicwriter.WriteFile(filename, data, perm) +} + +// AtomicWriteSet is used to atomically write a set +// of files and ensure they are visible at the same time. +// Must be committed to a new directory. +// +// Deprecated: use [atomicwriter.WriteSet] instead. +type AtomicWriteSet = atomicwriter.WriteSet + +// NewAtomicWriteSet creates a new atomic write set to +// atomically create a set of files. The given directory +// is used as the base directory for storing files before +// commit. If no temporary directory is given the system +// default is used. +// +// Deprecated: use [atomicwriter.NewWriteSet] instead. +func NewAtomicWriteSet(tmpDir string) (*atomicwriter.WriteSet, error) { + return atomicwriter.NewWriteSet(tmpDir) +} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/readers.go b/vendor/github.com/docker/docker/pkg/ioutils/readers.go new file mode 100644 index 00000000..9ddba246 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/ioutils/readers.go @@ -0,0 +1,118 @@ +package ioutils // import "github.com/docker/docker/pkg/ioutils" + +import ( + "context" + "io" + "runtime/debug" + "sync/atomic" + + "github.com/containerd/log" +) + +// readCloserWrapper wraps an io.Reader, and implements an io.ReadCloser +// It calls the given callback function when closed. It should be constructed +// with NewReadCloserWrapper +type readCloserWrapper struct { + io.Reader + closer func() error + closed atomic.Bool +} + +// Close calls back the passed closer function +func (r *readCloserWrapper) Close() error { + if !r.closed.CompareAndSwap(false, true) { + subsequentCloseWarn("ReadCloserWrapper") + return nil + } + return r.closer() +} + +// NewReadCloserWrapper wraps an io.Reader, and implements an io.ReadCloser. +// It calls the given callback function when closed. +func NewReadCloserWrapper(r io.Reader, closer func() error) io.ReadCloser { + return &readCloserWrapper{ + Reader: r, + closer: closer, + } +} + +// cancelReadCloser wraps an io.ReadCloser with a context for cancelling read +// operations. +type cancelReadCloser struct { + cancel func() + pR *io.PipeReader // Stream to read from + pW *io.PipeWriter + closed atomic.Bool +} + +// NewCancelReadCloser creates a wrapper that closes the ReadCloser when the +// context is cancelled. The returned io.ReadCloser must be closed when it is +// no longer needed. +func NewCancelReadCloser(ctx context.Context, in io.ReadCloser) io.ReadCloser { + pR, pW := io.Pipe() + + // Create a context used to signal when the pipe is closed + doneCtx, cancel := context.WithCancel(context.Background()) + + p := &cancelReadCloser{ + cancel: cancel, + pR: pR, + pW: pW, + } + + go func() { + _, err := io.Copy(pW, in) + select { + case <-ctx.Done(): + // If the context was closed, p.closeWithError + // was already called. Calling it again would + // change the error that Read returns. + default: + p.closeWithError(err) + } + in.Close() + }() + go func() { + for { + select { + case <-ctx.Done(): + p.closeWithError(ctx.Err()) + case <-doneCtx.Done(): + return + } + } + }() + + return p +} + +// Read wraps the Read method of the pipe that provides data from the wrapped +// ReadCloser. +func (p *cancelReadCloser) Read(buf []byte) (n int, err error) { + return p.pR.Read(buf) +} + +// closeWithError closes the wrapper and its underlying reader. It will +// cause future calls to Read to return err. +func (p *cancelReadCloser) closeWithError(err error) { + p.pW.CloseWithError(err) + p.cancel() +} + +// Close closes the wrapper its underlying reader. It will cause +// future calls to Read to return io.EOF. +func (p *cancelReadCloser) Close() error { + if !p.closed.CompareAndSwap(false, true) { + subsequentCloseWarn("cancelReadCloser") + return nil + } + p.closeWithError(io.EOF) + return nil +} + +func subsequentCloseWarn(name string) { + log.G(context.TODO()).Error("subsequent attempt to close " + name) + if log.GetLevel() >= log.DebugLevel { + log.G(context.TODO()).Errorf("stack trace: %s", string(debug.Stack())) + } +} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go b/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go new file mode 100644 index 00000000..010db59f --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go @@ -0,0 +1,96 @@ +package ioutils // import "github.com/docker/docker/pkg/ioutils" + +import ( + "io" + "sync" +) + +// WriteFlusher wraps the Write and Flush operation ensuring that every write +// is a flush. In addition, the Close method can be called to intercept +// Read/Write calls if the targets lifecycle has already ended. +type WriteFlusher struct { + w io.Writer + flusher flusher + flushed chan struct{} + flushedOnce sync.Once + closed chan struct{} + closeLock sync.Mutex +} + +type flusher interface { + Flush() +} + +func (wf *WriteFlusher) Write(b []byte) (n int, err error) { + select { + case <-wf.closed: + return 0, io.EOF + default: + } + + n, err = wf.w.Write(b) + wf.Flush() // every write is a flush. + return n, err +} + +// Flush the stream immediately. +func (wf *WriteFlusher) Flush() { + select { + case <-wf.closed: + return + default: + } + + wf.flushedOnce.Do(func() { + close(wf.flushed) + }) + wf.flusher.Flush() +} + +// Flushed returns the state of flushed. +// If it's flushed, return true, or else it return false. +func (wf *WriteFlusher) Flushed() bool { + // BUG(stevvooe): Remove this method. Its use is inherently racy. Seems to + // be used to detect whether or a response code has been issued or not. + // Another hook should be used instead. + var flushed bool + select { + case <-wf.flushed: + flushed = true + default: + } + return flushed +} + +// Close closes the write flusher, disallowing any further writes to the +// target. After the flusher is closed, all calls to write or flush will +// result in an error. +func (wf *WriteFlusher) Close() error { + wf.closeLock.Lock() + defer wf.closeLock.Unlock() + + select { + case <-wf.closed: + return io.EOF + default: + close(wf.closed) + } + return nil +} + +// nopFlusher represents a type which flush operation is nop. +type nopFlusher struct{} + +// Flush is a nop operation. +func (f *nopFlusher) Flush() {} + +// NewWriteFlusher returns a new WriteFlusher. +func NewWriteFlusher(w io.Writer) *WriteFlusher { + var fl flusher + if f, ok := w.(flusher); ok { + fl = f + } else { + fl = &nopFlusher{} + } + return &WriteFlusher{w: w, flusher: fl, closed: make(chan struct{}), flushed: make(chan struct{})} +} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writers.go b/vendor/github.com/docker/docker/pkg/ioutils/writers.go new file mode 100644 index 00000000..9c2d5d3b --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/ioutils/writers.go @@ -0,0 +1,28 @@ +package ioutils // import "github.com/docker/docker/pkg/ioutils" + +import ( + "io" + "sync/atomic" +) + +type writeCloserWrapper struct { + io.Writer + closer func() error + closed atomic.Bool +} + +func (r *writeCloserWrapper) Close() error { + if !r.closed.CompareAndSwap(false, true) { + subsequentCloseWarn("WriteCloserWrapper") + return nil + } + return r.closer() +} + +// NewWriteCloserWrapper returns a new io.WriteCloser. +func NewWriteCloserWrapper(r io.Writer, closer func() error) io.WriteCloser { + return &writeCloserWrapper{ + Writer: r, + closer: closer, + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 234e96e6..b7f12175 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -229,7 +229,7 @@ github.com/davecgh/go-spew/spew # github.com/distribution/reference v0.6.0 ## explicit; go 1.20 github.com/distribution/reference -# github.com/docker/cli v28.0.0-rc.1+incompatible +# github.com/docker/cli v27.5.1+incompatible ## explicit github.com/docker/cli/cli github.com/docker/cli/cli-plugins/hooks @@ -258,7 +258,6 @@ github.com/docker/cli/cli/registry/client github.com/docker/cli/cli/streams github.com/docker/cli/cli/trust github.com/docker/cli/cli/version -github.com/docker/cli/internal/tui github.com/docker/cli/opts github.com/docker/cli/pkg/kvfile github.com/docker/cli/templates @@ -312,6 +311,7 @@ github.com/docker/docker/pkg/archive github.com/docker/docker/pkg/atomicwriter github.com/docker/docker/pkg/homedir github.com/docker/docker/pkg/idtools +github.com/docker/docker/pkg/ioutils github.com/docker/docker/pkg/jsonmessage github.com/docker/docker/pkg/namesgenerator github.com/docker/docker/pkg/stdcopy