{"action":"created","comment":{"url":"https://api.github.com/repos/docker/distribution/pulls/comments/38982626","id":38982626,"diff_hunk":"@@ -0,0 +1,231 @@\n+// Package reference provides a general type to represent any way of referencing images within the registry.\n+// Its main purpose is to abstract tags and digests (content-addressable hash).\n+//\n+// Grammar\n+//\n+// \treference                       := repository [ \":\" tag ] [ \"@\" digest ]\n+//\n+//\t// repository.go\n+//\trepository\t\t\t:= hostname ['/' component]+\n+//\thostname \t\t\t:= hostcomponent [':' port-number]\n+//\tcomponent\t\t\t:= alpha-numeric [separator alpha-numeric]*\n+//\thostcomponent                   := [hostpart '.']* hostpart\n+// \talpha-numeric\t\t\t:= /[a-zA-Z0-9]+/\n+//\tseparator\t\t\t:= /[_-]/\n+//\tport-number\t\t\t:= /[0-9]+/\n+//\thostpart                        := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/\n+//\n+//\t// tag.go\n+//\ttag                             := /[\\w][\\w.-]{0,127}/\n+//\n+//\t// from the digest package\n+//\tdigest                          := digest-algorithm \":\" digest-hex\n+//\tdigest-algorithm                := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]\n+//\tdigest-algorithm-separator      := /[+.-_]/\n+//\tdigest-algorithm-component      := /[A-Za-z][A-Za-z0-9]*/\n+//\tdigest-hex                      := /[0-9a-fA-F]{32,}/ ; Atleast 128 bit digest value\n+package reference\n+\n+import (\n+\t\"errors\"\n+\t\"fmt\"\n+\n+\t\"github.com/docker/distribution/digest\"\n+)\n+\n+const (\n+\t// NameTotalLengthMax is the maximum total number of characters in a repository name.\n+\tNameTotalLengthMax = 255\n+)\n+\n+var (\n+\t// ErrReferenceInvalidFormat represents an error while trying to parse a string as a reference.\n+\tErrReferenceInvalidFormat = errors.New(\"invalid reference format\")\n+\n+\t// ErrNameEmpty is returned for empty, invalid repository names.\n+\tErrNameEmpty = errors.New(\"repository name must have at least one component\")\n+\n+\t// ErrNameTooLong is returned when a repository name is longer than\n+\t// RepositoryNameTotalLengthMax\n+\tErrNameTooLong = fmt.Errorf(\"repository name must not be more than %v characters\", NameTotalLengthMax)\n+)\n+\n+// Reference is an opaque object reference identifier that may include\n+// modifiers such as a hostname, name, tag, and digest.\n+type Reference interface {\n+\t// String returns the full reference\n+\tString() string\n+}\n+\n+// Named is an object with a full name\n+type Named interface {\n+\tName() string\n+}\n+\n+// Tagged is an object which has a tag\n+type Tagged interface {\n+\tTag() string\n+}\n+\n+// Digested is an object which has a digest\n+// in which it can be referenced by\n+type Digested interface {\n+\tDigest() digest.Digest\n+}\n+\n+// Canonical reference is an object with a fully unique\n+// name including a name with hostname and digest\n+type Canonical interface {\n+\tReference\n+\tNamed\n+\tDigested\n+}\n+\n+// SplitHostname splits a named reference into a\n+// hostname and name string. If no valid hostname is\n+// found, the hostname is empty and the full value\n+// is returned as name\n+func SplitHostname(named Named) (string, string) {\n+\tname := named.Name()\n+\tmatch := anchoredNameRegexp.FindStringSubmatch(name)\n+\tif match == nil || len(match) != 3 {\n+\t\treturn \"\", name\n+\t}\n+\treturn match[1], match[2]\n+}\n+\n+// Parse parses s and returns a syntactically valid Reference.\n+// If an error was encountered it is returned, along with a nil Reference.\n+// NOTE: Parse will not handle short digests.\n+func Parse(s string) (Reference, error) {\n+\tmatches := ReferenceRegexp.FindStringSubmatch(s)\n+\tif matches == nil {\n+\t\tif s == \"\" {\n+\t\t\treturn nil, ErrNameEmpty\n+\t\t}\n+\t\t// TODO(dmcgowan): Provide more specific and helpful error\n+\t\treturn nil, ErrReferenceInvalidFormat\n+\t}\n+\n+\tif len(matches[1]) > NameTotalLengthMax {\n+\t\treturn nil, ErrNameTooLong\n+\t}\n+\n+\tref := reference{\n+\t\tname: matches[1],\n+\t\ttag:  matches[2],\n+\t}\n+\tif matches[3] != \"\" {\n+\t\tvar err error\n+\t\tref.digest, err = digest.ParseDigest(matches[3])\n+\t\tif err != nil {\n+\t\t\treturn nil, err\n+\t\t}\n+\t}\n+\n+\tr := getBestReferenceType(ref)\n+\tif r == nil {\n+\t\treturn nil, ErrNameEmpty\n+\t}\n+\n+\treturn r, nil\n+}\n+\n+// ValidateName validates that the given string matches the name format\n+func ValidateName(name string) error {","path":"reference/reference.go","position":135,"original_position":135,"commit_id":"de0a10f5aa8fa00e702d99740e1cc8482b612252","original_commit_id":"de0a10f5aa8fa00e702d99740e1cc8482b612252","user":{"login":"dmcgowan","id":169601,"avatar_url":"https://avatars.githubusercontent.com/u/169601?v=3","gravatar_id":"","url":"https://api.github.com/users/dmcgowan","html_url":"https://github.com/dmcgowan","followers_url":"https://api.github.com/users/dmcgowan/followers","following_url":"https://api.github.com/users/dmcgowan/following{/other_user}","gists_url":"https://api.github.com/users/dmcgowan/gists{/gist_id}","starred_url":"https://api.github.com/users/dmcgowan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dmcgowan/subscriptions","organizations_url":"https://api.github.com/users/dmcgowan/orgs","repos_url":"https://api.github.com/users/dmcgowan/repos","events_url":"https://api.github.com/users/dmcgowan/events{/privacy}","received_events_url":"https://api.github.com/users/dmcgowan/received_events","type":"User","site_admin":false},"body":"This function was used to replace a previous validation function which was used to validate repository names when passed to an exported function. I was torn between removing the validation or adding such a function. Having an explicit parse function will also do the trick.","created_at":"2015-09-08T21:28:04Z","updated_at":"2015-09-08T21:28:04Z","html_url":"https://github.com/docker/distribution/pull/963#discussion_r38982626","pull_request_url":"https://api.github.com/repos/docker/distribution/pulls/963","_links":{"self":{"href":"https://api.github.com/repos/docker/distribution/pulls/comments/38982626"},"html":{"href":"https://github.com/docker/distribution/pull/963#discussion_r38982626"},"pull_request":{"href":"https://api.github.com/repos/docker/distribution/pulls/963"}}},"pull_request":{"url":"https://api.github.com/repos/docker/distribution/pulls/963","id":44467871,"html_url":"https://github.com/docker/distribution/pull/963","diff_url":"https://github.com/docker/distribution/pull/963.diff","patch_url":"https://github.com/docker/distribution/pull/963.patch","issue_url":"https://api.github.com/repos/docker/distribution/issues/963","number":963,"state":"open","locked":false,"title":"[Carry 690] Add a new reference package abstracting tags and digests","user":{"login":"dmcgowan","id":169601,"avatar_url":"https://avatars.githubusercontent.com/u/169601?v=3","gravatar_id":"","url":"https://api.github.com/users/dmcgowan","html_url":"https://github.com/dmcgowan","followers_url":"https://api.github.com/users/dmcgowan/followers","following_url":"https://api.github.com/users/dmcgowan/following{/other_user}","gists_url":"https://api.github.com/users/dmcgowan/gists{/gist_id}","starred_url":"https://api.github.com/users/dmcgowan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dmcgowan/subscriptions","organizations_url":"https://api.github.com/users/dmcgowan/orgs","repos_url":"https://api.github.com/users/dmcgowan/repos","events_url":"https://api.github.com/users/dmcgowan/events{/privacy}","received_events_url":"https://api.github.com/users/dmcgowan/received_events","type":"User","site_admin":false},"body":"Provides a package with interfaces to represent a way of referring to objects (images, manifest, tags, blobs) irrespective of their implementation.\r\n\r\nThese references can always be represented as a parsable string and may contain different properties including..\r\n- Named - Object has a name, such as the name of the repository it belongs to\r\n- Tagged - Object has a string tag which refers to it but cannot be independently verified\r\n- Digested - Object has a digest which refers to it and can be verified\r\n\r\nOpen Questions\r\n- There is an ambiguity with the current naming in the code. Currently a reference \"Name\" is the complete repository name without a tag or digest. This \"Name\" also consists of a hostname. However currently the remaining part is also referred to as \"name\". The work \"path\" may be more appropriate but that nomenclature is currently not used for any part of a repository.","created_at":"2015-09-08T18:44:04Z","updated_at":"2015-09-08T21:28:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"373c04403c0f82cf5c7589da9a7dd894720ec5cc","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/docker/distribution/pulls/963/commits","review_comments_url":"https://api.github.com/repos/docker/distribution/pulls/963/comments","review_comment_url":"https://api.github.com/repos/docker/distribution/pulls/comments{/number}","comments_url":"https://api.github.com/repos/docker/distribution/issues/963/comments","statuses_url":"https://api.github.com/repos/docker/distribution/statuses/de0a10f5aa8fa00e702d99740e1cc8482b612252","head":{"label":"dmcgowan:reference-update","ref":"reference-update","sha":"de0a10f5aa8fa00e702d99740e1cc8482b612252","user":{"login":"dmcgowan","id":169601,"avatar_url":"https://avatars.githubusercontent.com/u/169601?v=3","gravatar_id":"","url":"https://api.github.com/users/dmcgowan","html_url":"https://github.com/dmcgowan","followers_url":"https://api.github.com/users/dmcgowan/followers","following_url":"https://api.github.com/users/dmcgowan/following{/other_user}","gists_url":"https://api.github.com/users/dmcgowan/gists{/gist_id}","starred_url":"https://api.github.com/users/dmcgowan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dmcgowan/subscriptions","organizations_url":"https://api.github.com/users/dmcgowan/orgs","repos_url":"https://api.github.com/users/dmcgowan/repos","events_url":"https://api.github.com/users/dmcgowan/events{/privacy}","received_events_url":"https://api.github.com/users/dmcgowan/received_events","type":"User","site_admin":false},"repo":{"id":28724029,"name":"distribution","full_name":"dmcgowan/distribution","owner":{"login":"dmcgowan","id":169601,"avatar_url":"https://avatars.githubusercontent.com/u/169601?v=3","gravatar_id":"","url":"https://api.github.com/users/dmcgowan","html_url":"https://github.com/dmcgowan","followers_url":"https://api.github.com/users/dmcgowan/followers","following_url":"https://api.github.com/users/dmcgowan/following{/other_user}","gists_url":"https://api.github.com/users/dmcgowan/gists{/gist_id}","starred_url":"https://api.github.com/users/dmcgowan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dmcgowan/subscriptions","organizations_url":"https://api.github.com/users/dmcgowan/orgs","repos_url":"https://api.github.com/users/dmcgowan/repos","events_url":"https://api.github.com/users/dmcgowan/events{/privacy}","received_events_url":"https://api.github.com/users/dmcgowan/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/dmcgowan/distribution","description":"The Docker toolset to pack, ship, store, and deliver content","fork":true,"url":"https://api.github.com/repos/dmcgowan/distribution","forks_url":"https://api.github.com/repos/dmcgowan/distribution/forks","keys_url":"https://api.github.com/repos/dmcgowan/distribution/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dmcgowan/distribution/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dmcgowan/distribution/teams","hooks_url":"https://api.github.com/repos/dmcgowan/distribution/hooks","issue_events_url":"https://api.github.com/repos/dmcgowan/distribution/issues/events{/number}","events_url":"https://api.github.com/repos/dmcgowan/distribution/events","assignees_url":"https://api.github.com/repos/dmcgowan/distribution/assignees{/user}","branches_url":"https://api.github.com/repos/dmcgowan/distribution/branches{/branch}","tags_url":"https://api.github.com/repos/dmcgowan/distribution/tags","blobs_url":"https://api.github.com/repos/dmcgowan/distribution/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dmcgowan/distribution/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dmcgowan/distribution/git/refs{/sha}","trees_url":"https://api.github.com/repos/dmcgowan/distribution/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dmcgowan/distribution/statuses/{sha}","languages_url":"https://api.github.com/repos/dmcgowan/distribution/languages","stargazers_url":"https://api.github.com/repos/dmcgowan/distribution/stargazers","contributors_url":"https://api.github.com/repos/dmcgowan/distribution/contributors","subscribers_url":"https://api.github.com/repos/dmcgowan/distribution/subscribers","subscription_url":"https://api.github.com/repos/dmcgowan/distribution/subscription","commits_url":"https://api.github.com/repos/dmcgowan/distribution/commits{/sha}","git_commits_url":"https://api.github.com/repos/dmcgowan/distribution/git/commits{/sha}","comments_url":"https://api.github.com/repos/dmcgowan/distribution/comments{/number}","issue_comment_url":"https://api.github.com/repos/dmcgowan/distribution/issues/comments{/number}","contents_url":"https://api.github.com/repos/dmcgowan/distribution/contents/{+path}","compare_url":"https://api.github.com/repos/dmcgowan/distribution/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dmcgowan/distribution/merges","archive_url":"https://api.github.com/repos/dmcgowan/distribution/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dmcgowan/distribution/downloads","issues_url":"https://api.github.com/repos/dmcgowan/distribution/issues{/number}","pulls_url":"https://api.github.com/repos/dmcgowan/distribution/pulls{/number}","milestones_url":"https://api.github.com/repos/dmcgowan/distribution/milestones{/number}","notifications_url":"https://api.github.com/repos/dmcgowan/distribution/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dmcgowan/distribution/labels{/name}","releases_url":"https://api.github.com/repos/dmcgowan/distribution/releases{/id}","created_at":"2015-01-02T19:42:34Z","updated_at":"2015-01-02T19:42:34Z","pushed_at":"2015-09-08T18:28:25Z","git_url":"git://github.com/dmcgowan/distribution.git","ssh_url":"git@github.com:dmcgowan/distribution.git","clone_url":"https://github.com/dmcgowan/distribution.git","svn_url":"https://github.com/dmcgowan/distribution","homepage":null,"size":3989,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"docker:master","ref":"master","sha":"7c5a9ae96d3f783c7cfbc0f27647b717d361d80d","user":{"login":"docker","id":5429470,"avatar_url":"https://avatars.githubusercontent.com/u/5429470?v=3","gravatar_id":"","url":"https://api.github.com/users/docker","html_url":"https://github.com/docker","followers_url":"https://api.github.com/users/docker/followers","following_url":"https://api.github.com/users/docker/following{/other_user}","gists_url":"https://api.github.com/users/docker/gists{/gist_id}","starred_url":"https://api.github.com/users/docker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/docker/subscriptions","organizations_url":"https://api.github.com/users/docker/orgs","repos_url":"https://api.github.com/users/docker/repos","events_url":"https://api.github.com/users/docker/events{/privacy}","received_events_url":"https://api.github.com/users/docker/received_events","type":"Organization","site_admin":false},"repo":{"id":28366058,"name":"distribution","full_name":"docker/distribution","owner":{"login":"docker","id":5429470,"avatar_url":"https://avatars.githubusercontent.com/u/5429470?v=3","gravatar_id":"","url":"https://api.github.com/users/docker","html_url":"https://github.com/docker","followers_url":"https://api.github.com/users/docker/followers","following_url":"https://api.github.com/users/docker/following{/other_user}","gists_url":"https://api.github.com/users/docker/gists{/gist_id}","starred_url":"https://api.github.com/users/docker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/docker/subscriptions","organizations_url":"https://api.github.com/users/docker/orgs","repos_url":"https://api.github.com/users/docker/repos","events_url":"https://api.github.com/users/docker/events{/privacy}","received_events_url":"https://api.github.com/users/docker/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/docker/distribution","description":"The Docker toolset to pack, ship, store, and deliver content","fork":false,"url":"https://api.github.com/repos/docker/distribution","forks_url":"https://api.github.com/repos/docker/distribution/forks","keys_url":"https://api.github.com/repos/docker/distribution/keys{/key_id}","collaborators_url":"https://api.github.com/repos/docker/distribution/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/docker/distribution/teams","hooks_url":"https://api.github.com/repos/docker/distribution/hooks","issue_events_url":"https://api.github.com/repos/docker/distribution/issues/events{/number}","events_url":"https://api.github.com/repos/docker/distribution/events","assignees_url":"https://api.github.com/repos/docker/distribution/assignees{/user}","branches_url":"https://api.github.com/repos/docker/distribution/branches{/branch}","tags_url":"https://api.github.com/repos/docker/distribution/tags","blobs_url":"https://api.github.com/repos/docker/distribution/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/docker/distribution/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/docker/distribution/git/refs{/sha}","trees_url":"https://api.github.com/repos/docker/distribution/git/trees{/sha}","statuses_url":"https://api.github.com/repos/docker/distribution/statuses/{sha}","languages_url":"https://api.github.com/repos/docker/distribution/languages","stargazers_url":"https://api.github.com/repos/docker/distribution/stargazers","contributors_url":"https://api.github.com/repos/docker/distribution/contributors","subscribers_url":"https://api.github.com/repos/docker/distribution/subscribers","subscription_url":"https://api.github.com/repos/docker/distribution/subscription","commits_url":"https://api.github.com/repos/docker/distribution/commits{/sha}","git_commits_url":"https://api.github.com/repos/docker/distribution/git/commits{/sha}","comments_url":"https://api.github.com/repos/docker/distribution/comments{/number}","issue_comment_url":"https://api.github.com/repos/docker/distribution/issues/comments{/number}","contents_url":"https://api.github.com/repos/docker/distribution/contents/{+path}","compare_url":"https://api.github.com/repos/docker/distribution/compare/{base}...{head}","merges_url":"https://api.github.com/repos/docker/distribution/merges","archive_url":"https://api.github.com/repos/docker/distribution/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/docker/distribution/downloads","issues_url":"https://api.github.com/repos/docker/distribution/issues{/number}","pulls_url":"https://api.github.com/repos/docker/distribution/pulls{/number}","milestones_url":"https://api.github.com/repos/docker/distribution/milestones{/number}","notifications_url":"https://api.github.com/repos/docker/distribution/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/docker/distribution/labels{/name}","releases_url":"https://api.github.com/repos/docker/distribution/releases{/id}","created_at":"2014-12-22T23:49:26Z","updated_at":"2015-09-08T20:00:01Z","pushed_at":"2015-09-08T18:44:04Z","git_url":"git://github.com/docker/distribution.git","ssh_url":"git@github.com:docker/distribution.git","clone_url":"https://github.com/docker/distribution.git","svn_url":"https://github.com/docker/distribution","homepage":null,"size":13419,"stargazers_count":1007,"watchers_count":1007,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":378,"mirror_url":null,"open_issues_count":128,"forks":378,"open_issues":128,"watchers":1007,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/docker/distribution/pulls/963"},"html":{"href":"https://github.com/docker/distribution/pull/963"},"issue":{"href":"https://api.github.com/repos/docker/distribution/issues/963"},"comments":{"href":"https://api.github.com/repos/docker/distribution/issues/963/comments"},"review_comments":{"href":"https://api.github.com/repos/docker/distribution/pulls/963/comments"},"review_comment":{"href":"https://api.github.com/repos/docker/distribution/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/docker/distribution/pulls/963/commits"},"statuses":{"href":"https://api.github.com/repos/docker/distribution/statuses/de0a10f5aa8fa00e702d99740e1cc8482b612252"}}}}