Update regexp to support repeated dash and double underscore
In order to support valid hostnames as name components, supporting repeated dash was added. Additionally double underscore is now allowed as a separator to loosen the restriction for previously supported names. Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
This commit is contained in:
parent
bcda04d6cd
commit
6bd5b8c24e
3 changed files with 85 additions and 10 deletions
|
@ -8,12 +8,13 @@
|
||||||
// // repository.go
|
// // repository.go
|
||||||
// repository := hostname ['/' component]+
|
// repository := hostname ['/' component]+
|
||||||
// hostname := hostcomponent [':' port-number]
|
// hostname := hostcomponent [':' port-number]
|
||||||
// component := alpha-numeric [separator alpha-numeric]*
|
// component := subcomponent [separator subcomponent]*
|
||||||
|
// subcomponent := alpha-numeric ['-'* alpha-numeric]*
|
||||||
// hostcomponent := [hostpart '.']* hostpart
|
// hostcomponent := [hostpart '.']* hostpart
|
||||||
// alpha-numeric := /[a-zA-Z0-9]+/
|
// alpha-numeric := /[a-z0-9]+/
|
||||||
// separator := /[_-]/
|
// separator := /([_.]|__)/
|
||||||
// port-number := /[0-9]+/
|
// port-number := /[0-9]+/
|
||||||
// hostpart := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
|
// hostpart := /([a-z0-9]|[a-z0-9][a-z0-9-]*[a-z0-9])/
|
||||||
//
|
//
|
||||||
// // tag.go
|
// // tag.go
|
||||||
// tag := /[\w][\w.-]{0,127}/
|
// tag := /[\w][\w.-]{0,127}/
|
||||||
|
|
|
@ -3,14 +3,19 @@ package reference
|
||||||
import "regexp"
|
import "regexp"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// nameSubComponentRegexp defines the part of the name which must be
|
||||||
|
// begin and end with an alphanumeric character. These characters can
|
||||||
|
// be separated by any number of dashes.
|
||||||
|
nameSubComponentRegexp = regexp.MustCompile(`[a-z0-9]+(?:[-]+[a-z0-9]+)*`)
|
||||||
|
|
||||||
// nameComponentRegexp restricts registry path component names to
|
// nameComponentRegexp restricts registry path component names to
|
||||||
// start with at least one letter or number, with following parts able to
|
// start with at least one letter or number, with following parts able to
|
||||||
// be separated by one period, dash or underscore.
|
// be separated by one period, underscore or double underscore.
|
||||||
nameComponentRegexp = regexp.MustCompile(`[a-zA-Z0-9]+(?:[._-][a-z0-9]+)*`)
|
nameComponentRegexp = regexp.MustCompile(nameSubComponentRegexp.String() + `(?:(?:[._]|__)` + nameSubComponentRegexp.String() + `)*`)
|
||||||
|
|
||||||
nameRegexp = regexp.MustCompile(`(?:` + nameComponentRegexp.String() + `/)*` + nameComponentRegexp.String())
|
nameRegexp = regexp.MustCompile(`(?:` + nameComponentRegexp.String() + `/)*` + nameComponentRegexp.String())
|
||||||
|
|
||||||
hostnameComponentRegexp = regexp.MustCompile(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`)
|
hostnameComponentRegexp = regexp.MustCompile(`(?:[a-z0-9]|[a-z0-9][a-z0-9-]*[a-z0-9])`)
|
||||||
|
|
||||||
// hostnameComponentRegexp restricts the registry hostname component of a repository name to
|
// hostnameComponentRegexp restricts the registry hostname component of a repository name to
|
||||||
// start with a component as defined by hostnameRegexp and followed by an optional port.
|
// start with a component as defined by hostnameRegexp and followed by an optional port.
|
||||||
|
|
|
@ -16,14 +16,14 @@ func checkRegexp(t *testing.T, r *regexp.Regexp, m regexpMatch) {
|
||||||
matches := r.FindStringSubmatch(m.input)
|
matches := r.FindStringSubmatch(m.input)
|
||||||
if m.match && matches != nil {
|
if m.match && matches != nil {
|
||||||
if len(matches) != (r.NumSubexp()+1) || matches[0] != m.input {
|
if len(matches) != (r.NumSubexp()+1) || matches[0] != m.input {
|
||||||
t.Fatalf("Bad match result: %#v", matches)
|
t.Fatalf("Bad match result %#v for %q", matches, m.input)
|
||||||
}
|
}
|
||||||
if len(matches) < (len(m.subs) + 1) {
|
if len(matches) < (len(m.subs) + 1) {
|
||||||
t.Errorf("Expected %d sub matches, only have %d", len(m.subs), len(matches)-1)
|
t.Errorf("Expected %d sub matches, only have %d for %q", len(m.subs), len(matches)-1, m.input)
|
||||||
}
|
}
|
||||||
for i := range m.subs {
|
for i := range m.subs {
|
||||||
if m.subs[i] != matches[i+1] {
|
if m.subs[i] != matches[i+1] {
|
||||||
t.Errorf("Unexpected submatch %d: %q, expected %q", i+1, matches[i+1], m.subs[i])
|
t.Errorf("Unexpected submatch %d: %q, expected %q for %q", i+1, matches[i+1], m.subs[i], m.input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if m.match {
|
} else if m.match {
|
||||||
|
@ -325,6 +325,75 @@ func TestFullNameRegexp(t *testing.T) {
|
||||||
match: true,
|
match: true,
|
||||||
subs: []string{"xn--7o8h.com", "myimage"},
|
subs: []string{"xn--7o8h.com", "myimage"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: "example.com/xn--7o8h.com/myimage", // 🐳.com in punycode
|
||||||
|
match: true,
|
||||||
|
subs: []string{"example.com", "xn--7o8h.com/myimage"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "example.com/some_separator__underscore/myimage",
|
||||||
|
match: true,
|
||||||
|
subs: []string{"example.com", "some_separator__underscore/myimage"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "example.com/__underscore/myimage",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "example.com/..dots/myimage",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "example.com/.dots/myimage",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "example.com/nodouble..dots/myimage",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "example.com/nodouble..dots/myimage",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "docker./docker",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: ".docker/docker",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "docker-/docker",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "-docker/docker",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "do..cker/docker",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "do__cker:8080/docker",
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "do__cker/docker",
|
||||||
|
match: true,
|
||||||
|
subs: []string{"", "do__cker/docker"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "b.gcr.io/test.example.com/my-app",
|
||||||
|
match: true,
|
||||||
|
subs: []string{"b.gcr.io", "test.example.com/my-app"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "registry.io/foo/project--id.module--name.ver---sion--name",
|
||||||
|
match: true,
|
||||||
|
subs: []string{"registry.io", "foo/project--id.module--name.ver---sion--name"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for i := range testcases {
|
for i := range testcases {
|
||||||
checkRegexp(t, anchoredNameRegexp, testcases[i])
|
checkRegexp(t, anchoredNameRegexp, testcases[i])
|
||||||
|
|
Loading…
Reference in a new issue