Class: Solve::Constraint

Inherits:
Object
  • Object
show all
Defined in:
lib/solve/constraint.rb

Constant Summary collapse

OPERATOR_TYPES =
{
  "~>" => :approx,
  "~"  => :approx,
  ">=" => :greater_than_equal,
  "<=" => :less_than_equal,
  "="  => :equal,
  ">"  => :greater_than,
  "<"  => :less_than,
}.freeze
COMPARE_FUNS =
{
  approx: method(:compare_approx),
  greater_than_equal: method(:compare_gte),
  greater_than: method(:compare_gt),
  less_than_equal: method(:compare_lte),
  less_than: method(:compare_lt),
  equal: method(:compare_equal)
}.freeze
REGEXP =
/^(#{OPERATOR_TYPES.keys.join('|')})\s?(.+)$/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(constraint = nil) ⇒ Constraint

Returns a new instance of Constraint.

Parameters:

  • constraint (#to_s) (defaults to: nil)

    (“>= 0.0.0”)



145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/solve/constraint.rb', line 145

def initialize(constraint = nil)
  if constraint.nil? || constraint.empty?
    constraint = ">= 0.0.0"
  end

  @operator, @major, @minor, @patch, @pre_release, @build = self.class.split(constraint)

  unless operator_type == :approx
    @minor ||= 0
    @patch ||= 0
  end
end

Instance Attribute Details

#buildObject (readonly)

Returns the value of attribute build.



142
143
144
# File 'lib/solve/constraint.rb', line 142

def build
  @build
end

#majorObject (readonly)

Returns the value of attribute major.



138
139
140
# File 'lib/solve/constraint.rb', line 138

def major
  @major
end

#minorObject (readonly)

Returns the value of attribute minor.



139
140
141
# File 'lib/solve/constraint.rb', line 139

def minor
  @minor
end

#operatorObject (readonly)

Returns the value of attribute operator.



137
138
139
# File 'lib/solve/constraint.rb', line 137

def operator
  @operator
end

#patchObject (readonly)

Returns the value of attribute patch.



140
141
142
# File 'lib/solve/constraint.rb', line 140

def patch
  @patch
end

#pre_releaseObject (readonly)

Returns the value of attribute pre_release.



141
142
143
# File 'lib/solve/constraint.rb', line 141

def pre_release
  @pre_release
end

Class Method Details

.compare_approx(constraint, target_version) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/solve/constraint.rb', line 97

def compare_approx(constraint, target_version)
  min = constraint.version
  max = if constraint.patch.nil?
    Version.new([min.major + 1, 0, 0, 0])
  elsif constraint.build
    identifiers = constraint.version.identifiers(:build)
    replace     = identifiers.last.to_i.to_s == identifiers.last.to_s ? "-" : nil
    Version.new([min.major, min.minor, min.patch, min.pre_release, identifiers.fill(replace, -1).join('.')])
  elsif constraint.pre_release
    identifiers = constraint.version.identifiers(:pre_release)
    replace     = identifiers.last.to_i.to_s == identifiers.last.to_s ? "-" : nil
    Version.new([min.major, min.minor, min.patch, identifiers.fill(replace, -1).join('.')])
  else
    Version.new([min.major, min.minor + 1, 0, 0])
  end
  min <= target_version && target_version < max
end

.compare_equal(constraint, target_version) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


57
58
59
# File 'lib/solve/constraint.rb', line 57

def compare_equal(constraint, target_version)
  target_version == constraint.version
end

.compare_gt(constraint, target_version) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


65
66
67
# File 'lib/solve/constraint.rb', line 65

def compare_gt(constraint, target_version)
  target_version > constraint.version
end

.compare_gte(constraint, target_version) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


81
82
83
# File 'lib/solve/constraint.rb', line 81

def compare_gte(constraint, target_version)
  target_version >= constraint.version
end

.compare_lt(constraint, target_version) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


73
74
75
# File 'lib/solve/constraint.rb', line 73

def compare_lt(constraint, target_version)
  target_version < constraint.version
end

.compare_lte(constraint, target_version) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


89
90
91
# File 'lib/solve/constraint.rb', line 89

def compare_lte(constraint, target_version)
  target_version <= constraint.version
end

.split(constraint) ⇒ Array?

Split a constraint string into an Array of two elements. The first element being the operator and second being the version string.

If the given string does not contain a constraint operator then (=) will be used.

If the given string does not contain a valid version string then nil will be returned.

Examples:

splitting a string with a constraint operator and valid version string

Constraint.split(">= 1.0.0") => [ ">=", "1.0.0" ]

splitting a string without a constraint operator

Constraint.split("0.0.0") => [ "=", "1.0.0" ]

splitting a string without a valid version string

Constraint.split("hello") => nil

Parameters:

  • constraint (#to_s)

Returns:

  • (Array, nil)


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
# File 'lib/solve/constraint.rb', line 25

def split(constraint)
  if constraint =~ /^[0-9]/
    operator = "="
    version  = constraint
  else
    _, operator, version = REGEXP.match(constraint).to_a
  end

  if operator.nil?
    raise Errors::InvalidConstraintFormat.new(constraint)
  end

  split_version = case version.to_s
  when /^(\d+)\.(\d+)\.(\d+)(-([0-9a-z\-\.]+))?(\+([0-9a-z\-\.]+))?$/i
    [ $1.to_i, $2.to_i, $3.to_i, $5, $7 ]
  when /^(\d+)\.(\d+)\.(\d+)?$/
    [ $1.to_i, $2.to_i, $3.to_i, nil, nil ]
  when /^(\d+)\.(\d+)?$/
    [ $1.to_i, $2.to_i, nil, nil, nil ]
  when /^(\d+)$/
    [ $1.to_i, nil, nil, nil, nil ]
  else
    raise Errors::InvalidConstraintFormat.new(constraint)
  end

  [ operator, split_version ].flatten
end

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Parameters:

  • other (Object)

Returns:

  • (Boolean)


202
203
204
205
206
# File 'lib/solve/constraint.rb', line 202

def ==(other)
  other.is_a?(self.class) &&
    self.operator == other.operator &&
    self.version == other.version
end

#operator_typeSymbol

Returns:

  • (Symbol)


175
176
177
178
179
180
181
# File 'lib/solve/constraint.rb', line 175

def operator_type
  unless type = OPERATOR_TYPES.fetch(operator)
    raise RuntimeError, "unknown operator type: #{operator}"
  end

  type
end

#satisfies?(target_version) ⇒ Boolean

Returns true or false if the given version would be satisfied by the version constraint.

Parameters:

  • target_version (#to_s)

Returns:

  • (Boolean)


189
190
191
192
193
194
195
196
197
# File 'lib/solve/constraint.rb', line 189

def satisfies?(target_version)
  target_version = Version.new(target_version.to_s)

  if target_version.pre_release? && !version.pre_release?
    return false
  end

  compare(target_version)
end

#to_sObject



209
210
211
212
213
214
215
216
# File 'lib/solve/constraint.rb', line 209

def to_s
  str = "#{operator} #{major}"
  str += ".#{minor}" if minor
  str += ".#{patch}" if patch
  str += "-#{pre_release}" if pre_release
  str += "+#{build}" if build
  str
end

#versionSolve::Version

Return the Solve::Version representation of the major, minor, and patch attributes of this instance

Returns:



162
163
164
165
166
167
168
169
170
171
172
# File 'lib/solve/constraint.rb', line 162

def version
  @version ||= Version.new(
    [
      self.major,
      self.minor,
      self.patch,
      self.pre_release,
      self.build
    ]
  )
end