From 41e25209f7486676f633ae05d7fc61e05af07b90 Mon Sep 17 00:00:00 2001
From: Alyssa Ross <hi@alyssa.is>
Date: Mon, 19 Sep 2016 20:53:39 +0100
Subject: [PATCH] Save runtime dependencies in INSTALL_RECEIPT.json

Fixes #930
---
 Library/Homebrew/formula.rb                 |  6 ++++++
 Library/Homebrew/tab.rb                     |  7 +++++++
 Library/Homebrew/test/fixtures/receipt.json |  6 ++++++
 Library/Homebrew/test/test_formula.rb       | 21 +++++++++++++++++++++
 Library/Homebrew/test/test_tab.rb           | 19 ++++++++++++++++++-
 5 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index cdbc905762..4a48a5749a 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -1450,6 +1450,12 @@ class Formula
     Requirement.expand(self, &block)
   end
 
+  # Returns a list of Dependency objects that are required at runtime.
+  # @private
+  def runtime_dependencies
+    recursive_dependencies.reject(&:build?)
+  end
+
   # @private
   def to_hash
     hsh = {
diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb
index 53338a0355..12b23cc734 100644
--- a/Library/Homebrew/tab.rb
+++ b/Library/Homebrew/tab.rb
@@ -30,6 +30,10 @@ class Tab < OpenStruct
       "HEAD" => HOMEBREW_REPOSITORY.git_head,
       "compiler" => compiler,
       "stdlib" => stdlib,
+      "runtime_dependencies" => formula.runtime_dependencies.map do |dep|
+        f = dep.to_formula
+        { "full_name" => f.full_name, "version" => f.version.to_s }
+      end,
       "source" => {
         "path" => formula.specified_path.to_s,
         "tap" => formula.tap ? formula.tap.name : nil,
@@ -56,6 +60,7 @@ class Tab < OpenStruct
   def self.from_file_content(content, path)
     attributes = Utils::JSON.load(content)
     attributes["tabfile"] = path
+    attributes["runtime_dependencies"] ||= []
     attributes["source_modified_time"] ||= 0
     attributes["source"] ||= {}
 
@@ -172,6 +177,7 @@ class Tab < OpenStruct
       "HEAD" => nil,
       "stdlib" => nil,
       "compiler" => DevelopmentTools.default_compiler,
+      "runtime_dependencies" => [],
       "source" => {
         "path" => nil,
         "tap" => nil,
@@ -303,6 +309,7 @@ class Tab < OpenStruct
       "HEAD" => self.HEAD,
       "stdlib" => (stdlib.to_s if stdlib),
       "compiler" => (compiler.to_s if compiler),
+      "runtime_dependencies" => runtime_dependencies,
       "source" => source,
     }
 
diff --git a/Library/Homebrew/test/fixtures/receipt.json b/Library/Homebrew/test/fixtures/receipt.json
index 585a4e27de..62672bfa97 100644
--- a/Library/Homebrew/test/fixtures/receipt.json
+++ b/Library/Homebrew/test/fixtures/receipt.json
@@ -14,6 +14,12 @@
   "alias_path": "/usr/local/Library/Taps/homebrew/homebrew-core/Aliases/test-formula",
   "stdlib": "libcxx",
   "compiler": "clang",
+  "runtime_dependencies": [
+    {
+      "full_name": "foo",
+      "version": "1.0"
+    }
+  ],
   "source": {
       "path": "/usr/local/Library/Taps/hombrew/homebrew-core/Formula/foo.rb",
       "tap": "homebrew/core",
diff --git a/Library/Homebrew/test/test_formula.rb b/Library/Homebrew/test/test_formula.rb
index dcb3e3349f..9207f8ead7 100644
--- a/Library/Homebrew/test/test_formula.rb
+++ b/Library/Homebrew/test/test_formula.rb
@@ -638,6 +638,27 @@ class FormulaTests < Homebrew::TestCase
       f1.test_fixtures("foo")
   end
 
+  def test_dependencies
+    stub_formula_loader formula("f1") { url "f1-1.0" }
+    stub_formula_loader formula("f2") { url "f2-1.0" }
+
+    f3 = formula("f3") do
+      url "f3-1.0"
+      depends_on "f1" => :build
+      depends_on "f2"
+    end
+    stub_formula_loader f3
+
+    f4 = formula("f4") do
+      url "f4-1.0"
+      depends_on "f3"
+    end
+
+    assert_equal %w[f3], f4.deps.map(&:name)
+    assert_equal %w[f1 f2 f3], f4.recursive_dependencies.map(&:name)
+    assert_equal %w[f2 f3], f4.runtime_dependencies.map(&:name)
+  end
+
   def test_to_hash
     f1 = formula("foo") do
       url "foo-1.0"
diff --git a/Library/Homebrew/test/test_tab.rb b/Library/Homebrew/test/test_tab.rb
index 2efaee983a..ea4936c4b0 100644
--- a/Library/Homebrew/test/test_tab.rb
+++ b/Library/Homebrew/test/test_tab.rb
@@ -16,6 +16,7 @@ class TabTests < Homebrew::TestCase
                    "HEAD"                 => TEST_SHA1,
                    "compiler"             => "clang",
                    "stdlib"               => "libcxx",
+                   "runtime_dependencies" => [],
                    "source"               => {
                      "tap" => "homebrew/core",
                      "path" => nil,
@@ -40,6 +41,7 @@ class TabTests < Homebrew::TestCase
     assert_nil tab.tap
     assert_nil tab.time
     assert_nil tab.HEAD
+    assert_empty tab.runtime_dependencies
     assert_nil tab.stable_version
     assert_nil tab.devel_version
     assert_nil tab.head_version
@@ -95,12 +97,14 @@ class TabTests < Homebrew::TestCase
     assert_equal TEST_SHA1, tab.HEAD
     assert_equal :clang, tab.cxxstdlib.compiler
     assert_equal :libcxx, tab.cxxstdlib.type
+    assert_empty tab.runtime_dependencies
   end
 
   def test_from_file
     path = Pathname.new(TEST_DIRECTORY).join("fixtures", "receipt.json")
     tab = Tab.from_file(path)
     source_path = "/usr/local/Library/Taps/hombrew/homebrew-core/Formula/foo.rb"
+    runtime_dependencies = [{ "full_name" => "foo", "version" => "1.0" }]
 
     assert_equal @used.sort, tab.used_options.sort
     assert_equal @unused.sort, tab.unused_options.sort
@@ -115,6 +119,7 @@ class TabTests < Homebrew::TestCase
     assert_equal TEST_SHA1, tab.HEAD
     assert_equal :clang, tab.cxxstdlib.compiler
     assert_equal :libcxx, tab.cxxstdlib.type
+    assert_equal runtime_dependencies, tab.runtime_dependencies
     assert_equal "2.14", tab.stable_version.to_s
     assert_equal "2.15", tab.devel_version.to_s
     assert_equal "HEAD-0000000", tab.head_version.to_s
@@ -122,11 +127,22 @@ class TabTests < Homebrew::TestCase
   end
 
   def test_create
-    f = formula { url "foo-1.0" }
+    f = formula do
+      url "foo-1.0"
+      depends_on "bar"
+      depends_on "baz" => :build
+    end
+
+    stub_formula_loader formula("bar") { url "bar-2.0" }
+    stub_formula_loader formula("baz") { url "baz-3.0" }
+
     compiler = DevelopmentTools.default_compiler
     stdlib = :libcxx
     tab = Tab.create(f, compiler, stdlib)
 
+    runtime_dependencies = [{ "full_name" => "bar", "version" => "2.0" }]
+
+    assert_equal runtime_dependencies, tab.runtime_dependencies
     assert_equal f.path.to_s, tab.source["path"]
   end
 
@@ -167,6 +183,7 @@ class TabTests < Homebrew::TestCase
     assert_equal @tab.HEAD, tab.HEAD
     assert_equal @tab.compiler, tab.compiler
     assert_equal @tab.stdlib, tab.stdlib
+    assert_equal @tab.runtime_dependencies, tab.runtime_dependencies
     assert_equal @tab.stable_version, tab.stable_version
     assert_equal @tab.devel_version, tab.devel_version
     assert_equal @tab.head_version, tab.head_version
-- 
GitLab