From 53757ea33788ec46df1ab8592d96afed63518c7b Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 11 Nov 2022 15:02:10 +0100 Subject: [PATCH] reference: ParseDockerRef: slight refactor, and update docs - improve documentation - remove redundant error-check - simplify interface matching, which slightly improves readability - touch-up some docs Signed-off-by: Sebastiaan van Stijn --- reference/helpers.go | 2 +- reference/normalize.go | 50 ++++++++++++++++++++++++++---------------- reference/reference.go | 4 ++-- reference/sort.go | 16 ++++++++------ 4 files changed, 43 insertions(+), 29 deletions(-) diff --git a/reference/helpers.go b/reference/helpers.go index 978df7ea..d10c7ef8 100644 --- a/reference/helpers.go +++ b/reference/helpers.go @@ -32,7 +32,7 @@ func FamiliarString(ref Reference) string { } // FamiliarMatch reports whether ref matches the specified pattern. -// See https://godoc.org/path#Match for supported patterns. +// See [path.Match] for supported patterns. func FamiliarMatch(pattern string, ref Reference) (bool, error) { matched, err := path.Match(pattern, FamiliarString(ref)) if namedRef, isNamed := ref.(Named); isNamed && !matched { diff --git a/reference/normalize.go b/reference/normalize.go index 4598bf53..fb9172ce 100644 --- a/reference/normalize.go +++ b/reference/normalize.go @@ -54,31 +54,43 @@ func ParseNormalizedNamed(s string) (Named, error) { return named, nil } -// ParseDockerRef normalizes the image reference following the docker convention. This is added -// mainly for backward compatibility. -// The reference returned can only be either tagged or digested. For reference contains both tag -// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@ -// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as -// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa. +// namedTaggedDigested is a reference that has both a tag and a digest. +type namedTaggedDigested interface { + NamedTagged + Digested +} + +// ParseDockerRef normalizes the image reference following the docker convention, +// which allows for references to contain both a tag and a digest. It returns a +// reference that is either tagged or digested. For references containing both +// a tag and a digest, it returns a digested reference. For example, the following +// reference: +// +// docker.io/library/busybox:latest@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa +// +// Is returned as a digested reference (with the ":latest" tag removed): +// +// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa +// +// References that are already "tagged" or "digested" are returned unmodified: +// +// // Already a digested reference +// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa +// +// // Already a named reference +// docker.io/library/busybox:latest func ParseDockerRef(ref string) (Named, error) { named, err := ParseNormalizedNamed(ref) if err != nil { return nil, err } - if _, ok := named.(NamedTagged); ok { - if canonical, ok := named.(Canonical); ok { - // The reference is both tagged and digested, only - // return digested. - newNamed, err := WithName(canonical.Name()) - if err != nil { - return nil, err - } - newCanonical, err := WithDigest(newNamed, canonical.Digest()) - if err != nil { - return nil, err - } - return newCanonical, nil + if canonical, ok := named.(namedTaggedDigested); ok { + // The reference is both tagged and digested; only return digested. + newNamed, err := WithName(canonical.Name()) + if err != nil { + return nil, err } + return WithDigest(newNamed, canonical.Digest()) } return TagNameOnly(named), nil } diff --git a/reference/reference.go b/reference/reference.go index b6113642..e5d889a3 100644 --- a/reference/reference.go +++ b/reference/reference.go @@ -146,7 +146,7 @@ type namedRepository interface { Path() string } -// Domain returns the domain part of the Named reference +// Domain returns the domain part of the [Named] reference. func Domain(named Named) string { if r, ok := named.(namedRepository); ok { return r.Domain() @@ -155,7 +155,7 @@ func Domain(named Named) string { return domain } -// Path returns the name without the domain part of the Named reference +// Path returns the name without the domain part of the [Named] reference. func Path(named Named) (name string) { if r, ok := named.(namedRepository); ok { return r.Path() diff --git a/reference/sort.go b/reference/sort.go index 2049c71a..416c37b0 100644 --- a/reference/sort.go +++ b/reference/sort.go @@ -20,14 +20,16 @@ import ( "sort" ) -// Sort sorts string references preferring higher information references +// Sort sorts string references preferring higher information references. +// // The precedence is as follows: -// 1. Name + Tag + Digest -// 2. Name + Tag -// 3. Name + Digest -// 4. Name -// 5. Digest -// 6. Parse error +// +// 1. [Named] + [Tagged] + [Digested] (e.g., "docker.io/library/busybox:latest@sha256:") +// 2. [Named] + [Tagged] (e.g., "docker.io/library/busybox:latest") +// 3. [Named] + [Digested] (e.g., "docker.io/library/busybo@sha256:") +// 4. [Named] (e.g., "docker.io/library/busybox") +// 5. [Digested] (e.g., "docker.io@sha256:") +// 6. Parse error func Sort(references []string) []string { var prefs []Reference var bad []string