From e9631d969c9856d5c895abe3cebfd0591ba475ae Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Mon, 14 Jun 2021 12:01:01 -0400 Subject: [PATCH 1/5] Formulary: add `::map` to map formula refs --- Library/Homebrew/formulary.rb | 15 +++++++++++++++ Library/Homebrew/test/formulary_spec.rb | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index f3fcc3ac1e..a902e92820 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -395,6 +395,8 @@ module Formulary ) raise ArgumentError, "Formulae must have a ref!" unless ref + ref = @ref_mappings[ref] if @ref_mappings.present? && @ref_mappings.key?(ref) + cache_key = "#{ref}-#{spec}-#{alias_path}-#{from}" if factory_cached? && cache[:formulary_factory] && cache[:formulary_factory][cache_key] @@ -411,6 +413,19 @@ module Formulary formula end + # Register a reference mapping. This mapping will be used by {Formulary::factory} + # to allow certain references to be substituted for another string before + # being retrived. For example, to map `foo` to the `bar` formula: + #
Formulary.map "foo", to: "bar"
+  # Formulary.factory "bar" # returns the bar formula
+  # 
+ # @param ref the string to map. + # @param :to the target reference to which `ref` should be mapped. + def self.map(ref, to:) + @ref_mappings ||= {} + @ref_mappings[ref] = to + end + # Return a {Formula} instance for the given rack. # # @param spec when nil, will auto resolve the formula's spec. diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb index dfd1c8311a..454b064014 100644 --- a/Library/Homebrew/test/formulary_spec.rb +++ b/Library/Homebrew/test/formulary_spec.rb @@ -205,6 +205,23 @@ describe Formulary do end end + describe "::map" do + before do + formula_path.dirname.mkpath + formula_path.write formula_content + end + + it "maps a reference to a new Formula" do + expect { + described_class.factory("foo") + }.to raise_error(FormulaUnavailableError) + + described_class.map "foo", to: formula_name + + expect(described_class.factory("foo")).to be_kind_of(Formula) + end + end + specify "::from_contents" do expect(described_class.from_contents(formula_name, formula_path, formula_content)).to be_kind_of(Formula) end From 44bc942703fadd4ece7770c7a7b50fbc3e7509fe Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Mon, 14 Jun 2021 12:59:03 -0400 Subject: [PATCH 2/5] Fix tests --- Library/Homebrew/test/formulary_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb index 454b064014..e6a0a95934 100644 --- a/Library/Homebrew/test/formulary_spec.rb +++ b/Library/Homebrew/test/formulary_spec.rb @@ -213,12 +213,12 @@ describe Formulary do it "maps a reference to a new Formula" do expect { - described_class.factory("foo") + described_class.factory("formula-to-map") }.to raise_error(FormulaUnavailableError) - described_class.map "foo", to: formula_name + described_class.map "formula-to-map", to: formula_name - expect(described_class.factory("foo")).to be_kind_of(Formula) + expect(described_class.factory("formula-to-map")).to be_kind_of(Formula) end end From 75c1a23f631dd820a328a98c53fc951202a91211 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Tue, 15 Jun 2021 11:21:59 -0400 Subject: [PATCH 3/5] Rename method to `::map_name_to_bottle` --- Library/Homebrew/formulary.rb | 23 ++++++++++++----------- Library/Homebrew/test/formulary_spec.rb | 4 ++-- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index a902e92820..d3e7019045 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -395,7 +395,7 @@ module Formulary ) raise ArgumentError, "Formulae must have a ref!" unless ref - ref = @ref_mappings[ref] if @ref_mappings.present? && @ref_mappings.key?(ref) + ref = @name_mappings[ref] if @name_mappings.present? && @name_mappings.key?(ref) cache_key = "#{ref}-#{spec}-#{alias_path}-#{from}" if factory_cached? && cache[:formulary_factory] && @@ -413,17 +413,18 @@ module Formulary formula end - # Register a reference mapping. This mapping will be used by {Formulary::factory} - # to allow certain references to be substituted for another string before - # being retrived. For example, to map `foo` to the `bar` formula: - #
Formulary.map "foo", to: "bar"
-  # Formulary.factory "bar" # returns the bar formula
+  # Map a formula name to a bottle archive. This mapping will be used by {Formulary::factory}
+  # to allow formulae to be loaded automatically from their bottle archive without
+  # needing to exist in a tap or be passed as a complete filepath. For example,
+  # to map `foo` to the `hello` formula from its bottle archive:
+  # 
Formulary.map_name_to_bottle "foo", HOMEBREW_CACHE/"hello--2.10"
+  # Formulary.factory "foo" # returns the hello formula from the bottle archive
   # 
- # @param ref the string to map. - # @param :to the target reference to which `ref` should be mapped. - def self.map(ref, to:) - @ref_mappings ||= {} - @ref_mappings[ref] = to + # @param name the string to map. + # @param bottle a path pointing to the target bottle archive. + def self.map_name_to_bottle(name, bottle) + @name_mappings ||= {} + @name_mappings[name] = bottle.realpath end # Return a {Formula} instance for the given rack. diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb index e6a0a95934..e9f750a4b9 100644 --- a/Library/Homebrew/test/formulary_spec.rb +++ b/Library/Homebrew/test/formulary_spec.rb @@ -205,7 +205,7 @@ describe Formulary do end end - describe "::map" do + describe "::map_name_to_bottle" do before do formula_path.dirname.mkpath formula_path.write formula_content @@ -216,7 +216,7 @@ describe Formulary do described_class.factory("formula-to-map") }.to raise_error(FormulaUnavailableError) - described_class.map "formula-to-map", to: formula_name + described_class.map_name_to_bottle "formula-to-map", formula_path expect(described_class.factory("formula-to-map")).to be_kind_of(Formula) end From 618c41926b80de877c8d848ad35a076c75b07dd3 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Tue, 15 Jun 2021 11:32:04 -0400 Subject: [PATCH 4/5] Allow strings to be passed, too --- Library/Homebrew/formulary.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index d3e7019045..e7deac7174 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -424,7 +424,7 @@ module Formulary # @param bottle a path pointing to the target bottle archive. def self.map_name_to_bottle(name, bottle) @name_mappings ||= {} - @name_mappings[name] = bottle.realpath + @name_mappings[name] = Pathname(bottle).realpath end # Return a {Formula} instance for the given rack. From 8b04bcb9944d2675a31acf73fe1c1a3879fdad73 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Wed, 16 Jun 2021 10:27:15 -0400 Subject: [PATCH 5/5] Only allow mapping with environment variable Co-authored-by: Mike McQuaid --- Library/Homebrew/formulary.rb | 32 +++++++++++++++---------- Library/Homebrew/test/formulary_spec.rb | 10 ++++++-- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index e7deac7174..867d7237ee 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -395,7 +395,11 @@ module Formulary ) raise ArgumentError, "Formulae must have a ref!" unless ref - ref = @name_mappings[ref] if @name_mappings.present? && @name_mappings.key?(ref) + if ENV["HOMEBREW_BOTTLE_JSON"].present? && + @formula_name_local_bottle_path_map.present? && + @formula_name_local_bottle_path_map.key?(ref) + ref = @formula_name_local_bottle_path_map[ref] + end cache_key = "#{ref}-#{spec}-#{alias_path}-#{from}" if factory_cached? && cache[:formulary_factory] && @@ -413,18 +417,22 @@ module Formulary formula end - # Map a formula name to a bottle archive. This mapping will be used by {Formulary::factory} - # to allow formulae to be loaded automatically from their bottle archive without - # needing to exist in a tap or be passed as a complete filepath. For example, - # to map `foo` to the `hello` formula from its bottle archive: - #
Formulary.map_name_to_bottle "foo", HOMEBREW_CACHE/"hello--2.10"
-  # Formulary.factory "foo" # returns the hello formula from the bottle archive
+  # Map a formula name to a local/fetched bottle archive. This mapping will be used by {Formulary::factory}
+  # to allow formulae to be loaded automatically from their local bottle archive without
+  # needing to exist in a tap or be passed as a complete path. For example,
+  # to map `hello` from its bottle archive:
+  # 
Formulary.map_formula_name_to_local_bottle_path "hello", HOMEBREW_CACHE/"hello--2.10"
+  # Formulary.factory "hello" # returns the hello formula from the local bottle archive
   # 
- # @param name the string to map. - # @param bottle a path pointing to the target bottle archive. - def self.map_name_to_bottle(name, bottle) - @name_mappings ||= {} - @name_mappings[name] = Pathname(bottle).realpath + # @param formula_name the formula name string to map. + # @param local_bottle_path a path pointing to the target bottle archive. + def self.map_formula_name_to_local_bottle_path(formula_name, local_bottle_path) + if ENV["HOMEBREW_BOTTLE_JSON"].blank? + raise UsageError, "HOMEBREW_BOTTLE_JSON not set but required for #{__method__}!" + end + + @formula_name_local_bottle_path_map ||= {} + @formula_name_local_bottle_path_map[formula_name] = Pathname(local_bottle_path).realpath end # Return a {Formula} instance for the given rack. diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb index e9f750a4b9..c98916820a 100644 --- a/Library/Homebrew/test/formulary_spec.rb +++ b/Library/Homebrew/test/formulary_spec.rb @@ -205,7 +205,7 @@ describe Formulary do end end - describe "::map_name_to_bottle" do + describe "::map_formula_name_to_local_bottle_path" do before do formula_path.dirname.mkpath formula_path.write formula_content @@ -216,7 +216,13 @@ describe Formulary do described_class.factory("formula-to-map") }.to raise_error(FormulaUnavailableError) - described_class.map_name_to_bottle "formula-to-map", formula_path + ENV["HOMEBREW_BOTTLE_JSON"] = nil + expect { + described_class.map_formula_name_to_local_bottle_path "formula-to-map", formula_path + }.to raise_error(UsageError, /HOMEBREW_BOTTLE_JSON not set/) + + ENV["HOMEBREW_BOTTLE_JSON"] = "1" + described_class.map_formula_name_to_local_bottle_path "formula-to-map", formula_path expect(described_class.factory("formula-to-map")).to be_kind_of(Formula) end