{"action":"created","comment":{"url":"https://api.github.com/repos/Homebrew/brew/pulls/comments/170892476","pull_request_review_id":99647161,"id":170892476,"diff_hunk":"@@ -0,0 +1,137 @@\n+require \"dbm\"\n+require \"json\"\n+\n+#\n+# `DatabaseCache` acts as an interface to a persistent storage mechanism\n+# residing in the `HOMEBREW_CACHE`\n+#\n+class DatabaseCache\n+  # Users have read and write, but not execute permissions\n+  DATABASE_MODE = 0666\n+\n+  # Opens and yields a database in read/write mode\n+  #\n+  # DBM::WRCREAT: Creates the database if it does not already exist\n+  def initialize(name)\n+    @db = DBM.open(\"#{HOMEBREW_CACHE}/#{name}.db\", DATABASE_MODE, DBM::WRCREAT)\n+    yield(@db)\n+    @db.close\n+  end\n+end\n+\n+#\n+# `CacheStore` provides methods to mutate and fetch data from a persistent\n+# storage mechanism\n+#\n+class CacheStore\n+  def initialize(database_cache)\n+    @database_cache = database_cache\n+  end\n+\n+  # Inserts new values or updates existing cached values to persistent storage\n+  # mechanism\n+  def update!(*)\n+    raise NotImplementedError\n+  end\n+\n+  # Fetches cached values in persistent storage according to the type of data\n+  # stored\n+  def fetch_type(*)\n+    raise NotImplementedError\n+  end\n+\n+  # Deletes data from the cache based on a condition defined in a concrete class\n+  def flush_cache!\n+    raise NotImplementedError\n+  end\n+\n+  protected\n+\n+  attr_reader :database_cache\n+\n+  # Parses `DBM` stored `String` into ruby `Hash`\n+  #\n+  # DBM stores ruby objects as a ruby `String`. Hence, when fetching the data,\n+  # to convert the ruby string back into a ruby `Hash`, the string is converted\n+  # into a JSON compatible string, where it may be parsed by the JSON.parse\n+  # function\n+  def string_to_hash(string)\n+    JSON.parse(string.gsub(\"=>\", \":\"))\n+  end\n+end\n+\n+#\n+# `LinkageStore` provides methods to fetch and mutate linkage-specific data used\n+# by the `brew linkage` command\n+#\n+class LinkageStore < CacheStore\n+  HASH_LINKAGE_TYPES = [:brewed_dylibs, :reverse_links].freeze\n+\n+  def initialize(keg_name, database_cache)\n+    @keg_name = keg_name\n+    super(database_cache)\n+  end\n+\n+  def update!(\n+    path_values: {\n+      system_dylibs: %w[],\n+      variable_dylibs: %w[],\n+      broken_dylibs: %w[],\n+      indirect_deps: %w[],\n+      undeclared_deps:  %w[],\n+      unnecessary_deps: %w[],\n+    },\n+    hash_values: {\n+      brewed_dylibs: {},\n+      reverse_links: {},\n+    }\n+  )\n+    database_cache[keg_name] = {\n+      \"path_values\" => format_path_values(path_values),","path":"Library/Homebrew/os/mac/cache_store.rb","position":90,"original_position":90,"commit_id":"4bc6459ed7e4ad2aaa564dfbb90b2871489e058c","original_commit_id":"4bc6459ed7e4ad2aaa564dfbb90b2871489e058c","user":{"login":"MikeMcQuaid","id":125011,"avatar_url":"https://avatars2.githubusercontent.com/u/125011?v=4","gravatar_id":"","url":"https://api.github.com/users/MikeMcQuaid","html_url":"https://github.com/MikeMcQuaid","followers_url":"https://api.github.com/users/MikeMcQuaid/followers","following_url":"https://api.github.com/users/MikeMcQuaid/following{/other_user}","gists_url":"https://api.github.com/users/MikeMcQuaid/gists{/gist_id}","starred_url":"https://api.github.com/users/MikeMcQuaid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MikeMcQuaid/subscriptions","organizations_url":"https://api.github.com/users/MikeMcQuaid/orgs","repos_url":"https://api.github.com/users/MikeMcQuaid/repos","events_url":"https://api.github.com/users/MikeMcQuaid/events{/privacy}","received_events_url":"https://api.github.com/users/MikeMcQuaid/received_events","type":"User","site_admin":true},"body":"Can this use symbolic keys too?","created_at":"2018-02-27T11:28:56Z","updated_at":"2018-02-27T11:33:47Z","html_url":"https://github.com/Homebrew/brew/pull/3720#discussion_r170892476","pull_request_url":"https://api.github.com/repos/Homebrew/brew/pulls/3720","author_association":"OWNER","_links":{"self":{"href":"https://api.github.com/repos/Homebrew/brew/pulls/comments/170892476"},"html":{"href":"https://github.com/Homebrew/brew/pull/3720#discussion_r170892476"},"pull_request":{"href":"https://api.github.com/repos/Homebrew/brew/pulls/3720"}}},"pull_request":{"url":"https://api.github.com/repos/Homebrew/brew/pulls/3720","id":164429248,"html_url":"https://github.com/Homebrew/brew/pull/3720","diff_url":"https://github.com/Homebrew/brew/pull/3720.diff","patch_url":"https://github.com/Homebrew/brew/pull/3720.patch","issue_url":"https://api.github.com/repos/Homebrew/brew/issues/3720","number":3720,"state":"open","locked":false,"title":"Cache optimization for `brew linkage` command.","user":{"login":"AndrewMcBurney","id":8942499,"avatar_url":"https://avatars3.githubusercontent.com/u/8942499?v=4","gravatar_id":"","url":"https://api.github.com/users/AndrewMcBurney","html_url":"https://github.com/AndrewMcBurney","followers_url":"https://api.github.com/users/AndrewMcBurney/followers","following_url":"https://api.github.com/users/AndrewMcBurney/following{/other_user}","gists_url":"https://api.github.com/users/AndrewMcBurney/gists{/gist_id}","starred_url":"https://api.github.com/users/AndrewMcBurney/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AndrewMcBurney/subscriptions","organizations_url":"https://api.github.com/users/AndrewMcBurney/orgs","repos_url":"https://api.github.com/users/AndrewMcBurney/repos","events_url":"https://api.github.com/users/AndrewMcBurney/events{/privacy}","received_events_url":"https://api.github.com/users/AndrewMcBurney/received_events","type":"User","site_admin":false},"body":"- [x] Have you followed the guidelines in our [Contributing](https://github.com/Homebrew/brew/blob/master/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- [x] 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 run `brew style` with your changes locally?\r\n- [x] Have you successfully run `brew tests` with your changes locally?\r\n\r\n-----\r\n\r\nHi Homebrew maintainers!\r\n\r\nThis is my first time contributing to Homebrew. I saw issue https://github.com/Homebrew/brew/issues/3008, and thought it would be a good first issue to work on.\r\n\r\nThis pull request is still a work-in-progress. I was hoping to get some advice from the maintainers before proceeding any further.\r\n\r\nI implemented a simple caching mechanism using SQLite3 to store `brew linkage`-related data on-disk in a database located in the `HOMEBREW_CACHE` directory.\r\n\r\nThe pull request creates two new files (`Library/Homebrew/os/mac/linkage_store.rb` and `Library/Homebrew/os/mac/linkage_database.rb`), and changes a bit of `Library/Homebrew/os/mac/linkage_checker.rb`.\r\n\r\nAny constructive criticism and/or design advice would be greatly appreciated!\r\n\r\nAll the best,\r\nAndrew\r\n\r\n## Performance Enhancements\r\n\r\nThe caching improves performance for the `brew linkage` command. I've attached two flame graphs showing the breakdown of the command time, as well as two sample runs of the command each with 106 packages (including larger packages such as boost).\r\n\r\nThe command runs in under 5 seconds (as requested in #3008) with the caching mechanism utilized.\r\n\r\n- The first command run has a new `--rebuild` flag, which forces the cache to rebuild. The behaviour of the command with the `--rebuild` flag is equivalent to the current behaviour of the `brew linkage` command.\r\n- The second command run utilizes the SQLite3 caching, which is utilized by default.\r\n\r\n### Flame Graphs\r\n\r\n**Without Optimization**\r\n\r\n_Without the caching (i.e., using the `--rebuild` flag) the command (instrumented starting from `linkage.rb`) took 11.5 seconds to complete. The library `boost` took 1.01 seconds to complete checking dylibs._\r\n\r\n<img width=\"1440\" alt=\"screen shot 2018-01-23 at 10 40 02 am\" src=\"https://user-images.githubusercontent.com/8942499/35285041-5ace4ece-002a-11e8-82d8-679e989e8191.png\">\r\n\r\n**With Optimization**\r\n\r\n_With the caching (i.e., by default) the command (instrumented starting from `linkage.rb`) took 182 milliseconds to complete. The library `boost` took 1.38 milliseconds to complete checking dylibs._\r\n\r\n<img width=\"1440\" alt=\"screen shot 2018-01-23 at 10 40 38 am\" src=\"https://user-images.githubusercontent.com/8942499/35285045-5c592d18-002a-11e8-9489-5a6f72ca3c95.png\">\r\n\r\n### Input\r\n\r\n**Run 1 (no caching)**\r\n```bash\r\ntime brew linkage --rebuild apache-spark docker gettext heroku libidn2 mysql py2cairo sbt atk docker-compose gimme hicolor-icon-theme libmpc nettle pyenv scala autoconf docker-machine git hub libpng node pyenv-virtualenv scalastyle automake dockutil glfw hugo librsvg nvm pygobject sqlite bash elasticsearch glib icu4c libtasn1 openjpeg pygtk texinfo bdw-gc elixir glm imagemagick libtiff openssl python tree boost emacs gmp imagemagick@6 libtool openssl@1.1 python3 wget cairo emacs-plus gnu-sed isl libunistring p11-kit r wxmac cask erlang gnutls ispell libyaml pango rbenv xz cmake fontconfig go jpeg little-cms2 pcre rbenv-gemset yarn coreutils freetype gobject-introspection jruby llvm pixman readline zookeeper crystal-lang gcc graphite2 libcroco lua pkg-config redis dash gdbm gtk+ libevent maven poppler ruby dateutils gdk-pixbuf harfbuzz libffi mpfr postgresql ruby-build\r\n```\r\n\r\nRun 2 (SQLite3 caching)\r\n```bash\r\ntime brew linkage apache-spark docker gettext heroku libidn2 mysql py2cairo sbt atk docker-compose gimme hicolor-icon-theme libmpc nettle pyenv scala autoconf docker-machine git hub libpng node pyenv-virtualenv scalastyle automake dockutil glfw hugo librsvg nvm pygobject sqlite bash elasticsearch glib icu4c libtasn1 openjpeg pygtk texinfo bdw-gc elixir glm imagemagick libtiff openssl python tree boost emacs gmp imagemagick@6 libtool openssl@1.1 python3 wget cairo emacs-plus gnu-sed isl libunistring p11-kit r wxmac cask erlang gnutls ispell libyaml pango rbenv xz cmake fontconfig go jpeg little-cms2 pcre rbenv-gemset yarn coreutils freetype gobject-introspection jruby llvm pixman readline zookeeper crystal-lang gcc graphite2 libcroco lua pkg-config redis dash gdbm gtk+ libevent maven poppler ruby dateutils gdk-pixbuf harfbuzz libffi mpfr postgresql ruby-build\r\n```\r\n\r\n### Output\r\n\r\n**Run 1 (no caching)**\r\n```bash\r\n...\r\nbrew linkage --rebuild apache-spark docker gettext heroku libidn2 mysql  sbt   5.46s user 5.30s system 94% cpu 11.418 total\r\n```\r\n\r\n**Run 2 (SQLite3 caching)**\r\n```bash\r\n...\r\nbrew linkage apache-spark docker gettext heroku libidn2 mysql py2cairo sbt at  0.85s user 0.56s system 73% cpu 1.898 total\r\n```\r\n\r\n## Files Changed\r\n\r\n**[`Library/Homebrew/os/mac/linkage_database.rb`](https://github.com/AndrewMcBurney/brew/blob/cache-optimization/Library/Homebrew/os/mac/linkage_database.rb)**\r\n\r\n`LinkageDatabase` is a module to interface with the SQLite3 `linkage` database. The public interface is:\r\n\r\n```ruby\r\n# Expose linkage database through LinkageDatabase module\r\ndef db\r\n  @db ||= SQLite3::Database.new \"#{HOMEBREW_CACHE}/linkage.db\"\r\nend\r\n\r\n# Checks if the database has been initialized\r\ndef empty?(keys:)\r\n  ...\r\nend\r\n\r\n# Takes in an array of strings, and formats them into a SQL list string\r\ndef format_database_list(list)\r\n  ...\r\nend\r\n```\r\n\r\n**Caching Schema**\r\n\r\nThe schema for the caching is a single table schema, which includes relevant linkage information.\r\n\r\n```sql\r\nCREATE TABLE IF NOT EXISTS linkage (\r\n  id INTEGER PRIMARY KEY AUTOINCREMENT,\r\n  name TEXT NOT NULL,\r\n  path TEXT NOT NULL,\r\n  type TEXT NOT NULL CHECK (type IN (#{all_types})),\r\n  label TEXT CHECK (label IS NULL OR (type IN (#{hash_types}))),\r\n  UNIQUE(name, path, type, label) ON CONFLICT IGNORE\r\n);\r\n```\r\n\r\n**[`Library/Homebrew/os/mac/linkage_store.rb`](https://github.com/AndrewMcBurney/brew/blob/cache-optimization/Library/Homebrew/os/mac/linkage_store.rb)**\r\n\r\nThe `LinkageStore` class is a class with the responsibility to fetch, insert, update, and delete data from the SQLite3 cache.\r\n\r\nThe public interface for the class is:\r\n\r\n```ruby\r\n# Updates cached values in SQLite3 tables according to the type of data stored\r\ndef update!(\r\n      key:,\r\n      array_linkage_values: { system_dylibs: %w[], variable_dylibs: %w[],\r\n                              broken_dylibs: %w[], undeclared_deps: %w[],\r\n                              unnecessary_deps: %w[] },\r\n      hash_linkage_values: { brewed_dylibs: {}, reverse_links: {} }\r\n    )\r\n  ...\r\nend\r\n\r\n# Fetches a subset of paths by looking up an array of keys\r\ndef fetch_path_values!(type:, keys:)\r\n  ...\r\nend\r\n\r\n# Fetches path and label values from a table name given an array of keys and\r\n# returns them in a hash format with the labels as keys to an array of paths\r\ndef fetch_hash_values!(type:, keys:)\r\n  ...\r\nend\r\n\r\n# Deletes rows given an array of keys. If the row's name\r\n# attribute contains a value in the array of keys, then that row is deleted\r\ndef flush_cache_for_keys!(keys:)\r\n  ...\r\nend\r\n```\r\n\r\n**[`Library/Homebrew/dev-cmd/linkage.rb`](https://github.com/AndrewMcBurney/brew/blob/cache-optimization/Library/Homebrew/dev-cmd/linkage.rb)**\r\n\r\nThe `brew linkage` command now has the option to pass in the `--rebuild` flag. This flag will force the cache to rebuild, and the `LinkageChecker` will call `check_dylibs` for each of the `kegs` passed into the command. This option causes the command to work like it currently does (without the SQLite3 caching). By default, the `brew linkage` command will now use caching.\r\n\r\n## Questions\r\n\r\n**Updating the cache for a single keg**\r\n- At what point should I update the cache for a single keg? I was thinking `brew install <formula>`, but I'm not sure if there are any other commands where I should be updating the cache for a particular keg.\r\n\r\n**Updating the cache for multiple kegs**\r\n- At what points should I update the cache for multiple kegs at once? I was thinking when the `brew update` command is invoked the cache should be invalidated (ie. flushed) and updated on the next run of the `brew linkage` command.\r\n- Any advice on how to handle updating multiple kegs, and are there any cases I'm not considering where the cache would need to be updated?\r\n\r\n**How do you recommend writing tests for these changes?**\r\n- Does Homebrew have any specific output matchers or helper functions that would be useful to write tests for my changes?\r\n\r\n## Outstanding Issues\r\n\r\n- Write benchmark and integration tests for the caching system\r\n- Write unit tests for `Library/Homebrew/os/mac/linkage_database.rb` and `Library/Homebrew/os/mac/linkage_store.rb`.\r\n","created_at":"2018-01-22T22:05:22Z","updated_at":"2018-02-27T11:33:48Z","closed_at":null,"merged_at":null,"merge_commit_sha":"83f982adeddbbc100a76d7df9ec8754644caab60","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/Homebrew/brew/pulls/3720/commits","review_comments_url":"https://api.github.com/repos/Homebrew/brew/pulls/3720/comments","review_comment_url":"https://api.github.com/repos/Homebrew/brew/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Homebrew/brew/issues/3720/comments","statuses_url":"https://api.github.com/repos/Homebrew/brew/statuses/4bc6459ed7e4ad2aaa564dfbb90b2871489e058c","head":{"label":"AndrewMcBurney:cache-optimization","ref":"cache-optimization","sha":"4bc6459ed7e4ad2aaa564dfbb90b2871489e058c","user":{"login":"AndrewMcBurney","id":8942499,"avatar_url":"https://avatars3.githubusercontent.com/u/8942499?v=4","gravatar_id":"","url":"https://api.github.com/users/AndrewMcBurney","html_url":"https://github.com/AndrewMcBurney","followers_url":"https://api.github.com/users/AndrewMcBurney/followers","following_url":"https://api.github.com/users/AndrewMcBurney/following{/other_user}","gists_url":"https://api.github.com/users/AndrewMcBurney/gists{/gist_id}","starred_url":"https://api.github.com/users/AndrewMcBurney/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AndrewMcBurney/subscriptions","organizations_url":"https://api.github.com/users/AndrewMcBurney/orgs","repos_url":"https://api.github.com/users/AndrewMcBurney/repos","events_url":"https://api.github.com/users/AndrewMcBurney/events{/privacy}","received_events_url":"https://api.github.com/users/AndrewMcBurney/received_events","type":"User","site_admin":false},"repo":{"id":117751001,"name":"brew","full_name":"AndrewMcBurney/brew","owner":{"login":"AndrewMcBurney","id":8942499,"avatar_url":"https://avatars3.githubusercontent.com/u/8942499?v=4","gravatar_id":"","url":"https://api.github.com/users/AndrewMcBurney","html_url":"https://github.com/AndrewMcBurney","followers_url":"https://api.github.com/users/AndrewMcBurney/followers","following_url":"https://api.github.com/users/AndrewMcBurney/following{/other_user}","gists_url":"https://api.github.com/users/AndrewMcBurney/gists{/gist_id}","starred_url":"https://api.github.com/users/AndrewMcBurney/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AndrewMcBurney/subscriptions","organizations_url":"https://api.github.com/users/AndrewMcBurney/orgs","repos_url":"https://api.github.com/users/AndrewMcBurney/repos","events_url":"https://api.github.com/users/AndrewMcBurney/events{/privacy}","received_events_url":"https://api.github.com/users/AndrewMcBurney/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/AndrewMcBurney/brew","description":"🍺 The missing package manager for macOS","fork":true,"url":"https://api.github.com/repos/AndrewMcBurney/brew","forks_url":"https://api.github.com/repos/AndrewMcBurney/brew/forks","keys_url":"https://api.github.com/repos/AndrewMcBurney/brew/keys{/key_id}","collaborators_url":"https://api.github.com/repos/AndrewMcBurney/brew/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/AndrewMcBurney/brew/teams","hooks_url":"https://api.github.com/repos/AndrewMcBurney/brew/hooks","issue_events_url":"https://api.github.com/repos/AndrewMcBurney/brew/issues/events{/number}","events_url":"https://api.github.com/repos/AndrewMcBurney/brew/events","assignees_url":"https://api.github.com/repos/AndrewMcBurney/brew/assignees{/user}","branches_url":"https://api.github.com/repos/AndrewMcBurney/brew/branches{/branch}","tags_url":"https://api.github.com/repos/AndrewMcBurney/brew/tags","blobs_url":"https://api.github.com/repos/AndrewMcBurney/brew/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/AndrewMcBurney/brew/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/AndrewMcBurney/brew/git/refs{/sha}","trees_url":"https://api.github.com/repos/AndrewMcBurney/brew/git/trees{/sha}","statuses_url":"https://api.github.com/repos/AndrewMcBurney/brew/statuses/{sha}","languages_url":"https://api.github.com/repos/AndrewMcBurney/brew/languages","stargazers_url":"https://api.github.com/repos/AndrewMcBurney/brew/stargazers","contributors_url":"https://api.github.com/repos/AndrewMcBurney/brew/contributors","subscribers_url":"https://api.github.com/repos/AndrewMcBurney/brew/subscribers","subscription_url":"https://api.github.com/repos/AndrewMcBurney/brew/subscription","commits_url":"https://api.github.com/repos/AndrewMcBurney/brew/commits{/sha}","git_commits_url":"https://api.github.com/repos/AndrewMcBurney/brew/git/commits{/sha}","comments_url":"https://api.github.com/repos/AndrewMcBurney/brew/comments{/number}","issue_comment_url":"https://api.github.com/repos/AndrewMcBurney/brew/issues/comments{/number}","contents_url":"https://api.github.com/repos/AndrewMcBurney/brew/contents/{+path}","compare_url":"https://api.github.com/repos/AndrewMcBurney/brew/compare/{base}...{head}","merges_url":"https://api.github.com/repos/AndrewMcBurney/brew/merges","archive_url":"https://api.github.com/repos/AndrewMcBurney/brew/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/AndrewMcBurney/brew/downloads","issues_url":"https://api.github.com/repos/AndrewMcBurney/brew/issues{/number}","pulls_url":"https://api.github.com/repos/AndrewMcBurney/brew/pulls{/number}","milestones_url":"https://api.github.com/repos/AndrewMcBurney/brew/milestones{/number}","notifications_url":"https://api.github.com/repos/AndrewMcBurney/brew/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/AndrewMcBurney/brew/labels{/name}","releases_url":"https://api.github.com/repos/AndrewMcBurney/brew/releases{/id}","deployments_url":"https://api.github.com/repos/AndrewMcBurney/brew/deployments","created_at":"2018-01-16T22:34:30Z","updated_at":"2018-01-16T22:34:34Z","pushed_at":"2018-02-25T17:15:20Z","git_url":"git://github.com/AndrewMcBurney/brew.git","ssh_url":"git@github.com:AndrewMcBurney/brew.git","clone_url":"https://github.com/AndrewMcBurney/brew.git","svn_url":"https://github.com/AndrewMcBurney/brew","homepage":"https://brew.sh","size":22808,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"Homebrew:master","ref":"master","sha":"8a30be74424538aeec3139f1d06bdbb7b38e75b7","user":{"login":"Homebrew","id":1503512,"avatar_url":"https://avatars2.githubusercontent.com/u/1503512?v=4","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://avatars2.githubusercontent.com/u/1503512?v=4","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":"🍺 The missing package manager for macOS","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":"2018-02-27T11:31:34Z","pushed_at":"2018-02-27T10:57:25Z","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":"https://brew.sh","size":22855,"stargazers_count":11199,"watchers_count":11199,"language":"Ruby","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":2659,"mirror_url":null,"archived":false,"open_issues_count":27,"license":{"key":"bsd-2-clause","name":"BSD 2-Clause \"Simplified\" License","spdx_id":"BSD-2-Clause","url":"https://api.github.com/licenses/bsd-2-clause"},"forks":2659,"open_issues":27,"watchers":11199,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Homebrew/brew/pulls/3720"},"html":{"href":"https://github.com/Homebrew/brew/pull/3720"},"issue":{"href":"https://api.github.com/repos/Homebrew/brew/issues/3720"},"comments":{"href":"https://api.github.com/repos/Homebrew/brew/issues/3720/comments"},"review_comments":{"href":"https://api.github.com/repos/Homebrew/brew/pulls/3720/comments"},"review_comment":{"href":"https://api.github.com/repos/Homebrew/brew/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Homebrew/brew/pulls/3720/commits"},"statuses":{"href":"https://api.github.com/repos/Homebrew/brew/statuses/4bc6459ed7e4ad2aaa564dfbb90b2871489e058c"}},"author_association":"NONE"}}
{"actor":{"display_login":"MikeMcQuaid"}}