{"action":"created","comment":{"url":"https://api.github.com/repos/docker/distribution/pulls/comments/47861406","id":47861406,"diff_hunk":"@@ -49,59 +92,74 @@ type Manifest struct {\n }\n \n // SignedManifest provides an envelope for a signed image manifest, including\n-// the format sensitive raw bytes. It contains fields to\n+// the format sensitive raw bytes.\n type SignedManifest struct {\n \tManifest\n \n-\t// Raw is the byte representation of the ImageManifest, used for signature\n-\t// verification. The value of Raw must be used directly during\n-\t// serialization, or the signature check will fail. The manifest byte\n+\t// Canonical is the canonical byte representation of the ImageManifest,\n+\t// without any attached signatures. The manifest byte\n \t// representation cannot change or it will have to be re-signed.\n-\tRaw []byte `json:\"-\"`\n+\tCanonical []byte `json:\"-\"`\n+\n+\t// all contains the byte representation of the Manifest including signatures\n+\t// and is retuend by Payload()\n+\tall []byte\n }\n \n-// UnmarshalJSON populates a new ImageManifest struct from JSON data.\n+// UnmarshalJSON populates a new SignedManifest struct from JSON data.\n func (sm *SignedManifest) UnmarshalJSON(b []byte) error {\n-\tsm.Raw = make([]byte, len(b), len(b))\n-\tcopy(sm.Raw, b)\n+\tsm.all = make([]byte, len(b), len(b))\n+\t// store manifest and signatures in all\n+\tcopy(sm.all, b)\n+\n+\tjsig, err := libtrust.ParsePrettySignature(b, \"signatures\")\n+\tif err != nil {\n+\t\treturn err\n+\t}\n \n-\tp, err := sm.Payload()\n+\t// Resolve the payload in the manifest.\n+\tbytes, err := jsig.Payload()\n \tif err != nil {\n \t\treturn err\n \t}\n \n+\t// sm.Canonical stores the canonical manifest JSON\n+\tsm.Canonical = make([]byte, len(bytes), len(bytes))\n+\tcopy(sm.Canonical, bytes)\n+\n+\t// Unmarshal canonical JSON into Manifest object\n \tvar manifest Manifest\n-\tif err := json.Unmarshal(p, &manifest); err != nil {\n+\tif err := json.Unmarshal(sm.Canonical, &manifest); err != nil {\n \t\treturn err\n \t}\n \n \tsm.Manifest = manifest\n+\n \treturn nil\n }\n \n-// Payload returns the raw, signed content of the signed manifest. The\n-// contents can be used to calculate the content identifier.\n-func (sm *SignedManifest) Payload() ([]byte, error) {\n-\tjsig, err := libtrust.ParsePrettySignature(sm.Raw, \"signatures\")\n-\tif err != nil {\n-\t\treturn nil, err\n+// References returnes the descriptors of this manifests references\n+func (sm SignedManifest) References() []distribution.Descriptor {\n+\tdependencies := make([]distribution.Descriptor, len(sm.FSLayers))\n+\tfor i, fsLayer := range sm.FSLayers {\n+\t\tdependencies[i] = distribution.Descriptor{\n+\t\t\tMediaType: \"application/vnd.docker.container.image.rootfs.diff+x-gtar\",\n+\t\t\tDigest:    fsLayer.BlobSum,\n+\t\t}\n \t}\n \n-\t// Resolve the payload in the manifest.\n-\treturn jsig.Payload()\n+\treturn dependencies\n+\n }\n \n-// Signatures returns the signatures as provided by\n-// (*libtrust.JSONSignature).Signatures. The byte slices are opaque jws\n-// signatures.\n-func (sm *SignedManifest) Signatures() ([][]byte, error) {\n-\tjsig, err := libtrust.ParsePrettySignature(sm.Raw, \"signatures\")\n-\tif err != nil {\n-\t\treturn nil, err\n-\t}\n+// Target returns the target of this signed manifest\n+func (sm SignedManifest) Target() distribution.Descriptor {","path":"manifest/schema1/manifest.go","position":169,"original_position":169,"commit_id":"3ed8ffa3e9433438122e6da9728edc92736b112f","original_commit_id":"3ed8ffa3e9433438122e6da9728edc92736b112f","user":{"login":"aaronlehmann","id":10601430,"avatar_url":"https://avatars.githubusercontent.com/u/10601430?v=3","gravatar_id":"","url":"https://api.github.com/users/aaronlehmann","html_url":"https://github.com/aaronlehmann","followers_url":"https://api.github.com/users/aaronlehmann/followers","following_url":"https://api.github.com/users/aaronlehmann/following{/other_user}","gists_url":"https://api.github.com/users/aaronlehmann/gists{/gist_id}","starred_url":"https://api.github.com/users/aaronlehmann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aaronlehmann/subscriptions","organizations_url":"https://api.github.com/users/aaronlehmann/orgs","repos_url":"https://api.github.com/users/aaronlehmann/repos","events_url":"https://api.github.com/users/aaronlehmann/events{/privacy}","received_events_url":"https://api.github.com/users/aaronlehmann/received_events","type":"User","site_admin":false},"body":"Adding back a comment that GitHub thinks is against an outdated diff:\r\n\r\nThis function doesn't really make sense to me. It's returning a descriptor for the manifest itself as the target. It seems a bit recursive, and inconsistent with what Target will do for a schema2 manifest.\r\n\r\nThere isn't really a sensible implementation of Target for schema1. In the original proposal thread, I suggested that `Target` should not be part of the `Manifest` interface, because not all manifest types would be able to implement it. Looking over my preliminary schema2 code, all uses of `Target` do a type assertion to `*schema2.DeserializedManifest` before calling it. How about just removing `Target` from the interface and removing this implementation?\r\n\r\n\r\nAdding to that: `Target` doesn't make sense for manifest lists either. It's very schema2-specific.","created_at":"2015-12-17T02:01:04Z","updated_at":"2015-12-17T02:01:04Z","html_url":"https://github.com/docker/distribution/pull/1268#discussion_r47861406","pull_request_url":"https://api.github.com/repos/docker/distribution/pulls/1268","_links":{"self":{"href":"https://api.github.com/repos/docker/distribution/pulls/comments/47861406"},"html":{"href":"https://github.com/docker/distribution/pull/1268#discussion_r47861406"},"pull_request":{"href":"https://api.github.com/repos/docker/distribution/pulls/1268"}}},"pull_request":{"url":"https://api.github.com/repos/docker/distribution/pulls/1268","id":53762785,"html_url":"https://github.com/docker/distribution/pull/1268","diff_url":"https://github.com/docker/distribution/pull/1268.diff","patch_url":"https://github.com/docker/distribution/pull/1268.patch","issue_url":"https://api.github.com/repos/docker/distribution/issues/1268","number":1268,"state":"open","locked":false,"title":"Implementation of the Manifest Service API refactor.","user":{"login":"RichardScothern","id":922018,"avatar_url":"https://avatars.githubusercontent.com/u/922018?v=3","gravatar_id":"","url":"https://api.github.com/users/RichardScothern","html_url":"https://github.com/RichardScothern","followers_url":"https://api.github.com/users/RichardScothern/followers","following_url":"https://api.github.com/users/RichardScothern/following{/other_user}","gists_url":"https://api.github.com/users/RichardScothern/gists{/gist_id}","starred_url":"https://api.github.com/users/RichardScothern/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RichardScothern/subscriptions","organizations_url":"https://api.github.com/users/RichardScothern/orgs","repos_url":"https://api.github.com/users/RichardScothern/repos","events_url":"https://api.github.com/users/RichardScothern/events{/privacy}","received_events_url":"https://api.github.com/users/RichardScothern/received_events","type":"User","site_admin":false},"body":"Add a generic Manifest interface to represent manifests in the registry and\r\nremove references to schema specific manifests.\r\n\r\nAdd a ManifestBuilder to construct Manifest objects. Concrete manifest builders\r\nwill exist for each manifest type and implementations will contain manifest\r\nspecific data used to build a manifest.\r\n\r\nschema1\r\n-------\r\n\r\nChange the way data is stored in schema1.Manifest to enable Payload() to be used\r\nto return complete Manifest JSON from the HTTP handler without knowledge of the\r\nschema1 protocol.\r\n\r\ntags\r\n----\r\n\r\nMove tag functionality to a seperate TagService and update ManifestService\r\nto use the new interfaces.  Implement a driver based tagService to be backward\r\ncompatible with the current tag service.\r\n\r\nAdd a proxyTagService to enable the registry to get a digest for remote manifests\r\nfrom a tag.\r\n\r\nmanifest store\r\n--------------\r\n\r\nRemove revision store and move all signing functionality into the signed manifeststore.\r\n\r\nmanifest registration\r\n---------------------\r\n\r\nAdd a mechanism to register manifest media types and to allow different manifest\r\ntypes to be Unmarshalled correctly.\r\n\r\nclient\r\n------\r\n\r\nAdd ManifestServiceOptions to client functions to allow tags to be passed into Put and\r\nGet for building correct registry URLs.  Change functional arguments to be an interface type\r\nto allow passing data without mutating shared state.\r\n\r\nSigned-off-by: Richard Scothern <richard.scothern@docker.com>","created_at":"2015-12-15T21:12:15Z","updated_at":"2015-12-17T02:01:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e21631d888184a630e47b47b56bab61662a26314","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/docker/distribution/pulls/1268/commits","review_comments_url":"https://api.github.com/repos/docker/distribution/pulls/1268/comments","review_comment_url":"https://api.github.com/repos/docker/distribution/pulls/comments{/number}","comments_url":"https://api.github.com/repos/docker/distribution/issues/1268/comments","statuses_url":"https://api.github.com/repos/docker/distribution/statuses/3ed8ffa3e9433438122e6da9728edc92736b112f","head":{"label":"RichardScothern:manifest-refactor-impl","ref":"manifest-refactor-impl","sha":"3ed8ffa3e9433438122e6da9728edc92736b112f","user":{"login":"RichardScothern","id":922018,"avatar_url":"https://avatars.githubusercontent.com/u/922018?v=3","gravatar_id":"","url":"https://api.github.com/users/RichardScothern","html_url":"https://github.com/RichardScothern","followers_url":"https://api.github.com/users/RichardScothern/followers","following_url":"https://api.github.com/users/RichardScothern/following{/other_user}","gists_url":"https://api.github.com/users/RichardScothern/gists{/gist_id}","starred_url":"https://api.github.com/users/RichardScothern/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RichardScothern/subscriptions","organizations_url":"https://api.github.com/users/RichardScothern/orgs","repos_url":"https://api.github.com/users/RichardScothern/repos","events_url":"https://api.github.com/users/RichardScothern/events{/privacy}","received_events_url":"https://api.github.com/users/RichardScothern/received_events","type":"User","site_admin":false},"repo":{"id":32835922,"name":"distribution","full_name":"RichardScothern/distribution","owner":{"login":"RichardScothern","id":922018,"avatar_url":"https://avatars.githubusercontent.com/u/922018?v=3","gravatar_id":"","url":"https://api.github.com/users/RichardScothern","html_url":"https://github.com/RichardScothern","followers_url":"https://api.github.com/users/RichardScothern/followers","following_url":"https://api.github.com/users/RichardScothern/following{/other_user}","gists_url":"https://api.github.com/users/RichardScothern/gists{/gist_id}","starred_url":"https://api.github.com/users/RichardScothern/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RichardScothern/subscriptions","organizations_url":"https://api.github.com/users/RichardScothern/orgs","repos_url":"https://api.github.com/users/RichardScothern/repos","events_url":"https://api.github.com/users/RichardScothern/events{/privacy}","received_events_url":"https://api.github.com/users/RichardScothern/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/RichardScothern/distribution","description":"The Docker toolset to pack, ship, store, and deliver content","fork":true,"url":"https://api.github.com/repos/RichardScothern/distribution","forks_url":"https://api.github.com/repos/RichardScothern/distribution/forks","keys_url":"https://api.github.com/repos/RichardScothern/distribution/keys{/key_id}","collaborators_url":"https://api.github.com/repos/RichardScothern/distribution/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/RichardScothern/distribution/teams","hooks_url":"https://api.github.com/repos/RichardScothern/distribution/hooks","issue_events_url":"https://api.github.com/repos/RichardScothern/distribution/issues/events{/number}","events_url":"https://api.github.com/repos/RichardScothern/distribution/events","assignees_url":"https://api.github.com/repos/RichardScothern/distribution/assignees{/user}","branches_url":"https://api.github.com/repos/RichardScothern/distribution/branches{/branch}","tags_url":"https://api.github.com/repos/RichardScothern/distribution/tags","blobs_url":"https://api.github.com/repos/RichardScothern/distribution/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/RichardScothern/distribution/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/RichardScothern/distribution/git/refs{/sha}","trees_url":"https://api.github.com/repos/RichardScothern/distribution/git/trees{/sha}","statuses_url":"https://api.github.com/repos/RichardScothern/distribution/statuses/{sha}","languages_url":"https://api.github.com/repos/RichardScothern/distribution/languages","stargazers_url":"https://api.github.com/repos/RichardScothern/distribution/stargazers","contributors_url":"https://api.github.com/repos/RichardScothern/distribution/contributors","subscribers_url":"https://api.github.com/repos/RichardScothern/distribution/subscribers","subscription_url":"https://api.github.com/repos/RichardScothern/distribution/subscription","commits_url":"https://api.github.com/repos/RichardScothern/distribution/commits{/sha}","git_commits_url":"https://api.github.com/repos/RichardScothern/distribution/git/commits{/sha}","comments_url":"https://api.github.com/repos/RichardScothern/distribution/comments{/number}","issue_comment_url":"https://api.github.com/repos/RichardScothern/distribution/issues/comments{/number}","contents_url":"https://api.github.com/repos/RichardScothern/distribution/contents/{+path}","compare_url":"https://api.github.com/repos/RichardScothern/distribution/compare/{base}...{head}","merges_url":"https://api.github.com/repos/RichardScothern/distribution/merges","archive_url":"https://api.github.com/repos/RichardScothern/distribution/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/RichardScothern/distribution/downloads","issues_url":"https://api.github.com/repos/RichardScothern/distribution/issues{/number}","pulls_url":"https://api.github.com/repos/RichardScothern/distribution/pulls{/number}","milestones_url":"https://api.github.com/repos/RichardScothern/distribution/milestones{/number}","notifications_url":"https://api.github.com/repos/RichardScothern/distribution/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/RichardScothern/distribution/labels{/name}","releases_url":"https://api.github.com/repos/RichardScothern/distribution/releases{/id}","created_at":"2015-03-25T01:41:58Z","updated_at":"2015-05-08T16:24:12Z","pushed_at":"2015-12-17T00:47:56Z","git_url":"git://github.com/RichardScothern/distribution.git","ssh_url":"git@github.com:RichardScothern/distribution.git","clone_url":"https://github.com/RichardScothern/distribution.git","svn_url":"https://github.com/RichardScothern/distribution","homepage":null,"size":7581,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"docker:master","ref":"master","sha":"91627604434db8ac744db66b8d83554767ada3c1","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-12-16T19:57:34Z","pushed_at":"2015-12-17T01:39:21Z","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":10479,"stargazers_count":1468,"watchers_count":1468,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":557,"mirror_url":null,"open_issues_count":176,"forks":557,"open_issues":176,"watchers":1468,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/docker/distribution/pulls/1268"},"html":{"href":"https://github.com/docker/distribution/pull/1268"},"issue":{"href":"https://api.github.com/repos/docker/distribution/issues/1268"},"comments":{"href":"https://api.github.com/repos/docker/distribution/issues/1268/comments"},"review_comments":{"href":"https://api.github.com/repos/docker/distribution/pulls/1268/comments"},"review_comment":{"href":"https://api.github.com/repos/docker/distribution/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/docker/distribution/pulls/1268/commits"},"statuses":{"href":"https://api.github.com/repos/docker/distribution/statuses/3ed8ffa3e9433438122e6da9728edc92736b112f"}}}}