/tools/Ruby/lib/ruby/site_ruby/1.8/rubygems/dependency.rb

http://github.com/agross/netopenspace · Ruby · 210 lines · 108 code · 53 blank · 49 comment · 23 complexity · fc4dae144ce92a0eef916df60032a3f3 MD5 · raw file

  1. require "rubygems/requirement"
  2. ##
  3. # The Dependency class holds a Gem name and a Gem::Requirement.
  4. class Gem::Dependency
  5. ##
  6. # Valid dependency types.
  7. #--
  8. # When this list is updated, be sure to change
  9. # Gem::Specification::CURRENT_SPECIFICATION_VERSION as well.
  10. TYPES = [
  11. :development,
  12. :runtime,
  13. ]
  14. ##
  15. # Dependency name or regular expression.
  16. attr_accessor :name
  17. ##
  18. # Allows you to force this dependency to be a prerelease.
  19. attr_writer :prerelease
  20. ##
  21. # Constructs a dependency with +name+ and +requirements+. The last
  22. # argument can optionally be the dependency type, which defaults to
  23. # <tt>:runtime</tt>.
  24. def initialize name, *requirements
  25. type = Symbol === requirements.last ? requirements.pop : :runtime
  26. requirements = requirements.first if 1 == requirements.length # unpack
  27. unless TYPES.include? type
  28. raise ArgumentError, "Valid types are #{TYPES.inspect}, "
  29. + "not #{type.inspect}"
  30. end
  31. @name = name
  32. @requirement = Gem::Requirement.create requirements
  33. @type = type
  34. @prerelease = false
  35. # This is for Marshal backwards compatibility. See the comments in
  36. # +requirement+ for the dirty details.
  37. @version_requirements = @requirement
  38. end
  39. ##
  40. # A dependency's hash is the XOR of the hashes of +name+, +type+,
  41. # and +requirement+.
  42. def hash # :nodoc:
  43. name.hash ^ type.hash ^ requirement.hash
  44. end
  45. def inspect # :nodoc:
  46. "<%s type=%p name=%p requirements=%p>" %
  47. [self.class, self.type, self.name, requirement.to_s]
  48. end
  49. ##
  50. # Does this dependency require a prerelease?
  51. def prerelease?
  52. @prerelease || requirement.prerelease?
  53. end
  54. def pretty_print q # :nodoc:
  55. q.group 1, 'Gem::Dependency.new(', ')' do
  56. q.pp name
  57. q.text ','
  58. q.breakable
  59. q.pp requirement
  60. q.text ','
  61. q.breakable
  62. q.pp type
  63. end
  64. end
  65. ##
  66. # What does this dependency require?
  67. def requirement
  68. return @requirement if defined?(@requirement) and @requirement
  69. # @version_requirements and @version_requirement are legacy ivar
  70. # names, and supported here because older gems need to keep
  71. # working and Dependency doesn't implement marshal_dump and
  72. # marshal_load. In a happier world, this would be an
  73. # attr_accessor. The horrifying instance_variable_get you see
  74. # below is also the legacy of some old restructurings.
  75. #
  76. # Note also that because of backwards compatibility (loading new
  77. # gems in an old RubyGems installation), we can't add explicit
  78. # marshaling to this class until we want to make a big
  79. # break. Maybe 2.0.
  80. #
  81. # Children, define explicit marshal and unmarshal behavior for
  82. # public classes. Marshal formats are part of your public API.
  83. if defined?(@version_requirement) && @version_requirement
  84. version = @version_requirement.instance_variable_get :@version
  85. @version_requirement = nil
  86. @version_requirements = Gem::Requirement.new version
  87. end
  88. @requirement = @version_requirements if defined?(@version_requirements)
  89. end
  90. def requirements_list
  91. requirement.as_list
  92. end
  93. def to_s # :nodoc:
  94. if type != :runtime then
  95. "#{name} (#{requirement}, #{type})"
  96. else
  97. "#{name} (#{requirement})"
  98. end
  99. end
  100. ##
  101. # Dependency type.
  102. def type
  103. @type ||= :runtime
  104. end
  105. def == other # :nodoc:
  106. Gem::Dependency === other &&
  107. self.name == other.name &&
  108. self.type == other.type &&
  109. self.requirement == other.requirement
  110. end
  111. ##
  112. # Dependencies are ordered by name.
  113. def <=> other
  114. self.name <=> other.name
  115. end
  116. ##
  117. # Uses this dependency as a pattern to compare to +other+. This
  118. # dependency will match if the name matches the other's name, and
  119. # other has only an equal version requirement that satisfies this
  120. # dependency.
  121. def =~ other
  122. unless Gem::Dependency === other
  123. return unless other.respond_to?(:name) && other.respond_to?(:version)
  124. other = Gem::Dependency.new other.name, other.version
  125. end
  126. return false unless name === other.name
  127. reqs = other.requirement.requirements
  128. return false unless reqs.length == 1
  129. return false unless reqs.first.first == '='
  130. version = reqs.first.last
  131. requirement.satisfied_by? version
  132. end
  133. def match? name, version
  134. return false unless self.name === name
  135. return true if requirement.none?
  136. requirement.satisfied_by? Gem::Version.new(version)
  137. end
  138. def matches_spec? spec
  139. return false unless name === spec.name
  140. return true if requirement.none?
  141. requirement.satisfied_by?(spec.version)
  142. end
  143. ##
  144. # Merges the requirements of +other+ into this dependency
  145. def merge other
  146. unless name == other.name then
  147. raise ArgumentError,
  148. "#{self} and #{other} have different names"
  149. end
  150. default = Gem::Requirement.default
  151. self_req = self.requirement
  152. other_req = other.requirement
  153. return self.class.new name, self_req if other_req == default
  154. return self.class.new name, other_req if self_req == default
  155. self.class.new name, self_req.as_list.concat(other_req.as_list)
  156. end
  157. end