diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index f3fcc3ac1e..867d7237ee 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -395,6 +395,12 @@ module Formulary ) raise ArgumentError, "Formulae must have a ref!" unless 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] && cache[:formulary_factory][cache_key] @@ -411,6 +417,24 @@ module Formulary formula end + # 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 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. # # @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..c98916820a 100644 --- a/Library/Homebrew/test/formulary_spec.rb +++ b/Library/Homebrew/test/formulary_spec.rb @@ -205,6 +205,29 @@ describe Formulary do end end + describe "::map_formula_name_to_local_bottle_path" 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("formula-to-map") + }.to raise_error(FormulaUnavailableError) + + 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 + end + specify "::from_contents" do expect(described_class.from_contents(formula_name, formula_path, formula_content)).to be_kind_of(Formula) end