summaryrefslogtreecommitdiff
path: root/lib/rubygems/dependency.rb
blob: d142265c5d636ecab7cb2c3af254268dc535b59c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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
62
63
64
65
66
67
68
69
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++

##
# The Dependency class holds a Gem name and a Gem::Requirement

class Gem::Dependency

  ##
  # Valid dependency types.
  #--
  # When this list is updated, be sure to change
  # Gem::Specification::CURRENT_SPECIFICATION_VERSION as well.

  TYPES = [
    :development,
    :runtime,
  ]

  ##
  # Dependency name or regular expression.

  attr_accessor :name

  ##
  # Dependency type.

  attr_reader :type

  ##
  # Dependent versions.

  attr_writer :version_requirements

  ##
  # Orders dependencies by name only.

  def <=>(other)
    [@name] <=> [other.name]
  end

  ##
  # Constructs a dependency with +name+ and +requirements+.

  def initialize(name, version_requirements, type=:runtime)
    @name = name

    unless TYPES.include? type
      raise ArgumentError, "Valid types are #{TYPES.inspect}, not #{@type.inspect}"
    end

    @type = type

    @version_requirements = Gem::Requirement.create version_requirements
    @version_requirement = nil   # Avoid warnings.
  end

  def version_requirements
    normalize if defined? @version_requirement and @version_requirement
    @version_requirements
  end

  def requirement_list
    version_requirements.as_list
  end

  alias requirements_list requirement_list

  def normalize
    ver = @version_requirement.instance_variable_get :@version
    @version_requirements = Gem::Requirement.new([ver])
    @version_requirement = nil
  end

  def to_s # :nodoc:
    "#{name} (#{version_requirements}, #{@type || :runtime})"
  end

  def pretty_print(q) # :nodoc:
    q.group 1, 'Gem::Dependency.new(', ')' do
      q.pp @name
      q.text ','
      q.breakable

      q.pp @version_requirements

      q.text ','
      q.breakable

      q.pp @type
    end
  end

  def ==(other) # :nodoc:
    self.class === other &&
      self.name == other.name &&
      self.type == other.type &&
      self.version_requirements == other.version_requirements
  end

  ##
  # Uses this dependency as a pattern to compare to +other+.  This dependency
  # will match if the name matches the other's name, and other has only an
  # equal version requirement that satisfies this dependency.

  def =~(other)
    other = if self.class === other then
              other
            else
              return false unless other.respond_to? :name and
                                  other.respond_to? :version

              Gem::Dependency.new other.name, other.version
            end

    pattern = @name
    pattern = /\A#{Regexp.escape @name}\Z/ unless Regexp === pattern

    return false unless pattern =~ other.name

    reqs = other.version_requirements.requirements

    return false unless reqs.length == 1
    return false unless reqs.first.first == '='

    version = reqs.first.last

    version_requirements.satisfied_by? version
  end

  ##
  # A dependency's hash is the sum of the hash of the #name, #type and
  # #version_requirements

  def hash
    name.hash + type.hash + version_requirements.hash
  end

  def inspect # :nodoc:
    "<%s type=%p name=%p requirements=%p>" % [self.class, @type, @name,
      version_requirements.to_s]
  end

end