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 <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2022-11-11 15:02:10 +01:00
parent 2bf5e1879e
commit 53757ea337
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
4 changed files with 43 additions and 29 deletions

View file

@ -32,7 +32,7 @@ func FamiliarString(ref Reference) string {
} }
// FamiliarMatch reports whether ref matches the specified pattern. // 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) { func FamiliarMatch(pattern string, ref Reference) (bool, error) {
matched, err := path.Match(pattern, FamiliarString(ref)) matched, err := path.Match(pattern, FamiliarString(ref))
if namedRef, isNamed := ref.(Named); isNamed && !matched { if namedRef, isNamed := ref.(Named); isNamed && !matched {

View file

@ -54,31 +54,43 @@ func ParseNormalizedNamed(s string) (Named, error) {
return named, nil return named, nil
} }
// ParseDockerRef normalizes the image reference following the docker convention. This is added // namedTaggedDigested is a reference that has both a tag and a digest.
// mainly for backward compatibility. type namedTaggedDigested interface {
// The reference returned can only be either tagged or digested. For reference contains both tag NamedTagged
// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@ Digested
// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as }
// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa.
// 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) { func ParseDockerRef(ref string) (Named, error) {
named, err := ParseNormalizedNamed(ref) named, err := ParseNormalizedNamed(ref)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if _, ok := named.(NamedTagged); ok { if canonical, ok := named.(namedTaggedDigested); ok {
if canonical, ok := named.(Canonical); ok { // The reference is both tagged and digested; only return digested.
// The reference is both tagged and digested, only newNamed, err := WithName(canonical.Name())
// return digested. if err != nil {
newNamed, err := WithName(canonical.Name()) return nil, err
if err != nil {
return nil, err
}
newCanonical, err := WithDigest(newNamed, canonical.Digest())
if err != nil {
return nil, err
}
return newCanonical, nil
} }
return WithDigest(newNamed, canonical.Digest())
} }
return TagNameOnly(named), nil return TagNameOnly(named), nil
} }

View file

@ -146,7 +146,7 @@ type namedRepository interface {
Path() string 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 { func Domain(named Named) string {
if r, ok := named.(namedRepository); ok { if r, ok := named.(namedRepository); ok {
return r.Domain() return r.Domain()
@ -155,7 +155,7 @@ func Domain(named Named) string {
return domain 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) { func Path(named Named) (name string) {
if r, ok := named.(namedRepository); ok { if r, ok := named.(namedRepository); ok {
return r.Path() return r.Path()

View file

@ -20,14 +20,16 @@ import (
"sort" "sort"
) )
// Sort sorts string references preferring higher information references // Sort sorts string references preferring higher information references.
//
// The precedence is as follows: // The precedence is as follows:
// 1. Name + Tag + Digest //
// 2. Name + Tag // 1. [Named] + [Tagged] + [Digested] (e.g., "docker.io/library/busybox:latest@sha256:<digest>")
// 3. Name + Digest // 2. [Named] + [Tagged] (e.g., "docker.io/library/busybox:latest")
// 4. Name // 3. [Named] + [Digested] (e.g., "docker.io/library/busybo@sha256:<digest>")
// 5. Digest // 4. [Named] (e.g., "docker.io/library/busybox")
// 6. Parse error // 5. [Digested] (e.g., "docker.io@sha256:<digest>")
// 6. Parse error
func Sort(references []string) []string { func Sort(references []string) []string {
var prefs []Reference var prefs []Reference
var bad []string var bad []string