|
| 1 | +package packager |
| 2 | + |
| 3 | +// Borrow from "github.com/containers/image" with love <3 |
| 4 | +// https://github.com/containers/image/blob/aa915b75e867d14f6cb486a4fcc7d7c91cf4ca0a/docker/reference/regexp.go |
| 5 | + |
| 6 | +import ( |
| 7 | + "regexp" |
| 8 | + "strings" |
| 9 | +) |
| 10 | + |
| 11 | +const ( |
| 12 | + // alphaNumeric defines the alpha numeric atom, typically a |
| 13 | + // component of names. This only allows lower case characters and digits. |
| 14 | + alphaNumeric = `[a-z0-9]+` |
| 15 | + |
| 16 | + // separator defines the separators allowed to be embedded in name |
| 17 | + // components. This allow one period, one or two underscore and multiple |
| 18 | + // dashes. Repeated dashes and underscores are intentionally treated |
| 19 | + // differently. In order to support valid hostnames as name components, |
| 20 | + // supporting repeated dash was added. Additionally double underscore is |
| 21 | + // now allowed as a separator to loosen the restriction for previously |
| 22 | + // supported names. |
| 23 | + separator = `(?:[._]|__|[-]*)` |
| 24 | + |
| 25 | + // repository name to start with a component as defined by DomainRegexp |
| 26 | + // and followed by an optional port. |
| 27 | + domainComponent = `(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])` |
| 28 | + |
| 29 | + // The string counterpart for TagRegexp. |
| 30 | + tag = `[\w][\w.-]{0,127}` |
| 31 | + |
| 32 | + // The string counterpart for DigestRegexp. |
| 33 | + digestPat = `[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][[:xdigit:]]{32,}` |
| 34 | +) |
| 35 | + |
| 36 | +var ( |
| 37 | + // nameComponent restricts registry path component names to start |
| 38 | + // with at least one letter or number, with following parts able to be |
| 39 | + // separated by one period, one or two underscore and multiple dashes. |
| 40 | + nameComponent = expression( |
| 41 | + alphaNumeric, |
| 42 | + optional(repeated(separator, alphaNumeric))) |
| 43 | + |
| 44 | + domain = expression( |
| 45 | + domainComponent, |
| 46 | + optional(repeated(literal(`.`), domainComponent)), |
| 47 | + optional(literal(`:`), `[0-9]+`)) |
| 48 | + |
| 49 | + namePat = expression( |
| 50 | + optional(domain, literal(`/`)), |
| 51 | + nameComponent, |
| 52 | + optional(repeated(literal(`/`), nameComponent))) |
| 53 | + |
| 54 | + referencePat = anchored(capture(namePat), |
| 55 | + optional(literal(":"), capture(tag)), |
| 56 | + optional(literal("@"), capture(digestPat))) |
| 57 | + |
| 58 | + ReferenceRegexp = re(referencePat) |
| 59 | +) |
| 60 | + |
| 61 | +// re compiles the string to a regular expression. |
| 62 | +var re = regexp.MustCompile |
| 63 | + |
| 64 | +// literal compiles s into a literal regular expression, escaping any regexp |
| 65 | +// reserved characters. |
| 66 | +func literal(s string) string { |
| 67 | + return regexp.QuoteMeta(s) |
| 68 | +} |
| 69 | + |
| 70 | +// expression defines a full expression, where each regular expression must |
| 71 | +// follow the previous. |
| 72 | +func expression(res ...string) string { |
| 73 | + return strings.Join(res, "") |
| 74 | +} |
| 75 | + |
| 76 | +// optional wraps the expression in a non-capturing group and makes the |
| 77 | +// production optional. |
| 78 | +func optional(res ...string) string { |
| 79 | + return group(expression(res...)) + `?` |
| 80 | +} |
| 81 | + |
| 82 | +// repeated wraps the regexp in a non-capturing group to get one or more |
| 83 | +// matches. |
| 84 | +func repeated(res ...string) string { |
| 85 | + return group(expression(res...)) + `+` |
| 86 | +} |
| 87 | + |
| 88 | +// group wraps the regexp in a non-capturing group. |
| 89 | +func group(res ...string) string { |
| 90 | + return `(?:` + expression(res...) + `)` |
| 91 | +} |
| 92 | + |
| 93 | +// capture wraps the expression in a capturing group. |
| 94 | +func capture(res ...string) string { |
| 95 | + return `(` + expression(res...) + `)` |
| 96 | +} |
| 97 | + |
| 98 | +// anchored anchors the regular expression by adding start and end delimiters. |
| 99 | +func anchored(res ...string) string { |
| 100 | + return `^` + expression(res...) + `$` |
| 101 | +} |
0 commit comments