Files
docker-cli/cli/command/image/pull.go
Sebastiaan van Stijn b3df92053d add completion for docker image pull
With this patch, completion is provided for images already present
in the local image cache to help pulling the latest version of the
same tag;

    docker pull go<tab>
    golang:1.12    golang:1.18.0  golang:1.21    golang:1.24    gopher:latest
    golang:1.13    golang:1.20    golang:1.23    golang:latest

    docker pull golang:<tab>
    1.12    1.13    1.18.0  1.20    1.21    1.23    1.24    latest

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 5bf3c6793d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-03 15:42:07 +02:00

103 lines
3.1 KiB
Go

package image
import (
"context"
"fmt"
"strings"
"github.com/distribution/reference"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/trust"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
// pullOptions defines what and how to pull.
type pullOptions struct {
remote string
all bool
platform string
quiet bool
untrusted bool
}
// NewPullCommand creates a new `docker pull` command
//
// Deprecated: Do not import commands directly. They will be removed in a future release.
func NewPullCommand(dockerCLI command.Cli) *cobra.Command {
return newPullCommand(dockerCLI)
}
// newPullCommand creates a new `docker pull` command
func newPullCommand(dockerCLI command.Cli) *cobra.Command {
var opts pullOptions
cmd := &cobra.Command{
Use: "pull [OPTIONS] NAME[:TAG|@DIGEST]",
Short: "Download an image from a registry",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.remote = args[0]
return runPull(cmd.Context(), dockerCLI, opts)
},
Annotations: map[string]string{
"category-top": "5",
"aliases": "docker image pull, docker pull",
},
// Complete with local images to help pulling the latest version
// of images that are in the image cache.
ValidArgsFunction: completion.ImageNames(dockerCLI, 1),
}
flags := cmd.Flags()
flags.BoolVarP(&opts.all, "all-tags", "a", false, "Download all tagged images in the repository")
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Suppress verbose output")
addPlatformFlag(flags, &opts.platform)
flags.BoolVar(&opts.untrusted, "disable-content-trust", !dockerCLI.ContentTrustEnabled(), "Skip image verification")
_ = cmd.RegisterFlagCompletionFunc("platform", completion.Platforms)
return cmd
}
// runPull performs a pull against the engine based on the specified options
func runPull(ctx context.Context, dockerCLI command.Cli, opts pullOptions) error {
distributionRef, err := reference.ParseNormalizedNamed(opts.remote)
switch {
case err != nil:
return err
case opts.all && !reference.IsNameOnly(distributionRef):
return errors.New("tag can't be used with --all-tags/-a")
case !opts.all && reference.IsNameOnly(distributionRef):
distributionRef = reference.TagNameOnly(distributionRef)
if tagged, ok := distributionRef.(reference.Tagged); ok && !opts.quiet {
_, _ = fmt.Fprintln(dockerCLI.Out(), "Using default tag:", tagged.Tag())
}
}
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, authResolver(dockerCLI), distributionRef.String())
if err != nil {
return err
}
// Check if reference has a digest
_, isCanonical := distributionRef.(reference.Canonical)
if !opts.untrusted && !isCanonical {
err = trustedPull(ctx, dockerCLI, imgRefAndAuth, opts)
} else {
err = imagePullPrivileged(ctx, dockerCLI, imgRefAndAuth, opts)
}
if err != nil {
if strings.Contains(err.Error(), "when fetching 'plugin'") {
return errors.New(err.Error() + " - Use `docker plugin install`")
}
return err
}
_, _ = fmt.Fprintln(dockerCLI.Out(), imgRefAndAuth.Reference().String())
return nil
}