{"action":"created","comment":{"url":"https://api.github.com/repos/Polymer/polytool/pulls/comments/62539275","id":62539275,"diff_hunk":"@@ -9,55 +9,328 @@\n  */\n \n import * as gulpif from 'gulp-if';\n+import * as path from 'path';\n import {Transform} from 'stream';\n+import File = require('vinyl');\n \n import {Logger} from './logger';\n import {compose} from './streams';\n import {StreamResolver} from './stream-resolver';\n import {VulcanizeTransform} from './vulcanize';\n+import {Analyzer, Loader} from 'hydrolysis';\n \n // non-ES module\n const minimatchAll = require('minimatch-all');\n+const through = require('through2').obj;\n+const Vulcanize = require('vulcanize');\n \n export class Bundler {\n \n   root: string;\n   shell: string;\n+  sharedBundleUrl: string;\n   allEntrypoints: string[];\n \n   streamResolver: StreamResolver;\n+  loader: Loader;\n   bundle: Transform;\n   vulcanize: Transform;\n+  analyzer: Analyzer;\n+  entrypointFiles: Map<string, File>;\n+  sharedFile: File;\n \n-  constructor(root: string, shell: string, entrypoints: string[]) {\n+  _verboseLogging = false;\n+\n+  constructor(root: string, shell: string, entrypoints?: string[]) {\n     this.root = root;\n     this.shell = shell;\n-    let allEntrypoints = [];\n-    if (shell) allEntrypoints.push(shell);\n+    this.sharedBundleUrl = path.resolve(root, 'shared-bundle.html');\n+\n+    let _allEntrypoints = [];\n+    // It's important that shell is first for document-ordering of imports\n+    if (shell) _allEntrypoints.push(shell);\n     this.allEntrypoints =\n-        Array.prototype.concat.apply(allEntrypoints, entrypoints);\n+        Array.prototype.concat.apply(_allEntrypoints, entrypoints);\n \n     this.streamResolver = new StreamResolver({\n         entrypoints: this.allEntrypoints,\n         basePath: root,\n         root: root,\n         redirect: 'bower_components/',\n       });\n+\n+    this.loader = new Loader();\n+    this.loader.addResolver(this.streamResolver);\n+    this.analyzer = new Analyzer(false, this.loader);\n+\n     this.vulcanize = new VulcanizeTransform({\n       fsResolver: this.streamResolver,\n       inlineScripts: true,\n       inlineCss: true,\n       stripComments: true,\n     });\n \n+    this.entrypointFiles = new Map();\n+\n     this.bundle = compose([\n       this.streamResolver,\n-      gulpif((file) => this.isEntryPoint(file.path), this.vulcanize)\n+      through((file, enc, cb) => {\n+        if (this.isEntryPoint(file.path)) {\n+          // don't pass on any entrypoints until the stream has ended\n+          this.entrypointFiles.set(file.path, file);\n+          cb(null, null);\n+        } else {\n+          cb(null, file);\n+        }\n+      },\n+      (done) => {\n+        this._buildBundles().then((bundles: Map<string, string>) => {\n+          for (let entrypoint of this.entrypointFiles.keys()) {\n+            let file = this.entrypointFiles.get(entrypoint);\n+            let contents = bundles.get(entrypoint);\n+            file.contents = new Buffer(contents);\n+            this.bundle.push(file);\n+          }\n+          let sharedBundle = bundles.get(this.sharedBundleUrl);\n+          if (sharedBundle) {\n+            let contents = bundles.get(this.sharedBundleUrl);\n+            this.sharedFile.contents = new Buffer(contents);\n+            this.bundle.push(this.sharedFile);\n+          }\n+          // end the stream\n+          done();\n+        });\n+      })\n     ]);\n   }\n \n-  isEntryPoint(filepath: string): boolean {\n-    return minimatchAll(filepath, this.allEntrypoints, {matchBase: true})\n+  isEntryPoint(url: string): boolean {\n+    return minimatchAll(url, this.allEntrypoints, {matchBase: true});\n+  }\n+\n+  _buildBundles(): Promise<Map<string, string>> {\n+    return this._getBundles().then((bundles) => {\n+      if (this._verboseLogging) {\n+        console.log('bundles:');\n+        for (let url of bundles.keys()) {\n+          let deps = bundles.get(url);\n+          if (!deps) {\n+            console.log('    no deps?');\n+          } else {\n+            console.log(`  ${url} (${deps.length}):`);\n+            for (let dep of deps) {\n+              console.log(`    ${dep}`);\n+            }\n+          }\n+        }\n+      }\n+\n+      let sharedDeps = bundles.get(this.sharedBundleUrl);\n+      let excludes = sharedDeps ? sharedDeps.concat(this.sharedBundleUrl) : [];\n+      let promises = [];\n+\n+      for (let entrypoint of this.allEntrypoints) {\n+        promises.push(new Promise((resolve, reject) => {\n+          var vulcanize = new Vulcanize({\n+            abspath: null,\n+            fsResolver: this.streamResolver,\n+            addedImports: [this.sharedBundleUrl],\n+            stripExcludes: excludes,\n+            inlineScripts: true,\n+            inlineCss: true,\n+            inputUrl: entrypoint,\n+          });\n+          vulcanize.process(null, (err, doc) => {\n+            if (err) {\n+              reject(err);\n+            } else {\n+              if (this._verboseLogging) {\n+                console.log(`vulcanized doc for ${entrypoint}: ${doc.length}`);\n+              }\n+              resolve({\n+                url: entrypoint,\n+                contents: doc,\n+              });\n+            }\n+          });\n+        }));\n+      }\n+      // vulcanize the shared bundle\n+      if (sharedDeps) {\n+        promises.push(this._generateSharedBundle(sharedDeps));\n+      }\n+\n+      return Promise.all(promises).then((bundles) => {\n+        // convert {url,contents}[] into a Map\n+        let contentsMap = new Map();\n+        for (let bundle of bundles) {\n+          contentsMap.set(bundle.url, bundle.contents);\n+        }\n+        return contentsMap;\n+      });\n+    });\n+  }\n+\n+  _generateSharedBundle(sharedDeps: string[]): Promise<any> {\n+    return new Promise((resolve, reject) => {\n+      let contents = sharedDeps\n+          .map((d) => `<link rel=\"import\" href=\"${d}\">`)\n+          .join('\\n');\n+\n+      this.sharedFile = new File({\n+        cwd: this.root,\n+        base: this.root,\n+        path: this.sharedBundleUrl,\n+        contents: new Buffer(contents),\n+      });\n+\n+      // make the shared bundle visible to vulcanize\n+      this.streamResolver.addFile(this.sharedFile);\n+\n+      var vulcanize = new Vulcanize({\n+        abspath: null,\n+        fsResolver: this.streamResolver,\n+        inlineScripts: true,\n+        inlineCss: true,\n+        inputUrl: this.sharedBundleUrl,\n+      });\n+      vulcanize.process(null, (err, doc) => {\n+        if (err) {\n+          reject(err);\n+        } else {\n+          resolve({\n+            url: this.sharedBundleUrl,\n+            contents: doc,\n+          });\n+        }\n+      });\n+    });\n+  }\n+\n+  _getBundles() {\n+    return this._getDepsToEntrypointIndex().then((indexes) => {\n+      let depsToEntrypoints = indexes.depsToEntrypoints;\n+      let entrypointToDeps = indexes.entrypointToDeps;\n+      let bundles = new Map<string, string[]>();\n+\n+      let addImport = (from: string, to: string) => {\n+        let imports;\n+        if (!bundles.has(from)) {\n+          imports = [];\n+          bundles.set(from, imports);\n+        } else {\n+          imports = bundles.get(from);\n+        }\n+        if (!imports.includes(to)) {\n+          imports.push(to);\n+        }\n+      }\n+\n+      // We want to collect dependencies that appear in > 1 entrypoint, but\n+      // we need to collect them in document order, so rather than iterate\n+      // directly through each dependency in depsToEntrypoints, we iterate\n+      // through entrypoints in entrypointToDeps, which has dependencies in\n+      // order for each entrypoint. Then we iterate through dependencies for\n+      // each entrypoint and look up how many entrypoints depend on it.\n+      // This assumes an ordering between entrypoints, since they could have\n+      // conflicting orders between their top level imports. The shell should\n+      // always come first.\n+      for (let entrypoint of entrypointToDeps.keys()) {","path":"src/build/bundle.ts","position":237,"original_position":237,"commit_id":"70d19fb0133808ddb1b475c4fa9dba980f1b5da2","original_commit_id":"70d19fb0133808ddb1b475c4fa9dba980f1b5da2","user":{"login":"azakus","id":46725,"avatar_url":"https://avatars.githubusercontent.com/u/46725?v=3","gravatar_id":"","url":"https://api.github.com/users/azakus","html_url":"https://github.com/azakus","followers_url":"https://api.github.com/users/azakus/followers","following_url":"https://api.github.com/users/azakus/following{/other_user}","gists_url":"https://api.github.com/users/azakus/gists{/gist_id}","starred_url":"https://api.github.com/users/azakus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/azakus/subscriptions","organizations_url":"https://api.github.com/users/azakus/orgs","repos_url":"https://api.github.com/users/azakus/repos","events_url":"https://api.github.com/users/azakus/events{/privacy}","received_events_url":"https://api.github.com/users/azakus/received_events","type":"User","site_admin":false},"body":"SGTM","created_at":"2016-05-09T17:35:59Z","updated_at":"2016-05-09T17:35:59Z","html_url":"https://github.com/Polymer/polytool/pull/53#discussion_r62539275","pull_request_url":"https://api.github.com/repos/Polymer/polytool/pulls/53","_links":{"self":{"href":"https://api.github.com/repos/Polymer/polytool/pulls/comments/62539275"},"html":{"href":"https://github.com/Polymer/polytool/pull/53#discussion_r62539275"},"pull_request":{"href":"https://api.github.com/repos/Polymer/polytool/pulls/53"}}},"pull_request":{"url":"https://api.github.com/repos/Polymer/polytool/pulls/53","id":69281317,"html_url":"https://github.com/Polymer/polytool/pull/53","diff_url":"https://github.com/Polymer/polytool/pull/53.diff","patch_url":"https://github.com/Polymer/polytool/pull/53.patch","issue_url":"https://api.github.com/repos/Polymer/polytool/issues/53","number":53,"state":"open","locked":false,"title":"Bundle","user":{"login":"justinfagnani","id":522948,"avatar_url":"https://avatars.githubusercontent.com/u/522948?v=3","gravatar_id":"","url":"https://api.github.com/users/justinfagnani","html_url":"https://github.com/justinfagnani","followers_url":"https://api.github.com/users/justinfagnani/followers","following_url":"https://api.github.com/users/justinfagnani/following{/other_user}","gists_url":"https://api.github.com/users/justinfagnani/gists{/gist_id}","starred_url":"https://api.github.com/users/justinfagnani/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/justinfagnani/subscriptions","organizations_url":"https://api.github.com/users/justinfagnani/orgs","repos_url":"https://api.github.com/users/justinfagnani/repos","events_url":"https://api.github.com/users/justinfagnani/events{/privacy}","received_events_url":"https://api.github.com/users/justinfagnani/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-05-08T22:10:28Z","updated_at":"2016-05-09T17:35:59Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2435f47d0a2ed094437ccfa641ce283ec50d1a97","assignee":{"login":"azakus","id":46725,"avatar_url":"https://avatars.githubusercontent.com/u/46725?v=3","gravatar_id":"","url":"https://api.github.com/users/azakus","html_url":"https://github.com/azakus","followers_url":"https://api.github.com/users/azakus/followers","following_url":"https://api.github.com/users/azakus/following{/other_user}","gists_url":"https://api.github.com/users/azakus/gists{/gist_id}","starred_url":"https://api.github.com/users/azakus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/azakus/subscriptions","organizations_url":"https://api.github.com/users/azakus/orgs","repos_url":"https://api.github.com/users/azakus/repos","events_url":"https://api.github.com/users/azakus/events{/privacy}","received_events_url":"https://api.github.com/users/azakus/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/Polymer/polytool/pulls/53/commits","review_comments_url":"https://api.github.com/repos/Polymer/polytool/pulls/53/comments","review_comment_url":"https://api.github.com/repos/Polymer/polytool/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Polymer/polytool/issues/53/comments","statuses_url":"https://api.github.com/repos/Polymer/polytool/statuses/70d19fb0133808ddb1b475c4fa9dba980f1b5da2","head":{"label":"Polymer:bundle","ref":"bundle","sha":"70d19fb0133808ddb1b475c4fa9dba980f1b5da2","user":{"login":"Polymer","id":2159051,"avatar_url":"https://avatars.githubusercontent.com/u/2159051?v=3","gravatar_id":"","url":"https://api.github.com/users/Polymer","html_url":"https://github.com/Polymer","followers_url":"https://api.github.com/users/Polymer/followers","following_url":"https://api.github.com/users/Polymer/following{/other_user}","gists_url":"https://api.github.com/users/Polymer/gists{/gist_id}","starred_url":"https://api.github.com/users/Polymer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Polymer/subscriptions","organizations_url":"https://api.github.com/users/Polymer/orgs","repos_url":"https://api.github.com/users/Polymer/repos","events_url":"https://api.github.com/users/Polymer/events{/privacy}","received_events_url":"https://api.github.com/users/Polymer/received_events","type":"Organization","site_admin":false},"repo":{"id":51951003,"name":"polytool","full_name":"Polymer/polytool","owner":{"login":"Polymer","id":2159051,"avatar_url":"https://avatars.githubusercontent.com/u/2159051?v=3","gravatar_id":"","url":"https://api.github.com/users/Polymer","html_url":"https://github.com/Polymer","followers_url":"https://api.github.com/users/Polymer/followers","following_url":"https://api.github.com/users/Polymer/following{/other_user}","gists_url":"https://api.github.com/users/Polymer/gists{/gist_id}","starred_url":"https://api.github.com/users/Polymer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Polymer/subscriptions","organizations_url":"https://api.github.com/users/Polymer/orgs","repos_url":"https://api.github.com/users/Polymer/repos","events_url":"https://api.github.com/users/Polymer/events{/privacy}","received_events_url":"https://api.github.com/users/Polymer/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Polymer/polytool","description":"A command-line tool for Polymer projects","fork":false,"url":"https://api.github.com/repos/Polymer/polytool","forks_url":"https://api.github.com/repos/Polymer/polytool/forks","keys_url":"https://api.github.com/repos/Polymer/polytool/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Polymer/polytool/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Polymer/polytool/teams","hooks_url":"https://api.github.com/repos/Polymer/polytool/hooks","issue_events_url":"https://api.github.com/repos/Polymer/polytool/issues/events{/number}","events_url":"https://api.github.com/repos/Polymer/polytool/events","assignees_url":"https://api.github.com/repos/Polymer/polytool/assignees{/user}","branches_url":"https://api.github.com/repos/Polymer/polytool/branches{/branch}","tags_url":"https://api.github.com/repos/Polymer/polytool/tags","blobs_url":"https://api.github.com/repos/Polymer/polytool/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Polymer/polytool/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Polymer/polytool/git/refs{/sha}","trees_url":"https://api.github.com/repos/Polymer/polytool/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Polymer/polytool/statuses/{sha}","languages_url":"https://api.github.com/repos/Polymer/polytool/languages","stargazers_url":"https://api.github.com/repos/Polymer/polytool/stargazers","contributors_url":"https://api.github.com/repos/Polymer/polytool/contributors","subscribers_url":"https://api.github.com/repos/Polymer/polytool/subscribers","subscription_url":"https://api.github.com/repos/Polymer/polytool/subscription","commits_url":"https://api.github.com/repos/Polymer/polytool/commits{/sha}","git_commits_url":"https://api.github.com/repos/Polymer/polytool/git/commits{/sha}","comments_url":"https://api.github.com/repos/Polymer/polytool/comments{/number}","issue_comment_url":"https://api.github.com/repos/Polymer/polytool/issues/comments{/number}","contents_url":"https://api.github.com/repos/Polymer/polytool/contents/{+path}","compare_url":"https://api.github.com/repos/Polymer/polytool/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Polymer/polytool/merges","archive_url":"https://api.github.com/repos/Polymer/polytool/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Polymer/polytool/downloads","issues_url":"https://api.github.com/repos/Polymer/polytool/issues{/number}","pulls_url":"https://api.github.com/repos/Polymer/polytool/pulls{/number}","milestones_url":"https://api.github.com/repos/Polymer/polytool/milestones{/number}","notifications_url":"https://api.github.com/repos/Polymer/polytool/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Polymer/polytool/labels{/name}","releases_url":"https://api.github.com/repos/Polymer/polytool/releases{/id}","deployments_url":"https://api.github.com/repos/Polymer/polytool/deployments","created_at":"2016-02-17T19:57:15Z","updated_at":"2016-05-08T03:22:59Z","pushed_at":"2016-05-09T17:06:49Z","git_url":"git://github.com/Polymer/polytool.git","ssh_url":"git@github.com:Polymer/polytool.git","clone_url":"https://github.com/Polymer/polytool.git","svn_url":"https://github.com/Polymer/polytool","homepage":null,"size":127,"stargazers_count":10,"watchers_count":10,"language":"TypeScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"open_issues_count":17,"forks":6,"open_issues":17,"watchers":10,"default_branch":"master"}},"base":{"label":"Polymer:master","ref":"master","sha":"d885dc3e1c16b770711d9a9c4380b14809ad01d7","user":{"login":"Polymer","id":2159051,"avatar_url":"https://avatars.githubusercontent.com/u/2159051?v=3","gravatar_id":"","url":"https://api.github.com/users/Polymer","html_url":"https://github.com/Polymer","followers_url":"https://api.github.com/users/Polymer/followers","following_url":"https://api.github.com/users/Polymer/following{/other_user}","gists_url":"https://api.github.com/users/Polymer/gists{/gist_id}","starred_url":"https://api.github.com/users/Polymer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Polymer/subscriptions","organizations_url":"https://api.github.com/users/Polymer/orgs","repos_url":"https://api.github.com/users/Polymer/repos","events_url":"https://api.github.com/users/Polymer/events{/privacy}","received_events_url":"https://api.github.com/users/Polymer/received_events","type":"Organization","site_admin":false},"repo":{"id":51951003,"name":"polytool","full_name":"Polymer/polytool","owner":{"login":"Polymer","id":2159051,"avatar_url":"https://avatars.githubusercontent.com/u/2159051?v=3","gravatar_id":"","url":"https://api.github.com/users/Polymer","html_url":"https://github.com/Polymer","followers_url":"https://api.github.com/users/Polymer/followers","following_url":"https://api.github.com/users/Polymer/following{/other_user}","gists_url":"https://api.github.com/users/Polymer/gists{/gist_id}","starred_url":"https://api.github.com/users/Polymer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Polymer/subscriptions","organizations_url":"https://api.github.com/users/Polymer/orgs","repos_url":"https://api.github.com/users/Polymer/repos","events_url":"https://api.github.com/users/Polymer/events{/privacy}","received_events_url":"https://api.github.com/users/Polymer/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Polymer/polytool","description":"A command-line tool for Polymer projects","fork":false,"url":"https://api.github.com/repos/Polymer/polytool","forks_url":"https://api.github.com/repos/Polymer/polytool/forks","keys_url":"https://api.github.com/repos/Polymer/polytool/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Polymer/polytool/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Polymer/polytool/teams","hooks_url":"https://api.github.com/repos/Polymer/polytool/hooks","issue_events_url":"https://api.github.com/repos/Polymer/polytool/issues/events{/number}","events_url":"https://api.github.com/repos/Polymer/polytool/events","assignees_url":"https://api.github.com/repos/Polymer/polytool/assignees{/user}","branches_url":"https://api.github.com/repos/Polymer/polytool/branches{/branch}","tags_url":"https://api.github.com/repos/Polymer/polytool/tags","blobs_url":"https://api.github.com/repos/Polymer/polytool/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Polymer/polytool/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Polymer/polytool/git/refs{/sha}","trees_url":"https://api.github.com/repos/Polymer/polytool/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Polymer/polytool/statuses/{sha}","languages_url":"https://api.github.com/repos/Polymer/polytool/languages","stargazers_url":"https://api.github.com/repos/Polymer/polytool/stargazers","contributors_url":"https://api.github.com/repos/Polymer/polytool/contributors","subscribers_url":"https://api.github.com/repos/Polymer/polytool/subscribers","subscription_url":"https://api.github.com/repos/Polymer/polytool/subscription","commits_url":"https://api.github.com/repos/Polymer/polytool/commits{/sha}","git_commits_url":"https://api.github.com/repos/Polymer/polytool/git/commits{/sha}","comments_url":"https://api.github.com/repos/Polymer/polytool/comments{/number}","issue_comment_url":"https://api.github.com/repos/Polymer/polytool/issues/comments{/number}","contents_url":"https://api.github.com/repos/Polymer/polytool/contents/{+path}","compare_url":"https://api.github.com/repos/Polymer/polytool/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Polymer/polytool/merges","archive_url":"https://api.github.com/repos/Polymer/polytool/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Polymer/polytool/downloads","issues_url":"https://api.github.com/repos/Polymer/polytool/issues{/number}","pulls_url":"https://api.github.com/repos/Polymer/polytool/pulls{/number}","milestones_url":"https://api.github.com/repos/Polymer/polytool/milestones{/number}","notifications_url":"https://api.github.com/repos/Polymer/polytool/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Polymer/polytool/labels{/name}","releases_url":"https://api.github.com/repos/Polymer/polytool/releases{/id}","deployments_url":"https://api.github.com/repos/Polymer/polytool/deployments","created_at":"2016-02-17T19:57:15Z","updated_at":"2016-05-08T03:22:59Z","pushed_at":"2016-05-09T17:06:49Z","git_url":"git://github.com/Polymer/polytool.git","ssh_url":"git@github.com:Polymer/polytool.git","clone_url":"https://github.com/Polymer/polytool.git","svn_url":"https://github.com/Polymer/polytool","homepage":null,"size":127,"stargazers_count":10,"watchers_count":10,"language":"TypeScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"open_issues_count":17,"forks":6,"open_issues":17,"watchers":10,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Polymer/polytool/pulls/53"},"html":{"href":"https://github.com/Polymer/polytool/pull/53"},"issue":{"href":"https://api.github.com/repos/Polymer/polytool/issues/53"},"comments":{"href":"https://api.github.com/repos/Polymer/polytool/issues/53/comments"},"review_comments":{"href":"https://api.github.com/repos/Polymer/polytool/pulls/53/comments"},"review_comment":{"href":"https://api.github.com/repos/Polymer/polytool/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Polymer/polytool/pulls/53/commits"},"statuses":{"href":"https://api.github.com/repos/Polymer/polytool/statuses/70d19fb0133808ddb1b475c4fa9dba980f1b5da2"}}}}