Merge pull request #10393 from thaJeztah/improve_reference

pkg/reference: reduce allocations and improve GoDoc
This commit is contained in:
Maksym Pavlenko 2024-06-27 18:36:24 +00:00 committed by GitHub
commit ae7d74b9e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 54 additions and 13 deletions

View File

@ -18,7 +18,6 @@ package reference
import ( import (
"errors" "errors"
"fmt"
"net/url" "net/url"
"path" "path"
"regexp" "regexp"
@ -136,8 +135,12 @@ func (r Spec) Hostname() string {
// Digest returns the digest portion of the reference spec. This may be a // Digest returns the digest portion of the reference spec. This may be a
// partial or invalid digest, which may be used to lookup a complete digest. // partial or invalid digest, which may be used to lookup a complete digest.
func (r Spec) Digest() digest.Digest { func (r Spec) Digest() digest.Digest {
_, dgst := SplitObject(r.Object) i := strings.Index(r.Object, "@")
return dgst
if i < 0 {
return ""
}
return digest.Digest(r.Object[i+1:])
} }
// String returns the normalized string for the ref. // String returns the normalized string for the ref.
@ -146,21 +149,29 @@ func (r Spec) String() string {
return r.Locator return r.Locator
} }
if r.Object[:1] == "@" { if r.Object[:1] == "@" {
return fmt.Sprintf("%v%v", r.Locator, r.Object) return r.Locator + r.Object
} }
return fmt.Sprintf("%v:%v", r.Locator, r.Object) return r.Locator + ":" + r.Object
} }
// SplitObject provides two parts of the object spec, delimited by an `@` // SplitObject provides two parts of the object spec, delimited by an "@"
// symbol. // symbol. It does not perform any validation on correctness of the values
// returned, and it's the callers' responsibility to validate the result.
// //
// Either may be empty and it is the callers job to validate them // If an "@" delimiter is found, it returns the part *including* the "@"
// appropriately. // delimiter as "tag", and the part after the "@" as digest.
//
// The example below produces "docker.io/library/ubuntu:latest@" and
// "sha256:deadbeef";
//
// t, d := SplitObject("docker.io/library/ubuntu:latest@sha256:deadbeef")
// fmt.Println(t) // docker.io/library/ubuntu:latest@
// fmt.Println(d) // sha256:deadbeef
func SplitObject(obj string) (tag string, dgst digest.Digest) { func SplitObject(obj string) (tag string, dgst digest.Digest) {
parts := strings.SplitAfterN(obj, "@", 2) if i := strings.Index(obj, "@"); i >= 0 {
if len(parts) < 2 { // Offset by one so preserve the "@" in the tag returned.
return parts[0], "" return obj[:i+1], digest.Digest(obj[i+1:])
} }
return parts[0], digest.Digest(parts[1]) return obj, ""
} }

View File

@ -192,3 +192,33 @@ func TestReferenceParser(t *testing.T) {
}) })
} }
} }
func BenchmarkSplitObject(b *testing.B) {
inputs := []string{
"",
"@",
"docker.io@",
"@digest",
"docker.io/library/redis:foo?fooo=asdf",
"docker.io/library/redis:foo@sha256:abcdef?fooo=asdf",
"docker.io/library/redis@sha256:abcdef?fooo=asdf",
"docker.io/library/redis:obj@abcdef?fooo=asdf",
"localhost:5000/library/redis:obj@abcdef?fooo=asdf",
"/docker.io/library/redis:obj@abcdef?fooo=asdf",
"docker.io/library/redis?fooo=asdf",
"sub-dom1.foo.com/bar/baz/quux:latest",
"sub-dom1.foo.com/bar/baz/quux:some-long-tag",
"b.gcr.io/test.example.com/my-app:test.example.com",
"xn--n3h.com/myimage:xn--n3h.com", // ☃.com in punycode
"xn--7o8h.com/myimage:xn--7o8h.com@sha512:fffffff",
"http://xn--7o8h.com/myimage:xn--7o8h.com@sha512:fffffff",
}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for _, input := range inputs {
_, _ = SplitObject(input)
}
}
}