Module: Formulary Private
- Extended by:
- Cachable
- Defined in:
- Library/Homebrew/formulary.rb
Overview
Defined Under Namespace
Classes: AliasLoader, BottleLoader, FormulaContentsLoader, FormulaLoader, FromPathLoader, FromUrlLoader, NullLoader, TapLoader
Constant Summary collapse
- URL_START_REGEX =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
%r{(https?|ftp|file)://}.freeze
Class Method Summary collapse
- .canonical_name(ref) ⇒ Object private
- .class_s(name) ⇒ Object private
- .core_path(name) ⇒ Object private
- .enable_factory_cache! ⇒ Object private
- .ensure_utf8_encoding(io) ⇒ Object private
-
.factory(ref, spec = :stable, alias_path: nil, from: nil, force_bottle: false, flags: []) ⇒ Object
private
Return a Formula instance for the given reference.
- .factory_cached? ⇒ Boolean private
- .formula_class_defined?(path) ⇒ Boolean private
- .formula_class_get(path) ⇒ Object private
-
.from_contents(name, path, contents, spec = :stable, alias_path: nil, force_bottle: false, flags: []) ⇒ Object
private
Return a Formula instance directly from contents.
-
.from_keg(keg, spec = nil, alias_path: nil, force_bottle: false, flags: []) ⇒ Object
private
Return a Formula instance for the given keg.
-
.from_rack(rack, spec = nil, alias_path: nil, force_bottle: false, flags: []) ⇒ Object
private
Return a Formula instance for the given rack.
-
.keg_only?(rack) ⇒ Boolean
private
Return whether given rack is keg-only.
- .load_formula(name, path, contents, namespace, flags:) ⇒ Object private
- .load_formula_from_path(name, path, flags:) ⇒ Object private
- .loader_for(ref, from: nil) ⇒ Object private
- .path(ref) ⇒ Object private
- .resolve(name, spec: nil, force_bottle: false, flags: []) ⇒ Object private
- .tap_paths(name, taps = Dir[HOMEBREW_LIBRARY/"Taps/*/*/"]) ⇒ Object private
- .to_rack(ref) ⇒ Object private
Methods included from Cachable
Class Method Details
.canonical_name(ref) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
426 427 428 429 430 431 432 |
# File 'Library/Homebrew/formulary.rb', line 426 def self.canonical_name(ref) loader_for(ref).name rescue TapFormulaAmbiguityError # If there are multiple tap formulae with the name of ref, # then ref is the canonical name ref.downcase end |
.class_s(name) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
106 107 108 109 110 111 112 |
# File 'Library/Homebrew/formulary.rb', line 106 def self.class_s(name) class_name = name.capitalize class_name.gsub!(/[-_.\s]([a-zA-Z0-9])/) { Regexp.last_match(1).upcase } class_name.tr!("+", "x") class_name.sub!(/(.)@(\d)/, "\\1AT\\2") class_name end |
.core_path(name) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
492 493 494 |
# File 'Library/Homebrew/formulary.rb', line 492 def self.core_path(name) CoreTap.instance.formula_dir/"#{name.to_s.downcase}.rb" end |
.enable_factory_cache! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
17 18 19 |
# File 'Library/Homebrew/formulary.rb', line 17 def self.enable_factory_cache! @factory_cache = true end |
.ensure_utf8_encoding(io) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
102 103 104 |
# File 'Library/Homebrew/formulary.rb', line 102 def self.ensure_utf8_encoding(io) io.set_encoding(Encoding::UTF_8) end |
.factory(ref, spec = :stable, alias_path: nil, from: nil, force_bottle: false, flags: []) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return a Formula instance for the given reference.
ref
is a string containing:
- a formula name
- a formula pathname
- a formula URL
- a local bottle reference
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
# File 'Library/Homebrew/formulary.rb', line 337 def self.factory(ref, spec = :stable, alias_path: nil, from: nil, force_bottle: false, flags: []) raise ArgumentError, "Formulae must have a ref!" unless ref cache_key = "#{ref}-#{spec}-#{alias_path}-#{from}" if factory_cached? && cache[:formulary_factory] && cache[:formulary_factory][cache_key] return cache[:formulary_factory][cache_key] end formula = loader_for(ref, from: from).get_formula(spec, alias_path: alias_path, force_bottle: force_bottle, flags: flags) if factory_cached? cache[:formulary_factory] ||= {} cache[:formulary_factory][cache_key] ||= formula end formula end |
.factory_cached? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
21 22 23 |
# File 'Library/Homebrew/formulary.rb', line 21 def self.factory_cached? !@factory_cache.nil? end |
.formula_class_defined?(path) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
25 26 27 |
# File 'Library/Homebrew/formulary.rb', line 25 def self.formula_class_defined?(path) cache.key?(path) end |
.formula_class_get(path) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
29 30 31 |
# File 'Library/Homebrew/formulary.rb', line 29 def self.formula_class_get(path) cache.fetch(path) end |
.from_contents(name, path, contents, spec = :stable, alias_path: nil, force_bottle: false, flags: []) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return a Formula instance directly from contents.
408 409 410 411 |
# File 'Library/Homebrew/formulary.rb', line 408 def self.from_contents(name, path, contents, spec = :stable, alias_path: nil, force_bottle: false, flags: []) FormulaContentsLoader.new(name, path, contents) .get_formula(spec, alias_path: alias_path, force_bottle: force_bottle, flags: flags) end |
.from_keg(keg, spec = nil, alias_path: nil, force_bottle: false, flags: []) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return a Formula instance for the given keg.
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 |
# File 'Library/Homebrew/formulary.rb', line 383 def self.from_keg(keg, spec = nil, alias_path: nil, force_bottle: false, flags: []) tab = Tab.for_keg(keg) tap = tab.tap spec ||= tab.spec f = if tap.nil? factory(keg.rack.basename.to_s, spec, alias_path: alias_path, from: :keg, force_bottle: force_bottle, flags: flags) else begin factory("#{tap}/#{keg.rack.basename}", spec, alias_path: alias_path, from: :keg, force_bottle: force_bottle, flags: flags) rescue FormulaUnavailableError # formula may be migrated to different tap. Try to search in core and all taps. factory(keg.rack.basename.to_s, spec, alias_path: alias_path, from: :keg, force_bottle: force_bottle, flags: flags) end end f.build = tab f.build. = Tab.(f., tab.).as_flags f.version.update_commit(keg.version.version.commit) if f.head? && keg.version.head? f end |
.from_rack(rack, spec = nil, alias_path: nil, force_bottle: false, flags: []) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return a Formula instance for the given rack.
361 362 363 364 365 366 367 368 369 370 371 |
# File 'Library/Homebrew/formulary.rb', line 361 def self.from_rack(rack, spec = nil, alias_path: nil, force_bottle: false, flags: []) kegs = rack.directory? ? rack.subdirs.map { |d| Keg.new(d) } : [] keg = kegs.find(&:linked?) || kegs.find(&:optlinked?) || kegs.max_by(&:version) if keg from_keg(keg, spec, alias_path: alias_path) else factory(rack.basename.to_s, spec || :stable, alias_path: alias_path, from: :rack, force_bottle: force_bottle, flags: flags) end end |
.keg_only?(rack) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return whether given rack is keg-only.
374 375 376 377 378 |
# File 'Library/Homebrew/formulary.rb', line 374 def self.keg_only?(rack) Formulary.from_rack(rack).keg_only? rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError false end |
.load_formula(name, path, contents, namespace, flags:) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'Library/Homebrew/formulary.rb', line 33 def self.load_formula(name, path, contents, namespace, flags:) raise "Formula loading disabled by HOMEBREW_DISABLE_LOAD_FORMULA!" if Homebrew::EnvConfig.disable_load_formula? require "formula" mod = Module.new const_set(namespace, mod) begin # Set `BUILD_FLAGS` in the formula's namespace so we can # access them from within the formula's class scope. mod.const_set(:BUILD_FLAGS, flags) mod.module_eval(contents, path) rescue NameError, ArgumentError, ScriptError, MethodDeprecatedError => e $stderr.puts e.backtrace if Homebrew::EnvConfig.developer? raise FormulaUnreadableError.new(name, e) end class_name = class_s(name) begin mod.const_get(class_name) rescue NameError => e class_list = mod.constants .map { |const_name| mod.const_get(const_name) } .select { |const| const.is_a?(Class) } new_exception = FormulaClassUnavailableError.new(name, path, class_name, class_list) raise new_exception, "", e.backtrace end end |
.load_formula_from_path(name, path, flags:) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
63 64 65 66 67 68 |
# File 'Library/Homebrew/formulary.rb', line 63 def self.load_formula_from_path(name, path, flags:) contents = path.open("r") { |f| ensure_utf8_encoding(f).read } namespace = "FormulaNamespace#{Digest::MD5.hexdigest(path.to_s)}" klass = load_formula(name, path, contents, namespace, flags: flags) cache[path] = klass end |
.loader_for(ref, from: nil) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 |
# File 'Library/Homebrew/formulary.rb', line 438 def self.loader_for(ref, from: nil) case ref when Pathname::BOTTLE_EXTNAME_RX return BottleLoader.new(ref) when URL_START_REGEX return FromUrlLoader.new(ref) when HOMEBREW_TAP_FORMULA_REGEX return TapLoader.new(ref, from: from) end return FromPathLoader.new(ref) if File.extname(ref) == ".rb" && Pathname.new(ref)..exist? formula_with_that_name = core_path(ref) return FormulaLoader.new(ref, formula_with_that_name) if formula_with_that_name.file? possible_alias = CoreTap.instance.alias_dir/ref return AliasLoader.new(possible_alias) if possible_alias.file? possible_tap_formulae = tap_paths(ref) raise TapFormulaAmbiguityError.new(ref, possible_tap_formulae) if possible_tap_formulae.size > 1 if possible_tap_formulae.size == 1 path = possible_tap_formulae.first.resolved_path name = path.basename(".rb").to_s return FormulaLoader.new(name, path) end if newref = CoreTap.instance.formula_renames[ref] formula_with_that_oldname = core_path(newref) return FormulaLoader.new(newref, formula_with_that_oldname) if formula_with_that_oldname.file? 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) end return TapLoader.new(possible_tap_newname_formulae.first, from: from) unless possible_tap_newname_formulae.empty? possible_keg_formula = Pathname.new("#{HOMEBREW_PREFIX}/opt/#{ref}/.brew/#{ref}.rb") return FormulaLoader.new(ref, possible_keg_formula) if possible_keg_formula.file? possible_cached_formula = Pathname.new("#{HOMEBREW_CACHE_FORMULA}/#{ref}.rb") return FormulaLoader.new(ref, possible_cached_formula) if possible_cached_formula.file? NullLoader.new(ref) end |
.path(ref) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
434 435 436 |
# File 'Library/Homebrew/formulary.rb', line 434 def self.path(ref) loader_for(ref).path end |
.resolve(name, spec: nil, force_bottle: false, flags: []) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'Library/Homebrew/formulary.rb', line 70 def self.resolve(name, spec: nil, force_bottle: false, flags: []) if name.include?("/") || File.exist?(name) f = factory(name, *spec, force_bottle: force_bottle, flags: flags) if f.any_version_installed? tab = Tab.for_formula(f) resolved_spec = spec || tab.spec f.active_spec = resolved_spec if f.send(resolved_spec) f.build = tab if f.head? && tab.tabfile k = Keg.new(tab.tabfile.parent) f.version.update_commit(k.version.version.commit) if k.version.head? end end else rack = to_rack(name) alias_path = factory(name, force_bottle: force_bottle, flags: flags).alias_path f = from_rack(rack, *spec, alias_path: alias_path, force_bottle: force_bottle, flags: flags) end # If this formula was installed with an alias that has since changed, # then it was specified explicitly in ARGV. (Using the alias would # instead have found the new formula.) # # Because of this, the user is referring to this specific formula, # not any formula targeted by the same alias, so in this context # the formula shouldn't be considered outdated if the alias used to # install it has changed. f.follow_installed_alias = false f end |
.tap_paths(name, taps = Dir[HOMEBREW_LIBRARY/"Taps/*/*/"]) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
496 497 498 499 500 501 502 503 504 505 506 |
# File 'Library/Homebrew/formulary.rb', line 496 def self.tap_paths(name, taps = Dir[HOMEBREW_LIBRARY/"Taps/*/*/"]) name = name.to_s.downcase taps.map do |tap| Pathname.glob([ "#{tap}Formula/#{name}.rb", "#{tap}HomebrewFormula/#{name}.rb", "#{tap}#{name}.rb", "#{tap}Aliases/#{name}", ]).find(&:file?) end.compact end |
.to_rack(ref) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
413 414 415 416 417 418 419 420 421 422 423 424 |
# File 'Library/Homebrew/formulary.rb', line 413 def self.to_rack(ref) # If using a fully-scoped reference, check if the formula can be resolved. factory(ref) if ref.include? "/" # Check whether the rack with the given name exists. if (rack = HOMEBREW_CELLAR/File.basename(ref, ".rb")).directory? return rack.resolved_path end # Use canonical name to locate rack. (HOMEBREW_CELLAR/canonical_name(ref)).resolved_path end |