Usability improvements for reference package
Various improvements motivated by early real-world use in engine code under development: - Make `WithDigest` return `Canonical`, since the return value always has a name and a digest. - Introduce a `NamedTagged` type, which can be used for strongly typing cases where something must have a name and a tag. - Rename `ParseNamed` to `WithName`, and create a `ParseNamed` that accepts tags and digests (returning a `Named` type). The new `ParseNamed` makes code using the reference package much less verbose, since typical use cases require a name, and this is an additional type assertion and error case after every `Parse` call. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
parent
4c4112bdcf
commit
16eea0cc47
2 changed files with 31 additions and 9 deletions
|
@ -114,6 +114,12 @@ type Tagged interface {
|
||||||
Tag() string
|
Tag() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NamedTagged is an object including a name and tag.
|
||||||
|
type NamedTagged interface {
|
||||||
|
Named
|
||||||
|
Tag() string
|
||||||
|
}
|
||||||
|
|
||||||
// Digested is an object which has a digest
|
// Digested is an object which has a digest
|
||||||
// in which it can be referenced by
|
// in which it can be referenced by
|
||||||
type Digested interface {
|
type Digested interface {
|
||||||
|
@ -178,10 +184,26 @@ func Parse(s string) (Reference, error) {
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseNamed parses the input string and returns a named
|
// ParseNamed parses s and returns a syntactically valid reference implementing
|
||||||
// object representing the given string. If the input is
|
// the Named interface. The reference must have a name, otherwise an error is
|
||||||
// invalid ErrReferenceInvalidFormat will be returned.
|
// returned.
|
||||||
func ParseNamed(name string) (Named, error) {
|
// If an error was encountered it is returned, along with a nil Reference.
|
||||||
|
// NOTE: ParseNamed will not handle short digests.
|
||||||
|
func ParseNamed(s string) (Named, error) {
|
||||||
|
ref, err := Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
named, isNamed := ref.(Named)
|
||||||
|
if !isNamed {
|
||||||
|
return nil, fmt.Errorf("reference %s has no name", ref.String())
|
||||||
|
}
|
||||||
|
return named, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithName returns a named object representing the given string. If the input
|
||||||
|
// is invalid ErrReferenceInvalidFormat will be returned.
|
||||||
|
func WithName(name string) (Named, error) {
|
||||||
if !anchoredNameRegexp.MatchString(name) {
|
if !anchoredNameRegexp.MatchString(name) {
|
||||||
return nil, ErrReferenceInvalidFormat
|
return nil, ErrReferenceInvalidFormat
|
||||||
}
|
}
|
||||||
|
@ -190,7 +212,7 @@ func ParseNamed(name string) (Named, error) {
|
||||||
|
|
||||||
// WithTag combines the name from "name" and the tag from "tag" to form a
|
// WithTag combines the name from "name" and the tag from "tag" to form a
|
||||||
// reference incorporating both the name and the tag.
|
// reference incorporating both the name and the tag.
|
||||||
func WithTag(name Named, tag string) (Tagged, error) {
|
func WithTag(name Named, tag string) (NamedTagged, error) {
|
||||||
if !anchoredNameRegexp.MatchString(tag) {
|
if !anchoredNameRegexp.MatchString(tag) {
|
||||||
return nil, ErrTagInvalidFormat
|
return nil, ErrTagInvalidFormat
|
||||||
}
|
}
|
||||||
|
@ -202,7 +224,7 @@ func WithTag(name Named, tag string) (Tagged, error) {
|
||||||
|
|
||||||
// WithDigest combines the name from "name" and the digest from "digest" to form
|
// WithDigest combines the name from "name" and the digest from "digest" to form
|
||||||
// a reference incorporating both the name and the digest.
|
// a reference incorporating both the name and the digest.
|
||||||
func WithDigest(name Named, digest digest.Digest) (Digested, error) {
|
func WithDigest(name Named, digest digest.Digest) (Canonical, error) {
|
||||||
if !anchoredDigestRegexp.MatchString(digest.String()) {
|
if !anchoredDigestRegexp.MatchString(digest.String()) {
|
||||||
return nil, ErrDigestInvalidFormat
|
return nil, ErrDigestInvalidFormat
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,7 +253,7 @@ func TestSplitHostname(t *testing.T) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
named, err := ParseNamed(testcase.input)
|
named, err := WithName(testcase.input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
failf("error parsing name: %s", err)
|
failf("error parsing name: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -424,7 +424,7 @@ func TestWithTag(t *testing.T) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
named, err := ParseNamed(testcase.name)
|
named, err := WithName(testcase.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
failf("error parsing name: %s", err)
|
failf("error parsing name: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -466,7 +466,7 @@ func TestWithDigest(t *testing.T) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
named, err := ParseNamed(testcase.name)
|
named, err := WithName(testcase.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
failf("error parsing name: %s", err)
|
failf("error parsing name: %s", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue