| 
									
										
										
										
											2013-01-26 20:05:39 -06:00
										 |  |  | require 'dependable' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # A dependency on another Homebrew formula. | 
					
						
							|  |  |  | class Dependency | 
					
						
							|  |  |  |   include Dependable | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-27 14:22:43 -06:00
										 |  |  |   attr_reader :name, :tags, :env_proc, :option_name | 
					
						
							| 
									
										
										
										
											2013-01-26 20:05:39 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-27 14:22:43 -06:00
										 |  |  |   DEFAULT_ENV_PROC = proc {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def initialize(name, tags=[], env_proc=DEFAULT_ENV_PROC, option_name=name) | 
					
						
							|  |  |  |     @name = name | 
					
						
							| 
									
										
										
										
											2013-05-06 16:08:50 -05:00
										 |  |  |     @tags = tags | 
					
						
							| 
									
										
										
										
											2014-02-27 14:22:43 -06:00
										 |  |  |     @env_proc = env_proc | 
					
						
							|  |  |  |     @option_name = option_name | 
					
						
							| 
									
										
										
										
											2013-01-26 20:05:39 -06:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def to_s | 
					
						
							|  |  |  |     name | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def ==(other) | 
					
						
							| 
									
										
										
										
											2013-06-27 01:18:32 -05:00
										 |  |  |     instance_of?(other.class) && name == other.name | 
					
						
							| 
									
										
										
										
											2013-01-26 20:05:39 -06:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2013-11-05 16:02:26 -06:00
										 |  |  |   alias_method :eql?, :== | 
					
						
							| 
									
										
										
										
											2013-01-26 20:05:39 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def hash | 
					
						
							|  |  |  |     name.hash | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def to_formula | 
					
						
							| 
									
										
										
										
											2014-08-11 17:48:30 -05:00
										 |  |  |     formula = Formulary.factory(name) | 
					
						
							|  |  |  |     formula.build = BuildOptions.new(options, formula.options) | 
					
						
							|  |  |  |     formula | 
					
						
							| 
									
										
										
										
											2013-01-26 20:05:39 -06:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def installed? | 
					
						
							|  |  |  |     to_formula.installed? | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-27 14:22:43 -06:00
										 |  |  |   def satisfied?(inherited_options) | 
					
						
							|  |  |  |     installed? && missing_options(inherited_options).empty? | 
					
						
							| 
									
										
										
										
											2013-01-27 19:40:10 -06:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-23 22:41:35 -05:00
										 |  |  |   def missing_options(inherited_options) | 
					
						
							| 
									
										
										
										
											2014-08-27 23:28:00 -05:00
										 |  |  |     required = options | inherited_options | 
					
						
							|  |  |  |     required - Tab.for_formula(to_formula).used_options | 
					
						
							| 
									
										
										
										
											2013-01-27 19:40:10 -06:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-03 15:08:47 -05:00
										 |  |  |   def modify_build_environment | 
					
						
							|  |  |  |     env_proc.call unless env_proc.nil? | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-07 20:36:13 -05:00
										 |  |  |   def inspect | 
					
						
							| 
									
										
										
										
											2014-07-01 15:07:06 -05:00
										 |  |  |     "#<#{self.class.name}: #{name.inspect} #{tags.inspect}>" | 
					
						
							| 
									
										
										
										
											2013-06-07 20:36:13 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-27 23:23:22 -05:00
										 |  |  |   # Define marshaling semantics because we cannot serialize @env_proc | 
					
						
							|  |  |  |   def _dump(*) | 
					
						
							|  |  |  |     Marshal.dump([name, tags]) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def self._load(marshaled) | 
					
						
							|  |  |  |     new(*Marshal.load(marshaled)) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-10 23:45:05 -05:00
										 |  |  |   class << self | 
					
						
							|  |  |  |     # Expand the dependencies of dependent recursively, optionally yielding | 
					
						
							|  |  |  |     # [dependent, dep] pairs to allow callers to apply arbitrary filters to | 
					
						
							|  |  |  |     # the list. | 
					
						
							|  |  |  |     # The default filter, which is applied when a block is not given, omits | 
					
						
							|  |  |  |     # optionals and recommendeds based on what the dependent has asked for. | 
					
						
							| 
									
										
										
										
											2013-12-09 14:36:10 -06:00
										 |  |  |     def expand(dependent, deps=dependent.deps, &block) | 
					
						
							| 
									
										
										
										
											2014-02-13 15:38:39 -05:00
										 |  |  |       expanded_deps = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       deps.each do |dep| | 
					
						
							| 
									
										
										
										
											2014-02-27 14:22:42 -06:00
										 |  |  |         # FIXME don't hide cyclic dependencies | 
					
						
							|  |  |  |         next if dependent.name == dep.name | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-22 21:36:11 -05:00
										 |  |  |         case action(dependent, dep, &block) | 
					
						
							|  |  |  |         when :prune | 
					
						
							| 
									
										
										
										
											2014-02-13 15:38:39 -05:00
										 |  |  |           next | 
					
						
							| 
									
										
										
										
											2013-07-22 21:36:11 -05:00
										 |  |  |         when :skip | 
					
						
							| 
									
										
										
										
											2014-02-13 15:38:39 -05:00
										 |  |  |           expanded_deps.concat(expand(dep.to_formula, &block)) | 
					
						
							| 
									
										
										
										
											2013-11-13 10:38:14 -06:00
										 |  |  |         when :keep_but_prune_recursive_deps | 
					
						
							| 
									
										
										
										
											2014-02-13 15:38:39 -05:00
										 |  |  |           expanded_deps << dep | 
					
						
							| 
									
										
										
										
											2013-05-10 23:45:05 -05:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2014-02-13 15:38:39 -05:00
										 |  |  |           expanded_deps.concat(expand(dep.to_formula, &block)) | 
					
						
							|  |  |  |           expanded_deps << dep | 
					
						
							| 
									
										
										
										
											2013-05-10 23:45:05 -05:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2014-02-13 15:38:39 -05:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2013-06-07 22:27:30 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-09 14:36:10 -06:00
										 |  |  |       merge_repeats(expanded_deps) | 
					
						
							| 
									
										
										
										
											2013-05-10 23:45:05 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-22 21:36:11 -05:00
										 |  |  |     def action(dependent, dep, &block) | 
					
						
							|  |  |  |       catch(:action) do | 
					
						
							| 
									
										
										
										
											2013-01-26 20:05:39 -06:00
										 |  |  |         if block_given? | 
					
						
							|  |  |  |           yield dependent, dep | 
					
						
							|  |  |  |         elsif dep.optional? || dep.recommended? | 
					
						
							| 
									
										
										
										
											2013-12-09 14:36:10 -06:00
										 |  |  |           prune unless dependent.build.with?(dep) | 
					
						
							| 
									
										
										
										
											2013-01-26 20:05:39 -06:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2013-05-10 23:45:05 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-01-26 20:05:39 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-22 21:48:53 -05:00
										 |  |  |     # Prune a dependency and its dependencies recursively | 
					
						
							| 
									
										
										
										
											2013-05-10 23:45:05 -05:00
										 |  |  |     def prune | 
					
						
							| 
									
										
										
										
											2013-07-22 21:36:11 -05:00
										 |  |  |       throw(:action, :prune) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-22 21:48:53 -05:00
										 |  |  |     # Prune a single dependency but do not prune its dependencies | 
					
						
							| 
									
										
										
										
											2013-07-22 21:36:11 -05:00
										 |  |  |     def skip | 
					
						
							|  |  |  |       throw(:action, :skip) | 
					
						
							| 
									
										
										
										
											2013-05-10 23:45:05 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-06-07 22:27:30 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-13 10:38:14 -06:00
										 |  |  |     # Keep a dependency, but prune its dependencies | 
					
						
							|  |  |  |     def keep_but_prune_recursive_deps | 
					
						
							|  |  |  |       throw(:action, :keep_but_prune_recursive_deps) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-07 22:27:30 -05:00
										 |  |  |     def merge_repeats(deps) | 
					
						
							|  |  |  |       grouped = deps.group_by(&:name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       deps.uniq.map do |dep| | 
					
						
							| 
									
										
										
										
											2013-06-25 10:12:14 -05:00
										 |  |  |         tags = grouped.fetch(dep.name).map(&:tags).flatten.uniq | 
					
						
							| 
									
										
										
										
											2014-02-27 14:22:43 -06:00
										 |  |  |         dep.class.new(dep.name, tags, dep.env_proc) | 
					
						
							| 
									
										
										
										
											2013-06-07 22:27:30 -05:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-01-26 20:05:39 -06:00
										 |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							| 
									
										
										
										
											2014-02-28 11:16:55 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | class TapDependency < Dependency | 
					
						
							|  |  |  |   def initialize(name, tags=[], env_proc=DEFAULT_ENV_PROC, option_name=name) | 
					
						
							|  |  |  |     super(name, tags, env_proc, name.split("/").last) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def installed? | 
					
						
							|  |  |  |     super | 
					
						
							|  |  |  |   rescue FormulaUnavailableError | 
					
						
							|  |  |  |     false | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |