diff --git a/reference/reference.go b/reference/reference.go index bb09fa25d..5b3e08ee4 100644 --- a/reference/reference.go +++ b/reference/reference.go @@ -24,6 +24,7 @@ package reference import ( "errors" "fmt" + "strings" "github.com/docker/distribution/digest" ) @@ -43,6 +44,9 @@ var ( // ErrDigestInvalidFormat represents an error while trying to parse a string as a tag. ErrDigestInvalidFormat = errors.New("invalid digest format") + // ErrNameContainsUppercase is returned for invalid repository names that contain uppercase characters. + ErrNameContainsUppercase = errors.New("repository name must be lowercase") + // ErrNameEmpty is returned for empty, invalid repository names. ErrNameEmpty = errors.New("repository name must have at least one component") @@ -149,7 +153,9 @@ func Parse(s string) (Reference, error) { if s == "" { return nil, ErrNameEmpty } - // TODO(dmcgowan): Provide more specific and helpful error + if ReferenceRegexp.FindStringSubmatch(strings.ToLower(s)) != nil { + return nil, ErrNameContainsUppercase + } return nil, ErrReferenceInvalidFormat } diff --git a/reference/reference_test.go b/reference/reference_test.go index cde1a7a2e..f60cf093e 100644 --- a/reference/reference_test.go +++ b/reference/reference_test.go @@ -95,6 +95,25 @@ func TestReferenceParse(t *testing.T) { input: "validname@invaliddigest:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", err: digest.ErrDigestUnsupported, }, + { + input: "Uppercase:tag", + err: ErrNameContainsUppercase, + }, + // FIXME "Uppercase" is incorrectly handled as a domain-name here, therefore passes. + // See https://github.com/docker/distribution/pull/1778, and https://github.com/docker/docker/pull/20175 + //{ + // input: "Uppercase/lowercase:tag", + // err: ErrNameContainsUppercase, + //}, + { + input: "test:5000/Uppercase/lowercase:tag", + err: ErrNameContainsUppercase, + }, + { + input: "lowercase:Uppercase", + repository: "lowercase", + tag: "Uppercase", + }, { input: strings.Repeat("a/", 128) + "a:tag", err: ErrNameTooLong,