2015-06-02 20:51:16 -04:00
|
|
|
require "digest/md5"
|
2015-12-13 20:19:53 -08:00
|
|
|
require "tap"
|
2015-06-02 20:51:16 -04:00
|
|
|
|
2013-06-23 12:47:10 -07:00
|
|
|
# The Formulary is responsible for creating instances of Formula.
|
2016-05-22 21:29:22 +01:00
|
|
|
# It is not meant to be used directly from formulae.
|
2014-05-02 07:39:23 -07:00
|
|
|
|
2013-06-08 20:58:43 -07:00
|
|
|
class Formulary
|
2015-06-01 19:20:11 -04:00
|
|
|
FORMULAE = {}
|
2015-01-01 01:21:59 -05:00
|
|
|
|
2015-06-01 19:20:11 -04:00
|
|
|
def self.formula_class_defined?(path)
|
|
|
|
FORMULAE.key?(path)
|
2013-06-18 10:11:06 -07:00
|
|
|
end
|
2013-06-08 20:58:43 -07:00
|
|
|
|
2015-06-01 19:20:11 -04:00
|
|
|
def self.formula_class_get(path)
|
|
|
|
FORMULAE.fetch(path)
|
2013-06-18 10:11:06 -07:00
|
|
|
end
|
2013-06-08 20:58:43 -07:00
|
|
|
|
2015-09-02 16:12:26 +08:00
|
|
|
def self.load_formula(name, path, contents, namespace)
|
2016-05-28 15:54:05 +01:00
|
|
|
if ENV["HOMEBREW_DISABLE_LOAD_FORMULA"]
|
|
|
|
raise "Formula loading disabled by HOMEBREW_DISABLE_LOAD_FORMULA!"
|
|
|
|
end
|
|
|
|
|
2015-06-01 19:20:11 -04:00
|
|
|
mod = Module.new
|
2015-09-02 16:12:26 +08:00
|
|
|
const_set(namespace, mod)
|
2015-06-06 18:10:47 -04:00
|
|
|
mod.module_eval(contents, path)
|
2015-06-01 19:20:11 -04:00
|
|
|
class_name = class_s(name)
|
|
|
|
|
|
|
|
begin
|
2015-09-02 16:12:26 +08:00
|
|
|
mod.const_get(class_name)
|
2016-04-16 20:58:20 +02:00
|
|
|
rescue NameError => original_exception
|
|
|
|
class_list = mod.constants.
|
|
|
|
map { |const_name| mod.const_get(const_name) }.
|
|
|
|
select { |const| const.is_a?(Class) }
|
|
|
|
e = FormulaClassUnavailableError.new(name, path, class_name, class_list)
|
|
|
|
raise e, "", original_exception.backtrace
|
2015-06-01 19:20:11 -04:00
|
|
|
end
|
2013-12-09 21:10:32 -06:00
|
|
|
end
|
|
|
|
|
2015-09-02 16:12:26 +08:00
|
|
|
def self.load_formula_from_path(name, path)
|
|
|
|
contents = path.open("r") { |f| set_encoding(f).read }
|
|
|
|
namespace = "FormulaNamespace#{Digest::MD5.hexdigest(path.to_s)}"
|
|
|
|
klass = load_formula(name, path, contents, namespace)
|
|
|
|
FORMULAE[path] = klass
|
|
|
|
end
|
|
|
|
|
2015-06-06 18:10:47 -04:00
|
|
|
if IO.method_defined?(:set_encoding)
|
|
|
|
def self.set_encoding(io)
|
|
|
|
io.set_encoding(Encoding::UTF_8)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
def self.set_encoding(io)
|
|
|
|
io
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def self.class_s(name)
|
2014-04-03 22:40:40 -05:00
|
|
|
class_name = name.capitalize
|
|
|
|
class_name.gsub!(/[-_.\s]([a-zA-Z0-9])/) { $1.upcase }
|
2015-08-06 15:45:52 +08:00
|
|
|
class_name.tr!("+", "x")
|
2014-04-03 22:40:40 -05:00
|
|
|
class_name
|
2014-02-21 00:43:58 -05:00
|
|
|
end
|
|
|
|
|
2013-06-18 10:11:06 -07:00
|
|
|
# A FormulaLoader returns instances of formulae.
|
|
|
|
# Subclasses implement loaders for particular sources of formulae.
|
|
|
|
class FormulaLoader
|
|
|
|
# The formula's name
|
|
|
|
attr_reader :name
|
|
|
|
# The formula's ruby file's path or filename
|
|
|
|
attr_reader :path
|
2014-04-03 22:40:40 -05:00
|
|
|
|
|
|
|
def initialize(name, path)
|
|
|
|
@name = name
|
2014-04-06 00:31:07 -05:00
|
|
|
@path = path.resolved_path
|
2014-04-03 22:40:40 -05:00
|
|
|
end
|
2013-06-18 10:11:06 -07:00
|
|
|
|
|
|
|
# Gets the formula instance.
|
2014-06-19 21:35:46 -05:00
|
|
|
def get_formula(spec)
|
|
|
|
klass.new(name, path, spec)
|
2014-03-07 17:23:44 -06:00
|
|
|
end
|
2013-06-18 10:11:06 -07:00
|
|
|
|
|
|
|
def klass
|
2015-06-01 19:20:11 -04:00
|
|
|
load_file unless Formulary.formula_class_defined?(path)
|
|
|
|
Formulary.formula_class_get(path)
|
2013-06-18 10:11:06 -07:00
|
|
|
end
|
2014-12-29 14:53:22 -05:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def load_file
|
2016-06-01 09:45:49 +02:00
|
|
|
$stderr.puts "#{$0} (#{self.class.name}): loading #{path}" if ARGV.debug?
|
2014-12-31 11:13:45 -05:00
|
|
|
raise FormulaUnavailableError.new(name) unless path.file?
|
2015-09-02 16:12:26 +08:00
|
|
|
Formulary.load_formula_from_path(name, path)
|
2014-12-29 14:53:22 -05:00
|
|
|
end
|
2013-06-18 10:11:06 -07:00
|
|
|
end
|
2013-06-08 20:58:43 -07:00
|
|
|
|
2013-06-18 10:11:06 -07:00
|
|
|
# Loads formulae from bottles.
|
|
|
|
class BottleLoader < FormulaLoader
|
2015-08-03 13:09:07 +01:00
|
|
|
def initialize(bottle_name)
|
2013-06-18 10:11:06 -07:00
|
|
|
@bottle_filename = Pathname(bottle_name).realpath
|
2016-04-25 17:57:51 +01:00
|
|
|
name, full_name = Utils::Bottles.resolve_formula_names @bottle_filename
|
2015-05-27 22:49:18 +08:00
|
|
|
super name, Formulary.path(full_name)
|
2013-06-18 10:11:06 -07:00
|
|
|
end
|
2013-06-08 20:58:43 -07:00
|
|
|
|
2014-06-19 21:35:46 -05:00
|
|
|
def get_formula(spec)
|
2014-03-07 17:23:44 -06:00
|
|
|
formula = super
|
2013-09-25 18:51:30 -05:00
|
|
|
formula.local_bottle_path = @bottle_filename
|
2015-07-23 14:09:32 +08:00
|
|
|
formula_version = formula.pkg_version
|
2016-04-25 17:57:51 +01:00
|
|
|
bottle_version = Utils::Bottles.resolve_version(@bottle_filename)
|
2015-07-23 14:09:32 +08:00
|
|
|
unless formula_version == bottle_version
|
|
|
|
raise BottleVersionMismatchError.new(@bottle_filename, bottle_version, formula, formula_version)
|
|
|
|
end
|
2014-03-07 17:23:44 -06:00
|
|
|
formula
|
2013-06-18 10:11:06 -07:00
|
|
|
end
|
|
|
|
end
|
2013-06-08 20:58:43 -07:00
|
|
|
|
2014-04-05 22:03:34 -05:00
|
|
|
class AliasLoader < FormulaLoader
|
2015-08-03 13:09:07 +01:00
|
|
|
def initialize(alias_path)
|
2014-04-05 22:03:34 -05:00
|
|
|
path = alias_path.resolved_path
|
|
|
|
name = path.basename(".rb").to_s
|
|
|
|
super name, path
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-06-18 10:11:06 -07:00
|
|
|
# Loads formulae from disk using a path
|
|
|
|
class FromPathLoader < FormulaLoader
|
2015-08-03 13:09:07 +01:00
|
|
|
def initialize(path)
|
2014-04-03 22:40:40 -05:00
|
|
|
path = Pathname.new(path).expand_path
|
2014-04-05 22:03:34 -05:00
|
|
|
super path.basename(".rb").to_s, path
|
2013-06-18 10:11:06 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-06-23 12:47:10 -07:00
|
|
|
# Loads formulae from URLs
|
2013-06-18 10:11:06 -07:00
|
|
|
class FromUrlLoader < FormulaLoader
|
|
|
|
attr_reader :url
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def initialize(url)
|
2013-06-18 10:11:06 -07:00
|
|
|
@url = url
|
2014-04-10 18:58:09 -04:00
|
|
|
uri = URI(url)
|
|
|
|
formula = File.basename(uri.path, ".rb")
|
|
|
|
super formula, HOMEBREW_CACHE_FORMULA/File.basename(uri.path)
|
2013-06-18 10:11:06 -07:00
|
|
|
end
|
|
|
|
|
2014-12-29 14:53:22 -05:00
|
|
|
def load_file
|
|
|
|
HOMEBREW_CACHE_FORMULA.mkpath
|
|
|
|
FileUtils.rm_f(path)
|
|
|
|
curl url, "-o", path
|
2014-03-07 17:23:44 -06:00
|
|
|
super
|
2013-06-08 20:58:43 -07:00
|
|
|
end
|
2013-06-18 10:11:06 -07:00
|
|
|
end
|
2013-06-08 20:58:43 -07:00
|
|
|
|
2013-06-18 10:11:06 -07:00
|
|
|
# Loads tapped formulae.
|
|
|
|
class TapLoader < FormulaLoader
|
2015-07-14 21:33:29 +08:00
|
|
|
attr_reader :tap
|
2014-04-05 22:03:33 -05:00
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def initialize(tapped_name)
|
2014-04-05 22:03:33 -05:00
|
|
|
user, repo, name = tapped_name.split("/", 3).map(&:downcase)
|
2015-12-02 14:35:42 +08:00
|
|
|
@tap = Tap.fetch user, repo
|
2016-02-24 20:06:33 +08:00
|
|
|
formula_dir = @tap.formula_dir || @tap.path
|
|
|
|
path = formula_dir/"#{name}.rb"
|
2015-09-12 18:04:06 +08:00
|
|
|
|
2016-02-24 20:06:33 +08:00
|
|
|
unless path.file?
|
2015-12-06 21:44:18 +08:00
|
|
|
if (possible_alias = @tap.alias_dir/name).file?
|
2015-09-12 18:04:06 +08:00
|
|
|
path = possible_alias.resolved_path
|
|
|
|
name = path.basename(".rb").to_s
|
2016-02-24 20:06:33 +08:00
|
|
|
elsif (new_name = @tap.formula_renames[name]) &&
|
|
|
|
(new_path = formula_dir/"#{new_name}.rb").file?
|
|
|
|
path = new_path
|
|
|
|
name = new_name
|
2015-09-12 18:04:06 +08:00
|
|
|
end
|
|
|
|
end
|
2014-04-07 18:44:29 -05:00
|
|
|
|
2014-04-05 22:03:33 -05:00
|
|
|
super name, path
|
2013-06-08 20:58:43 -07:00
|
|
|
end
|
|
|
|
|
2014-06-19 21:35:46 -05:00
|
|
|
def get_formula(spec)
|
2014-03-07 17:23:44 -06:00
|
|
|
super
|
2014-12-29 15:23:01 -05:00
|
|
|
rescue FormulaUnavailableError => e
|
2015-07-14 21:33:29 +08:00
|
|
|
raise TapFormulaUnavailableError.new(tap, name), "", e.backtrace
|
2013-06-18 10:11:06 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-01-01 01:21:59 -05:00
|
|
|
class NullLoader < FormulaLoader
|
|
|
|
def initialize(name)
|
2015-05-08 18:59:08 +08:00
|
|
|
super name, Formulary.core_path(name)
|
2015-01-01 01:21:59 -05:00
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def get_formula(_spec)
|
2015-01-01 01:21:59 -05:00
|
|
|
raise FormulaUnavailableError.new(name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-09-02 16:25:46 +08:00
|
|
|
# Load formulae directly from their contents
|
|
|
|
class FormulaContentsLoader < FormulaLoader
|
|
|
|
# The formula's contents
|
|
|
|
attr_reader :contents
|
|
|
|
|
|
|
|
def initialize(name, path, contents)
|
|
|
|
@contents = contents
|
|
|
|
super name, path
|
|
|
|
end
|
|
|
|
|
|
|
|
def klass
|
2016-06-01 09:45:49 +02:00
|
|
|
$stderr.puts "#{$0} (#{self.class.name}): loading #{path}" if ARGV.debug?
|
2015-09-02 16:25:46 +08:00
|
|
|
namespace = "FormulaNamespace#{Digest::MD5.hexdigest(contents)}"
|
|
|
|
Formulary.load_formula(name, path, contents, namespace)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-06-18 10:11:06 -07:00
|
|
|
# Return a Formula instance for the given reference.
|
2013-06-23 12:47:10 -07:00
|
|
|
# `ref` is string containing:
|
|
|
|
# * a formula name
|
|
|
|
# * a formula pathname
|
|
|
|
# * a formula URL
|
|
|
|
# * a local bottle reference
|
2015-08-03 13:09:07 +01:00
|
|
|
def self.factory(ref, spec = :stable)
|
2014-06-19 21:35:46 -05:00
|
|
|
loader_for(ref).get_formula(spec)
|
2014-04-05 22:03:33 -05:00
|
|
|
end
|
|
|
|
|
2015-05-16 11:26:26 +08:00
|
|
|
# Return a Formula instance for the given rack.
|
2015-07-30 16:33:19 +08:00
|
|
|
# It will auto resolve formula's spec when requested spec is nil
|
2015-08-03 13:09:07 +01:00
|
|
|
def self.from_rack(rack, spec = nil)
|
2015-05-16 11:26:26 +08:00
|
|
|
kegs = rack.directory? ? rack.subdirs.map { |d| Keg.new(d) } : []
|
|
|
|
keg = kegs.detect(&:linked?) || kegs.detect(&:optlinked?) || kegs.max_by(&:version)
|
|
|
|
|
2016-07-15 17:45:21 +08:00
|
|
|
if keg
|
|
|
|
from_keg(keg, spec)
|
|
|
|
else
|
|
|
|
factory(rack.basename.to_s, spec || :stable)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Return a Formula instance for the given keg.
|
|
|
|
# It will auto resolve formula's spec when requested spec is nil
|
|
|
|
def self.from_keg(keg, spec = nil)
|
2015-07-30 16:33:19 +08:00
|
|
|
tab = Tab.for_keg(keg)
|
|
|
|
tap = tab.tap
|
|
|
|
spec ||= tab.spec
|
2015-05-16 11:26:26 +08:00
|
|
|
|
2016-07-15 15:03:58 +08:00
|
|
|
f = if tap.nil?
|
2016-07-15 19:59:35 +08:00
|
|
|
factory(keg.rack.basename.to_s, spec)
|
2015-05-16 11:26:26 +08:00
|
|
|
else
|
2015-10-09 15:27:59 +08:00
|
|
|
begin
|
2016-07-15 17:45:21 +08:00
|
|
|
factory("#{tap}/#{keg.rack.basename}", spec)
|
2015-10-09 15:27:59 +08:00
|
|
|
rescue FormulaUnavailableError
|
|
|
|
# formula may be migrated to different tap. Try to search in core and all taps.
|
2016-07-15 17:45:21 +08:00
|
|
|
factory(keg.rack.basename.to_s, spec)
|
2015-10-09 15:27:59 +08:00
|
|
|
end
|
2015-05-16 11:26:26 +08:00
|
|
|
end
|
2016-07-15 15:03:58 +08:00
|
|
|
f.build = tab
|
2016-08-06 11:22:12 +03:00
|
|
|
f.version.update_commit(keg.version.version.commit) if f.head? && keg.version.head?
|
2016-07-15 15:03:58 +08:00
|
|
|
f
|
2015-05-16 11:26:26 +08:00
|
|
|
end
|
|
|
|
|
2015-09-02 16:25:46 +08:00
|
|
|
# Return a Formula instance directly from contents
|
|
|
|
def self.from_contents(name, path, contents, spec = :stable)
|
|
|
|
FormulaContentsLoader.new(name, path, contents).get_formula(spec)
|
|
|
|
end
|
|
|
|
|
2015-08-09 14:56:01 +03:00
|
|
|
def self.to_rack(ref)
|
2015-08-10 21:35:59 +08:00
|
|
|
# First, check whether the rack with the given name exists.
|
|
|
|
if (rack = HOMEBREW_CELLAR/File.basename(ref, ".rb")).directory?
|
2015-08-15 16:12:42 +08:00
|
|
|
return rack.resolved_path
|
2015-08-09 14:56:01 +03:00
|
|
|
end
|
|
|
|
|
2015-08-10 21:35:59 +08:00
|
|
|
# Second, use canonical name to locate rack.
|
2015-08-15 16:12:42 +08:00
|
|
|
(HOMEBREW_CELLAR/canonical_name(ref)).resolved_path
|
2015-08-09 14:56:01 +03:00
|
|
|
end
|
|
|
|
|
2014-04-05 22:03:34 -05:00
|
|
|
def self.canonical_name(ref)
|
|
|
|
loader_for(ref).name
|
2015-05-15 19:41:31 +08:00
|
|
|
rescue TapFormulaAmbiguityError
|
|
|
|
# If there are multiple tap formulae with the name of ref,
|
|
|
|
# then ref is the canonical name
|
|
|
|
ref.downcase
|
2014-04-05 22:03:34 -05:00
|
|
|
end
|
|
|
|
|
2015-05-08 13:48:36 +08:00
|
|
|
def self.path(ref)
|
|
|
|
loader_for(ref).path
|
|
|
|
end
|
|
|
|
|
2014-04-05 22:03:33 -05:00
|
|
|
def self.loader_for(ref)
|
|
|
|
case ref
|
2015-09-02 20:21:43 +08:00
|
|
|
when %r{(https?|ftp|file)://}
|
2014-04-05 22:03:33 -05:00
|
|
|
return FromUrlLoader.new(ref)
|
|
|
|
when Pathname::BOTTLE_EXTNAME_RX
|
|
|
|
return BottleLoader.new(ref)
|
2014-04-05 22:03:33 -05:00
|
|
|
when HOMEBREW_TAP_FORMULA_REGEX
|
|
|
|
return TapLoader.new(ref)
|
2013-06-08 20:58:43 -07:00
|
|
|
end
|
|
|
|
|
2014-04-05 22:03:34 -05:00
|
|
|
if File.extname(ref) == ".rb"
|
2014-04-05 22:03:33 -05:00
|
|
|
return FromPathLoader.new(ref)
|
|
|
|
end
|
|
|
|
|
2015-05-08 18:59:08 +08:00
|
|
|
formula_with_that_name = core_path(ref)
|
2014-04-05 22:03:33 -05:00
|
|
|
if formula_with_that_name.file?
|
2015-01-01 01:21:59 -05:00
|
|
|
return FormulaLoader.new(ref, formula_with_that_name)
|
2014-04-05 22:03:33 -05:00
|
|
|
end
|
|
|
|
|
2016-03-07 18:04:25 +08:00
|
|
|
possible_alias = CoreTap.instance.alias_dir/ref
|
2014-04-05 22:03:33 -05:00
|
|
|
if possible_alias.file?
|
2014-04-05 22:03:34 -05:00
|
|
|
return AliasLoader.new(possible_alias)
|
2014-04-05 22:03:33 -05:00
|
|
|
end
|
|
|
|
|
2015-08-22 13:15:33 +08:00
|
|
|
possible_tap_formulae = tap_paths(ref)
|
2015-05-08 19:16:06 +08:00
|
|
|
if possible_tap_formulae.size > 1
|
|
|
|
raise TapFormulaAmbiguityError.new(ref, possible_tap_formulae)
|
|
|
|
elsif possible_tap_formulae.size == 1
|
2015-09-12 18:04:06 +08:00
|
|
|
path = possible_tap_formulae.first.resolved_path
|
|
|
|
name = path.basename(".rb").to_s
|
|
|
|
return FormulaLoader.new(name, path)
|
2015-05-08 19:16:06 +08:00
|
|
|
end
|
|
|
|
|
2016-03-07 18:04:25 +08:00
|
|
|
if newref = CoreTap.instance.formula_renames[ref]
|
2015-08-09 14:52:49 +03:00
|
|
|
formula_with_that_oldname = core_path(newref)
|
|
|
|
if formula_with_that_oldname.file?
|
|
|
|
return FormulaLoader.new(newref, formula_with_that_oldname)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
possible_tap_newname_formulae = []
|
|
|
|
Tap.each do |tap|
|
|
|
|
if newref = tap.formula_renames[ref]
|
|
|
|
possible_tap_newname_formulae << "#{tap.name}/#{newref}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if possible_tap_newname_formulae.size > 1
|
|
|
|
raise TapFormulaWithOldnameAmbiguityError.new(ref, possible_tap_newname_formulae)
|
|
|
|
elsif !possible_tap_newname_formulae.empty?
|
|
|
|
return TapLoader.new(possible_tap_newname_formulae.first)
|
|
|
|
end
|
|
|
|
|
2014-04-05 22:03:33 -05:00
|
|
|
possible_cached_formula = Pathname.new("#{HOMEBREW_CACHE_FORMULA}/#{ref}.rb")
|
|
|
|
if possible_cached_formula.file?
|
2015-01-01 01:21:59 -05:00
|
|
|
return FormulaLoader.new(ref, possible_cached_formula)
|
2014-04-05 22:03:33 -05:00
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
NullLoader.new(ref)
|
2013-06-08 20:58:43 -07:00
|
|
|
end
|
2015-05-08 18:59:08 +08:00
|
|
|
|
|
|
|
def self.core_path(name)
|
2016-03-07 18:04:25 +08:00
|
|
|
CoreTap.instance.formula_dir/"#{name.downcase}.rb"
|
2015-05-08 18:59:08 +08:00
|
|
|
end
|
2015-05-08 19:16:06 +08:00
|
|
|
|
2015-08-22 13:15:33 +08:00
|
|
|
def self.tap_paths(name, taps = Dir["#{HOMEBREW_LIBRARY}/Taps/*/*/"])
|
2015-05-08 19:16:06 +08:00
|
|
|
name = name.downcase
|
2015-08-09 22:43:01 +08:00
|
|
|
taps.map do |tap|
|
2015-06-12 13:26:46 +08:00
|
|
|
Pathname.glob([
|
|
|
|
"#{tap}Formula/#{name}.rb",
|
|
|
|
"#{tap}HomebrewFormula/#{name}.rb",
|
2015-09-12 18:04:06 +08:00
|
|
|
"#{tap}#{name}.rb",
|
|
|
|
"#{tap}Aliases/#{name}",
|
2015-06-12 13:26:46 +08:00
|
|
|
]).detect(&:file?)
|
|
|
|
end.compact
|
2015-05-08 19:16:06 +08:00
|
|
|
end
|
2015-08-09 22:43:01 +08:00
|
|
|
|
2015-08-22 13:15:33 +08:00
|
|
|
def self.find_with_priority(ref, spec = :stable)
|
2015-08-09 22:43:01 +08:00
|
|
|
possible_pinned_tap_formulae = tap_paths(ref, Dir["#{HOMEBREW_LIBRARY}/PinnedTaps/*/*/"]).map(&:realpath)
|
|
|
|
if possible_pinned_tap_formulae.size > 1
|
|
|
|
raise TapFormulaAmbiguityError.new(ref, possible_pinned_tap_formulae)
|
|
|
|
elsif possible_pinned_tap_formulae.size == 1
|
|
|
|
selected_formula = factory(possible_pinned_tap_formulae.first, spec)
|
|
|
|
if core_path(ref).file?
|
|
|
|
opoo <<-EOS.undent
|
|
|
|
#{ref} is provided by core, but is now shadowed by #{selected_formula.full_name}.
|
2016-03-06 14:50:33 +08:00
|
|
|
To refer to the core formula, use Homebrew/core/#{ref} instead.
|
2015-08-09 22:43:01 +08:00
|
|
|
EOS
|
|
|
|
end
|
|
|
|
selected_formula
|
|
|
|
else
|
|
|
|
factory(ref, spec)
|
|
|
|
end
|
|
|
|
end
|
2013-06-08 20:58:43 -07:00
|
|
|
end
|