| 
									
										
										
										
											2013-06-23 12:47:10 -07:00
										 |  |  | # The Formulary is responsible for creating instances of Formula. | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  | class Formulary | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-23 14:07:46 -07:00
										 |  |  |   def self.unload_formula formula_name | 
					
						
							| 
									
										
										
										
											2014-02-21 00:43:58 -05:00
										 |  |  |     Object.send(:remove_const, class_s(formula_name)) | 
					
						
							| 
									
										
										
										
											2013-06-23 14:07:46 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |   def self.formula_class_defined? formula_name | 
					
						
							| 
									
										
										
										
											2014-02-21 00:43:58 -05:00
										 |  |  |     Object.const_defined?(class_s(formula_name)) | 
					
						
							| 
									
										
										
										
											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
										 |  |  |   def self.get_formula_class formula_name | 
					
						
							| 
									
										
										
										
											2014-02-21 00:43:58 -05:00
										 |  |  |     Object.const_get(class_s(formula_name)) | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-09 21:10:32 -06:00
										 |  |  |   def self.restore_formula formula_name, value | 
					
						
							|  |  |  |     old_verbose, $VERBOSE = $VERBOSE, nil | 
					
						
							| 
									
										
										
										
											2014-02-21 00:43:58 -05:00
										 |  |  |     Object.const_set(class_s(formula_name), value) | 
					
						
							| 
									
										
										
										
											2013-12-09 21:10:32 -06:00
										 |  |  |   ensure | 
					
						
							|  |  |  |     $VERBOSE = old_verbose | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 00:43:58 -05:00
										 |  |  |   def self.class_s name | 
					
						
							| 
									
										
										
										
											2014-02-21 00:43:58 -05:00
										 |  |  |     (@class_s ||= {}).fetch(name) do | 
					
						
							|  |  |  |       class_name = name.capitalize | 
					
						
							|  |  |  |       class_name.gsub!(/[-_.\s]([a-zA-Z0-9])/) { $1.upcase } | 
					
						
							|  |  |  |       class_name.gsub!('+', 'x') | 
					
						
							|  |  |  |       @class_s[name] = class_name | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Gets the formula instance. | 
					
						
							| 
									
										
										
										
											2014-03-07 17:23:44 -06:00
										 |  |  |     def get_formula | 
					
						
							|  |  |  |       klass.new(name, path) | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Return the Class for this formula, `require`-ing it if | 
					
						
							|  |  |  |     # it has not been parsed before. | 
					
						
							|  |  |  |     def klass | 
					
						
							| 
									
										
										
										
											2013-06-30 10:26:12 -07:00
										 |  |  |       begin | 
					
						
							|  |  |  |         have_klass = Formulary.formula_class_defined? name | 
					
						
							|  |  |  |       rescue NameError | 
					
						
							|  |  |  |         raise FormulaUnavailableError.new(name) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       unless have_klass | 
					
						
							| 
									
										
										
										
											2014-03-07 17:33:02 -06:00
										 |  |  |         puts "#{$0} (#{self.class.name}): loading #{path}" if ARGV.debug? | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |         begin | 
					
						
							| 
									
										
										
										
											2014-02-19 16:53:18 -05:00
										 |  |  |           require path | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |         rescue NoMethodError | 
					
						
							|  |  |  |           # This is a programming error in an existing formula, and should not | 
					
						
							|  |  |  |           # have a "no such formula" message. | 
					
						
							|  |  |  |           raise | 
					
						
							|  |  |  |         rescue LoadError, NameError | 
					
						
							| 
									
										
										
										
											2013-08-04 20:38:26 -05:00
										 |  |  |           raise if ARGV.debug?  # let's see the REAL error | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |           raise FormulaUnavailableError.new(name) | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2013-06-30 10:26:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |       klass = Formulary.get_formula_class(name) | 
					
						
							| 
									
										
										
										
											2014-02-21 00:43:58 -05:00
										 |  |  |       if klass == Formula || !(klass < Formula) | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |         raise FormulaUnavailableError.new(name) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       klass | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |   # Loads formulae from bottles. | 
					
						
							|  |  |  |   class BottleLoader < FormulaLoader | 
					
						
							|  |  |  |     def initialize bottle_name | 
					
						
							|  |  |  |       @bottle_filename = Pathname(bottle_name).realpath | 
					
						
							| 
									
										
										
										
											2013-07-04 11:21:50 +01:00
										 |  |  |       name_without_version = bottle_filename_formula_name @bottle_filename | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  |       if name_without_version.empty? | 
					
						
							|  |  |  |         if ARGV.homebrew_developer? | 
					
						
							| 
									
										
										
										
											2013-08-04 08:25:51 -07:00
										 |  |  |           opoo "Add a new regex to bottle_version.rb to parse this filename." | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2013-07-04 11:20:59 +01:00
										 |  |  |         @name = bottle_name | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |         @name = name_without_version | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |       @path = Formula.path(@name) | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |     def get_formula | 
					
						
							| 
									
										
										
										
											2014-03-07 17:23:44 -06:00
										 |  |  |       formula = super | 
					
						
							| 
									
										
										
										
											2013-09-25 18:51:30 -05:00
										 |  |  |       formula.local_bottle_path = @bottle_filename | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |   # Loads formulae from Homebrew's provided Library | 
					
						
							|  |  |  |   class StandardLoader < FormulaLoader | 
					
						
							|  |  |  |     def initialize name | 
					
						
							|  |  |  |       @name = name | 
					
						
							|  |  |  |       @path = Formula.path(name) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Loads formulae from disk using a path | 
					
						
							|  |  |  |   class FromPathLoader < FormulaLoader | 
					
						
							|  |  |  |     def initialize path | 
					
						
							|  |  |  |       # require allows filenames to drop the .rb extension, but everything else | 
					
						
							|  |  |  |       # in our codebase will require an exact and fullpath. | 
					
						
							| 
									
										
										
										
											2013-06-30 14:36:12 -07:00
										 |  |  |       path = "#{path}.rb" unless path =~ /\.rb$/ | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-19 16:53:18 -05:00
										 |  |  |       @path = Pathname.new(path).expand_path | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |       @name = @path.stem | 
					
						
							|  |  |  |     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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def initialize url | 
					
						
							|  |  |  |       @url = url | 
					
						
							| 
									
										
										
										
											2013-06-23 12:47:10 -07:00
										 |  |  |       @path = HOMEBREW_CACHE_FORMULA/File.basename(url) | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |       @name = File.basename(url, '.rb') | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Downloads the formula's .rb file | 
					
						
							|  |  |  |     def fetch | 
					
						
							|  |  |  |       unless Formulary.formula_class_defined? name | 
					
						
							|  |  |  |         HOMEBREW_CACHE_FORMULA.mkpath | 
					
						
							|  |  |  |         FileUtils.rm path.to_s, :force => true | 
					
						
							|  |  |  |         curl url, '-o', path.to_s | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |     def get_formula | 
					
						
							| 
									
										
										
										
											2014-03-07 17:23:44 -06:00
										 |  |  |       fetch | 
					
						
							|  |  |  |       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 | 
					
						
							|  |  |  |     def initialize tapped_name | 
					
						
							|  |  |  |       @name = tapped_name | 
					
						
							|  |  |  |       @path = Pathname.new(tapped_name) | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |     def get_formula | 
					
						
							| 
									
										
										
										
											2014-03-07 17:23:44 -06:00
										 |  |  |       super | 
					
						
							| 
									
										
										
										
											2014-02-28 15:58:20 -06:00
										 |  |  |     rescue FormulaUnavailableError => e | 
					
						
							|  |  |  |       raise TapFormulaUnavailableError.new(e.name) | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # 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 | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |   def self.factory ref | 
					
						
							|  |  |  |     # If a URL is passed, download to the cache and install | 
					
						
							|  |  |  |     if ref =~ %r[(https?|ftp)://] | 
					
						
							|  |  |  |       f = FromUrlLoader.new(ref) | 
					
						
							|  |  |  |     elsif ref =~ Pathname::BOTTLE_EXTNAME_RX | 
					
						
							|  |  |  |       f = BottleLoader.new(ref) | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       name_or_path = Formula.canonical_name(ref) | 
					
						
							| 
									
										
										
										
											2014-02-28 15:58:20 -06:00
										 |  |  |       if name_or_path =~ HOMEBREW_TAP_FORMULA_REGEX | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |         # name appears to be a tapped formula, so we don't munge it | 
					
						
							|  |  |  |         # in order to provide a useful error message when require fails. | 
					
						
							|  |  |  |         f = TapLoader.new(name_or_path) | 
					
						
							|  |  |  |       elsif name_or_path.include? "/" | 
					
						
							|  |  |  |         # If name was a path or mapped to a cached formula | 
					
						
							|  |  |  |         f = FromPathLoader.new(name_or_path) | 
					
						
							| 
									
										
										
										
											2013-06-30 16:43:28 -07:00
										 |  |  |       elsif name_or_path =~ /\.rb$/ | 
					
						
							| 
									
										
										
										
											2014-02-28 16:27:25 -06:00
										 |  |  |         f = FromPathLoader.new(File.expand_path(name_or_path)) | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |       else | 
					
						
							|  |  |  |         f = StandardLoader.new(name_or_path) | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-18 10:11:06 -07:00
										 |  |  |     f.get_formula | 
					
						
							| 
									
										
										
										
											2013-06-08 20:58:43 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | end |