PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Library/Homebrew/dependency_collector.rb

https://github.com/kmowery/homebrew
Ruby | 188 lines | 150 code | 22 blank | 16 comment | 13 complexity | acf70d0a63460be11859cf45c00fe8f3 MD5 | raw file
  1. require 'dependency'
  2. require 'dependencies'
  3. require 'requirement'
  4. require 'requirements'
  5. require 'requirements/ld64_dependency'
  6. require 'set'
  7. ## A dependency is a formula that another formula needs to install.
  8. ## A requirement is something other than a formula that another formula
  9. ## needs to be present. This includes external language modules,
  10. ## command-line tools in the path, or any arbitrary predicate.
  11. ##
  12. ## The `depends_on` method in the formula DSL is used to declare
  13. ## dependencies and requirements.
  14. # This class is used by `depends_on` in the formula DSL to turn dependency
  15. # specifications into the proper kinds of dependencies and requirements.
  16. class DependencyCollector
  17. # Define the languages that we can handle as external dependencies.
  18. LANGUAGE_MODULES = Set[
  19. :chicken, :jruby, :lua, :node, :ocaml, :perl, :python, :rbx, :ruby
  20. ].freeze
  21. CACHE = {}
  22. attr_reader :deps, :requirements
  23. def initialize
  24. @deps = Dependencies.new
  25. @requirements = ComparableSet.new
  26. end
  27. def add(spec)
  28. case dep = fetch(spec)
  29. when Dependency
  30. @deps << dep
  31. when Requirement
  32. @requirements << dep
  33. end
  34. dep
  35. end
  36. def fetch(spec)
  37. CACHE.fetch(cache_key(spec)) { |key| CACHE[key] = build(spec) }
  38. end
  39. def cache_key(spec)
  40. if Resource === spec && spec.download_strategy == CurlDownloadStrategy
  41. File.extname(spec.url)
  42. else
  43. spec
  44. end
  45. end
  46. def build(spec)
  47. spec, tags = case spec
  48. when Hash then destructure_spec_hash(spec)
  49. else spec
  50. end
  51. parse_spec(spec, Array(tags))
  52. end
  53. private
  54. def destructure_spec_hash(spec)
  55. spec.each { |o| return o }
  56. end
  57. def parse_spec(spec, tags)
  58. case spec
  59. when String
  60. parse_string_spec(spec, tags)
  61. when Resource
  62. resource_dep(spec, tags)
  63. when Symbol
  64. parse_symbol_spec(spec, tags)
  65. when Requirement, Dependency
  66. spec
  67. when Class
  68. parse_class_spec(spec, tags)
  69. else
  70. raise TypeError, "Unsupported type #{spec.class} for #{spec.inspect}"
  71. end
  72. end
  73. def parse_string_spec(spec, tags)
  74. if tags.empty?
  75. Dependency.new(spec, tags)
  76. elsif (tag = tags.first) && LANGUAGE_MODULES.include?(tag)
  77. LanguageModuleDependency.new(tag, spec, tags[1])
  78. elsif HOMEBREW_TAP_FORMULA_REGEX === spec
  79. TapDependency.new(spec, tags)
  80. else
  81. Dependency.new(spec, tags)
  82. end
  83. end
  84. def parse_symbol_spec(spec, tags)
  85. case spec
  86. when :autoconf, :automake, :bsdmake, :libtool, :libltdl
  87. # Xcode no longer provides autotools or some other build tools
  88. autotools_dep(spec, tags)
  89. when :x11 then X11Dependency.new(spec.to_s, tags)
  90. when :cairo, :fontconfig, :freetype, :libpng, :pixman
  91. # We no longer use X11 proxy deps, but we support the symbols
  92. # for backwards compatibility.
  93. Dependency.new(spec.to_s, tags)
  94. when :xcode then XcodeDependency.new(tags)
  95. when :macos then MinimumMacOSRequirement.new(tags)
  96. when :mysql then MysqlDependency.new(tags)
  97. when :postgresql then PostgresqlDependency.new(tags)
  98. when :fortran then FortranDependency.new(tags)
  99. when :mpi then MPIDependency.new(*tags)
  100. when :tex then TeXDependency.new(tags)
  101. when :arch then ArchRequirement.new(tags)
  102. when :hg then MercurialDependency.new(tags)
  103. # python2 is deprecated
  104. when :python, :python2 then PythonDependency.new(tags)
  105. when :python3 then Python3Dependency.new(tags)
  106. # Tiger's ld is too old to properly link some software
  107. when :ld64 then LD64Dependency.new if MacOS.version < :leopard
  108. when :ant then ant_dep(spec, tags)
  109. when :clt # deprecated
  110. else
  111. raise ArgumentError, "Unsupported special dependency #{spec.inspect}"
  112. end
  113. end
  114. def parse_class_spec(spec, tags)
  115. if spec < Requirement
  116. spec.new(tags)
  117. else
  118. raise TypeError, "#{spec.inspect} is not a Requirement subclass"
  119. end
  120. end
  121. def autotools_dep(spec, tags)
  122. if spec == :libltdl
  123. spec = :libtool
  124. tags << :run
  125. end
  126. tags << :build unless tags.include? :run
  127. Dependency.new(spec.to_s, tags)
  128. end
  129. def ant_dep(spec, tags)
  130. if MacOS.version >= :mavericks
  131. tags << :build
  132. Dependency.new(spec.to_s, tags)
  133. end
  134. end
  135. def resource_dep(spec, tags)
  136. tags << :build
  137. strategy = spec.download_strategy
  138. case
  139. when strategy <= CurlDownloadStrategy
  140. parse_url_spec(spec.url, tags)
  141. when strategy <= GitDownloadStrategy
  142. GitDependency.new(tags)
  143. when strategy <= MercurialDownloadStrategy
  144. MercurialDependency.new(tags)
  145. when strategy <= FossilDownloadStrategy
  146. Dependency.new("fossil", tags)
  147. when strategy <= BazaarDownloadStrategy
  148. Dependency.new("bazaar", tags)
  149. when strategy <= CVSDownloadStrategy
  150. Dependency.new("cvs", tags) if MacOS.version >= :mavericks || !MacOS::Xcode.provides_cvs?
  151. when strategy < AbstractDownloadStrategy
  152. # allow unknown strategies to pass through
  153. else
  154. raise TypeError,
  155. "#{strategy.inspect} is not an AbstractDownloadStrategy subclass"
  156. end
  157. end
  158. def parse_url_spec(url, tags)
  159. case File.extname(url)
  160. when '.xz' then Dependency.new('xz', tags)
  161. when '.lz' then Dependency.new('lzip', tags)
  162. when '.rar' then Dependency.new('unrar', tags)
  163. when '.7z' then Dependency.new('p7zip', tags)
  164. end
  165. end
  166. end