{"action":"created","comment":{"url":"https://api.github.com/repos/Homebrew/brew/pulls/comments/60813583","id":60813583,"diff_hunk":"@@ -402,7 +404,168 @@ def subject_for_bump(formula, old, new)\n     subject\n   end\n \n+  def maybe_pbcopy(text)\n+    pbcopy(text) unless ARGV.include? \"--no-pbcopy\"\n+  end\n+\n   def pbcopy(text)\n     Utils.popen_write(\"pbcopy\") { |io| io.write text }\n   end\n+\n+  # Publishes the current bottle files for a given formula to Bintray\n+  def publish_bottle_files_to_bintray(f, creds)\n+    repo = Bintray.repository(f.tap)\n+    package = Bintray.package(f.name)\n+    info = FormulaInfoFromJson.lookup(f.name)\n+    version = info.pkg_version\n+    curl \"-w\", '\\n', \"--silent\", \"--fail\",\n+         \"-u#{creds[:user]}:#{creds[:key]}\", \"-X\", \"POST\",\n+         \"-H\", \"Content-Type: application/json\",\n+         \"-d\", '{\"publish_wait_for_secs\": 0}',\n+         \"https://api.bintray.com/content/homebrew/#{repo}/#{package}/#{version}/publish\"\n+  end\n+\n+  # The URL for a given bottle\n+  # Opts:\n+  #  bottle_tag  - tag indicating platform of bottle. Defaults to current\n+  #                process's platform\n+  def bottle_url(f, opts = {})\n+    my_bottle_tag = opts[:bottle_tag] || bottle_tag\n+    my_bottle_tag ||= bottle_tag\n+    spec = f.stable\n+    bottle_spec = spec.bottle_specification\n+    filename = Bottle::Filename.create(f, my_bottle_tag, bottle_spec.revision)\n+    \"#{bottle_spec.root_url}/#{filename}\"\n+  end\n+\n+  def bottle_url_any_platform(f)\n+    info = FormulaInfoFromJson.lookup(f.name)\n+    bottle_info = info.bottle_info_any\n+    return bottle_info.nil? ? nil : bottle_info.url\n+  end\n+\n+  # Formula info drawn from an external \"brew info --json\" call\n+  class FormulaInfoFromJson\n+    # The whole info structure parsed from the JSON\n+    attr_accessor :info\n+\n+    def initialize(info)\n+      @info = info\n+    end\n+\n+    def self.lookup(name)\n+      json = Utils.popen_read(HOMEBREW_BREW_FILE, \"info\", \"--json=v1\", name)\n+      Homebrew.force_utf8!(json)\n+      opoo \"Failed getting info for #{name}\" unless $?.success?","path":"Library/Homebrew/cmd/pull.rb","position":316,"original_position":316,"commit_id":"60e07b294cdb5802e9c16c7e13de8cff9338136e","original_commit_id":"60e07b294cdb5802e9c16c7e13de8cff9338136e","user":{"login":"UniqMartin","id":11892150,"avatar_url":"https://avatars.githubusercontent.com/u/11892150?v=3","gravatar_id":"","url":"https://api.github.com/users/UniqMartin","html_url":"https://github.com/UniqMartin","followers_url":"https://api.github.com/users/UniqMartin/followers","following_url":"https://api.github.com/users/UniqMartin/following{/other_user}","gists_url":"https://api.github.com/users/UniqMartin/gists{/gist_id}","starred_url":"https://api.github.com/users/UniqMartin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/UniqMartin/subscriptions","organizations_url":"https://api.github.com/users/UniqMartin/orgs","repos_url":"https://api.github.com/users/UniqMartin/repos","events_url":"https://api.github.com/users/UniqMartin/events{/privacy}","received_events_url":"https://api.github.com/users/UniqMartin/received_events","type":"User","site_admin":false},"body":"`opoo` is just printing a warning. I imagine if that invocation returned with an error, then the next line will fail hard while trying to load and parse the JSON (unless that's rescued and dealt with somewhere further up the call chain). What is really supposed to happen here?","created_at":"2016-04-22T22:58:37Z","updated_at":"2016-04-22T22:58:37Z","html_url":"https://github.com/Homebrew/brew/pull/132#discussion_r60813583","pull_request_url":"https://api.github.com/repos/Homebrew/brew/pulls/132","_links":{"self":{"href":"https://api.github.com/repos/Homebrew/brew/pulls/comments/60813583"},"html":{"href":"https://github.com/Homebrew/brew/pull/132#discussion_r60813583"},"pull_request":{"href":"https://api.github.com/repos/Homebrew/brew/pulls/132"}}},"pull_request":{"url":"https://api.github.com/repos/Homebrew/brew/pulls/132","id":67412319,"html_url":"https://github.com/Homebrew/brew/pull/132","diff_url":"https://github.com/Homebrew/brew/pull/132.diff","patch_url":"https://github.com/Homebrew/brew/pull/132.patch","issue_url":"https://api.github.com/repos/Homebrew/brew/issues/132","number":132,"state":"open","locked":false,"title":"brew pull: portable bottle downloads, more concise output, faster polling","user":{"login":"apjanke","id":2618447,"avatar_url":"https://avatars.githubusercontent.com/u/2618447?v=3","gravatar_id":"","url":"https://api.github.com/users/apjanke","html_url":"https://github.com/apjanke","followers_url":"https://api.github.com/users/apjanke/followers","following_url":"https://api.github.com/users/apjanke/following{/other_user}","gists_url":"https://api.github.com/users/apjanke/gists{/gist_id}","starred_url":"https://api.github.com/users/apjanke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apjanke/subscriptions","organizations_url":"https://api.github.com/users/apjanke/orgs","repos_url":"https://api.github.com/users/apjanke/repos","events_url":"https://api.github.com/users/apjanke/events{/privacy}","received_events_url":"https://api.github.com/users/apjanke/received_events","type":"User","site_admin":false},"body":"- [X] Have you followed the guidelines in our [Contributing](https://github.com/Homebrew/brew/blob/master/.github/CONTRIBUTING.md) document?\r\n- [X] Have you checked to ensure there aren't other open [Pull Requests](https://github.com/Homebrew/brew/pulls) for the same change?\r\n- [X] Have you added an explanation of what your changes do and why you'd like us to include them?\r\n- [ ] Have you written new tests for your changes? [Here's an example](https://github.com/Homebrew/homebrew/pull/49031).\r\n- [X] Have you successfully ran `brew tests` with your changes locally?\r\n\r\n###  Summary\r\n\r\nDo the bottle check using any platform's bottle, so `brew pull` works on bottled formulae which don't include a bottle for the current system.\r\n\r\nMake output more concise and informative\r\n     * Remove expected download error messages when waiting for Bintray publishing\r\n     * Replace patch download progress bars with patch file name\r\n     * Silence git output about switching to and from bottle-pulling branch\r\n     * Include formula name and patch type in some progress messages\r\n\r\nPolls Bintray every 2 seconds instead of doing an exponential backoff, to minimize user waiting time.\r\n\r\nAdds a `Formula` class cache clearing method.\r\n\r\n###  Discussion\r\n\r\nThis is a rewrite of homebrew/legacy-homebrew#50070. I think it addresses most of the concerns expressed there.\r\n\r\nThe self-calls and \"internal\" commands are all replaced with use of `brew info --json`, so the `brew` command's observable behavior isn't cluttered by this. Makes the code simpler, too.\r\n\r\nI'm convinced now that a simple clearing of the `Formulary.FORMULAE` cache is enough to correctly pick up fresh class definitions from updated files: the `Formula` subclass definitions are all wrapped in random module namespaces so they're effectively anonymous, and we don't have to worry about pollution of the global class definition set affecting newly-loaded formulae.\r\n\r\nSorry, @xu-cheng, I couldn't figure out a way to implement the polling purely in terms of `curl`. I wanted it to do a) a single-line progress bar that indicates polling passes, not content downloaded, b) can retry based on exact HTTP error status, so we can restrict it to retrying only on 401 Not Authorized if needed, and c) reuses the same HTTP connection for each poll of a given file, to minimize Bintray resource usage with the faster polling cycle.\r\n\r\n###  Testing\r\n\r\nI've been using a variant of this ([`pull2` in [my homebrew-custom tap](https://github.com/apjanke/homebrew-custom/blob/master/cmd/brew-pull2.rb)) for the past few days and it's been working well. I don't see a way to write unit tests for it, as all its behavior depends on transient external GitHub state.","created_at":"2016-04-21T19:54:27Z","updated_at":"2016-04-22T22:58:37Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7d97960b26e7c57b3a4ac1617386e8f3c0147770","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Homebrew/brew/pulls/132/commits","review_comments_url":"https://api.github.com/repos/Homebrew/brew/pulls/132/comments","review_comment_url":"https://api.github.com/repos/Homebrew/brew/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Homebrew/brew/issues/132/comments","statuses_url":"https://api.github.com/repos/Homebrew/brew/statuses/60e07b294cdb5802e9c16c7e13de8cff9338136e","head":{"label":"apjanke:brew-pull-portable-bottle-downloads","ref":"brew-pull-portable-bottle-downloads","sha":"60e07b294cdb5802e9c16c7e13de8cff9338136e","user":{"login":"apjanke","id":2618447,"avatar_url":"https://avatars.githubusercontent.com/u/2618447?v=3","gravatar_id":"","url":"https://api.github.com/users/apjanke","html_url":"https://github.com/apjanke","followers_url":"https://api.github.com/users/apjanke/followers","following_url":"https://api.github.com/users/apjanke/following{/other_user}","gists_url":"https://api.github.com/users/apjanke/gists{/gist_id}","starred_url":"https://api.github.com/users/apjanke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apjanke/subscriptions","organizations_url":"https://api.github.com/users/apjanke/orgs","repos_url":"https://api.github.com/users/apjanke/repos","events_url":"https://api.github.com/users/apjanke/events{/privacy}","received_events_url":"https://api.github.com/users/apjanke/received_events","type":"User","site_admin":false},"repo":{"id":55512108,"name":"brew","full_name":"apjanke/brew","owner":{"login":"apjanke","id":2618447,"avatar_url":"https://avatars.githubusercontent.com/u/2618447?v=3","gravatar_id":"","url":"https://api.github.com/users/apjanke","html_url":"https://github.com/apjanke","followers_url":"https://api.github.com/users/apjanke/followers","following_url":"https://api.github.com/users/apjanke/following{/other_user}","gists_url":"https://api.github.com/users/apjanke/gists{/gist_id}","starred_url":"https://api.github.com/users/apjanke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apjanke/subscriptions","organizations_url":"https://api.github.com/users/apjanke/orgs","repos_url":"https://api.github.com/users/apjanke/repos","events_url":"https://api.github.com/users/apjanke/events{/privacy}","received_events_url":"https://api.github.com/users/apjanke/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/apjanke/brew","description":":beer: The missing package manager for OS X","fork":true,"url":"https://api.github.com/repos/apjanke/brew","forks_url":"https://api.github.com/repos/apjanke/brew/forks","keys_url":"https://api.github.com/repos/apjanke/brew/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apjanke/brew/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apjanke/brew/teams","hooks_url":"https://api.github.com/repos/apjanke/brew/hooks","issue_events_url":"https://api.github.com/repos/apjanke/brew/issues/events{/number}","events_url":"https://api.github.com/repos/apjanke/brew/events","assignees_url":"https://api.github.com/repos/apjanke/brew/assignees{/user}","branches_url":"https://api.github.com/repos/apjanke/brew/branches{/branch}","tags_url":"https://api.github.com/repos/apjanke/brew/tags","blobs_url":"https://api.github.com/repos/apjanke/brew/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apjanke/brew/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apjanke/brew/git/refs{/sha}","trees_url":"https://api.github.com/repos/apjanke/brew/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apjanke/brew/statuses/{sha}","languages_url":"https://api.github.com/repos/apjanke/brew/languages","stargazers_url":"https://api.github.com/repos/apjanke/brew/stargazers","contributors_url":"https://api.github.com/repos/apjanke/brew/contributors","subscribers_url":"https://api.github.com/repos/apjanke/brew/subscribers","subscription_url":"https://api.github.com/repos/apjanke/brew/subscription","commits_url":"https://api.github.com/repos/apjanke/brew/commits{/sha}","git_commits_url":"https://api.github.com/repos/apjanke/brew/git/commits{/sha}","comments_url":"https://api.github.com/repos/apjanke/brew/comments{/number}","issue_comment_url":"https://api.github.com/repos/apjanke/brew/issues/comments{/number}","contents_url":"https://api.github.com/repos/apjanke/brew/contents/{+path}","compare_url":"https://api.github.com/repos/apjanke/brew/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apjanke/brew/merges","archive_url":"https://api.github.com/repos/apjanke/brew/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apjanke/brew/downloads","issues_url":"https://api.github.com/repos/apjanke/brew/issues{/number}","pulls_url":"https://api.github.com/repos/apjanke/brew/pulls{/number}","milestones_url":"https://api.github.com/repos/apjanke/brew/milestones{/number}","notifications_url":"https://api.github.com/repos/apjanke/brew/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apjanke/brew/labels{/name}","releases_url":"https://api.github.com/repos/apjanke/brew/releases{/id}","deployments_url":"https://api.github.com/repos/apjanke/brew/deployments","created_at":"2016-04-05T13:55:02Z","updated_at":"2016-04-05T13:55:04Z","pushed_at":"2016-04-22T20:57:19Z","git_url":"git://github.com/apjanke/brew.git","ssh_url":"git@github.com:apjanke/brew.git","clone_url":"https://github.com/apjanke/brew.git","svn_url":"https://github.com/apjanke/brew","homepage":"http://brew.sh","size":11472,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":false,"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":"Homebrew:master","ref":"master","sha":"2921795668970f9b5598037fc55940d29ba941d6","user":{"login":"Homebrew","id":1503512,"avatar_url":"https://avatars.githubusercontent.com/u/1503512?v=3","gravatar_id":"","url":"https://api.github.com/users/Homebrew","html_url":"https://github.com/Homebrew","followers_url":"https://api.github.com/users/Homebrew/followers","following_url":"https://api.github.com/users/Homebrew/following{/other_user}","gists_url":"https://api.github.com/users/Homebrew/gists{/gist_id}","starred_url":"https://api.github.com/users/Homebrew/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Homebrew/subscriptions","organizations_url":"https://api.github.com/users/Homebrew/orgs","repos_url":"https://api.github.com/users/Homebrew/repos","events_url":"https://api.github.com/users/Homebrew/events{/privacy}","received_events_url":"https://api.github.com/users/Homebrew/received_events","type":"Organization","site_admin":false},"repo":{"id":53238813,"name":"brew","full_name":"Homebrew/brew","owner":{"login":"Homebrew","id":1503512,"avatar_url":"https://avatars.githubusercontent.com/u/1503512?v=3","gravatar_id":"","url":"https://api.github.com/users/Homebrew","html_url":"https://github.com/Homebrew","followers_url":"https://api.github.com/users/Homebrew/followers","following_url":"https://api.github.com/users/Homebrew/following{/other_user}","gists_url":"https://api.github.com/users/Homebrew/gists{/gist_id}","starred_url":"https://api.github.com/users/Homebrew/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Homebrew/subscriptions","organizations_url":"https://api.github.com/users/Homebrew/orgs","repos_url":"https://api.github.com/users/Homebrew/repos","events_url":"https://api.github.com/users/Homebrew/events{/privacy}","received_events_url":"https://api.github.com/users/Homebrew/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Homebrew/brew","description":":beer: The missing package manager for OS X","fork":false,"url":"https://api.github.com/repos/Homebrew/brew","forks_url":"https://api.github.com/repos/Homebrew/brew/forks","keys_url":"https://api.github.com/repos/Homebrew/brew/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Homebrew/brew/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Homebrew/brew/teams","hooks_url":"https://api.github.com/repos/Homebrew/brew/hooks","issue_events_url":"https://api.github.com/repos/Homebrew/brew/issues/events{/number}","events_url":"https://api.github.com/repos/Homebrew/brew/events","assignees_url":"https://api.github.com/repos/Homebrew/brew/assignees{/user}","branches_url":"https://api.github.com/repos/Homebrew/brew/branches{/branch}","tags_url":"https://api.github.com/repos/Homebrew/brew/tags","blobs_url":"https://api.github.com/repos/Homebrew/brew/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Homebrew/brew/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Homebrew/brew/git/refs{/sha}","trees_url":"https://api.github.com/repos/Homebrew/brew/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Homebrew/brew/statuses/{sha}","languages_url":"https://api.github.com/repos/Homebrew/brew/languages","stargazers_url":"https://api.github.com/repos/Homebrew/brew/stargazers","contributors_url":"https://api.github.com/repos/Homebrew/brew/contributors","subscribers_url":"https://api.github.com/repos/Homebrew/brew/subscribers","subscription_url":"https://api.github.com/repos/Homebrew/brew/subscription","commits_url":"https://api.github.com/repos/Homebrew/brew/commits{/sha}","git_commits_url":"https://api.github.com/repos/Homebrew/brew/git/commits{/sha}","comments_url":"https://api.github.com/repos/Homebrew/brew/comments{/number}","issue_comment_url":"https://api.github.com/repos/Homebrew/brew/issues/comments{/number}","contents_url":"https://api.github.com/repos/Homebrew/brew/contents/{+path}","compare_url":"https://api.github.com/repos/Homebrew/brew/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Homebrew/brew/merges","archive_url":"https://api.github.com/repos/Homebrew/brew/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Homebrew/brew/downloads","issues_url":"https://api.github.com/repos/Homebrew/brew/issues{/number}","pulls_url":"https://api.github.com/repos/Homebrew/brew/pulls{/number}","milestones_url":"https://api.github.com/repos/Homebrew/brew/milestones{/number}","notifications_url":"https://api.github.com/repos/Homebrew/brew/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Homebrew/brew/labels{/name}","releases_url":"https://api.github.com/repos/Homebrew/brew/releases{/id}","deployments_url":"https://api.github.com/repos/Homebrew/brew/deployments","created_at":"2016-03-06T05:08:38Z","updated_at":"2016-04-22T21:04:45Z","pushed_at":"2016-04-22T20:59:33Z","git_url":"git://github.com/Homebrew/brew.git","ssh_url":"git@github.com:Homebrew/brew.git","clone_url":"https://github.com/Homebrew/brew.git","svn_url":"https://github.com/Homebrew/brew","homepage":"http://brew.sh","size":11578,"stargazers_count":579,"watchers_count":579,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":130,"mirror_url":null,"open_issues_count":33,"forks":130,"open_issues":33,"watchers":579,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Homebrew/brew/pulls/132"},"html":{"href":"https://github.com/Homebrew/brew/pull/132"},"issue":{"href":"https://api.github.com/repos/Homebrew/brew/issues/132"},"comments":{"href":"https://api.github.com/repos/Homebrew/brew/issues/132/comments"},"review_comments":{"href":"https://api.github.com/repos/Homebrew/brew/pulls/132/comments"},"review_comment":{"href":"https://api.github.com/repos/Homebrew/brew/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Homebrew/brew/pulls/132/commits"},"statuses":{"href":"https://api.github.com/repos/Homebrew/brew/statuses/60e07b294cdb5802e9c16c7e13de8cff9338136e"}}}}