diff --git a/pkg/name/digest.go b/pkg/name/digest.go index 5b8eb4ff4..f3c14ab8b 100644 --- a/pkg/name/digest.go +++ b/pkg/name/digest.go @@ -31,6 +31,7 @@ type Digest struct { Repository digest string original string + tag *string } var _ Reference = (*Digest)(nil) @@ -64,6 +65,15 @@ func (d Digest) String() string { return d.original } +// MaybeTagStr returns the tag string (if one was provided). Use bool return value to determine if a tag was present. +func (d Digest) MaybeTagStr() (string, bool) { + if d.tag != nil { + return *d.tag, true + } else { + return "", false + } +} + // MarshalJSON formats the digest into a string for JSON serialization. func (d Digest) MarshalJSON() ([]byte, error) { return json.Marshal(d.String()) @@ -116,8 +126,17 @@ func NewDigest(name string, opts ...Option) (Digest, error) { return Digest{}, err } + var tagStr *string tag, err := NewTag(base, opts...) if err == nil { + + // Check and see if the TagStr was provided in the original base + // If not then it's a default tag and should be ignored + maybeTag := tag.TagStr() + if strings.HasSuffix(base, tagDelim+maybeTag) { + tagStr = &maybeTag + } + base = tag.Repository.Name() } @@ -129,5 +148,6 @@ func NewDigest(name string, opts ...Option) (Digest, error) { Repository: repo, digest: dig, original: name, + tag: tagStr, }, nil } diff --git a/pkg/name/digest_test.go b/pkg/name/digest_test.go index a99fb27da..7306ea49f 100644 --- a/pkg/name/digest_test.go +++ b/pkg/name/digest_test.go @@ -132,6 +132,15 @@ func TestDigestComponents(t *testing.T) { if actualDigest != validDigest { t.Errorf("DigestStr() was incorrect for %v. Wanted: `%s` Got: `%s`", digest, validDigest, actualDigest) } + + expectedTagStr := "" + expectedOk := false + + tagStr, ok := digest.MaybeTagStr() + if tagStr != expectedTagStr || ok != expectedOk { + t.Errorf("MaybeTagStr() was incorrect for %v. Wanted: (`%s`, `%t`) Got: (`%s`, `%t`)", digest, expectedTagStr, expectedOk, tagStr, ok) + } + } func TestDigestScopes(t *testing.T) { @@ -154,6 +163,46 @@ func TestDigestScopes(t *testing.T) { } } +func TestMaybeTagStr(t *testing.T) { + t.Parallel() + + testRegistry := "gcr.io" + testRepo := "project-id/image" + testTag := "1.0" + + validations := map[string]Option{"strict": StrictValidation, "weak": WeakValidation} + + digestNameStrWithTag := testRegistry + "/" + testRepo + ":" + testTag + "@" + validDigest + for valName, opt := range validations { + digest, err := NewDigest(digestNameStrWithTag, opt) + if err != nil { + t.Fatalf("`%s` should be a valid Digest name with validation: `%s`, got error: %v", digestNameStrWithTag, valName, err) + } + + tagStr, ok := digest.MaybeTagStr() + expectedTagStr := testTag + expectedOk := true + if tagStr != expectedTagStr || ok != expectedOk { + t.Errorf("MaybeTagStr() was incorrect for %v with validation: `%s`. Wanted: (`%s`, `%t`) Got: (`%s`, `%t`)", digest, valName, expectedTagStr, expectedOk, tagStr, ok) + } + } + + digestNameStrWithoutTag := testRegistry + "/" + testRepo + "@" + validDigest + for valName, opt := range validations { + digest, err := NewDigest(digestNameStrWithoutTag, opt) + if err != nil { + t.Fatalf("`%s` should be a valid Digest name with validation: `%s`, got error: %v", digestNameStrWithoutTag, valName, err) + } + + tagStr, ok := digest.MaybeTagStr() + expectedTagStr := "" + expectedOk := false + if tagStr != expectedTagStr || ok != expectedOk { + t.Errorf("MaybeTagStr() was incorrect for %v with validation: `%s`. Wanted: (`%s`, `%t`) Got: (`%s`, `%t`)", digest, valName, expectedTagStr, expectedOk, tagStr, ok) + } + } +} + func TestJSON(t *testing.T) { t.Parallel() digestNameStr := "gcr.io/project-id/image@" + validDigest