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?(.+)$/.freeze

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)


164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/solve/constraint.rb', line 164

def initialize(constraint = nil)
  constraint = constraint.to_s
  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

  @version = Semverse::Version.new([
    major,
    minor,
    patch,
    pre_release,
    build,
  ])
end

Instance Attribute Details

#buildObject (readonly)

Returns the value of attribute build.



155
156
157
# File 'lib/solve/constraint.rb', line 155

def build
  @build
end

#majorObject (readonly)

Returns the value of attribute major.



151
152
153
# File 'lib/solve/constraint.rb', line 151

def major
  @major
end

#minorObject (readonly)

Returns the value of attribute minor.



152
153
154
# File 'lib/solve/constraint.rb', line 152

def minor
  @minor
end

#operatorObject (readonly)

Returns the value of attribute operator.



150
151
152
# File 'lib/solve/constraint.rb', line 150

def operator
  @operator
end

#patchObject (readonly)

Returns the value of attribute patch.



153
154
155
# File 'lib/solve/constraint.rb', line 153

def patch
  @patch
end

#pre_releaseObject (readonly)

Returns the value of attribute pre_release.



154
155
156
# File 'lib/solve/constraint.rb', line 154

def pre_release
  @pre_release
end

#versionSemverse::Version (readonly)

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

Returns:

  • (Semverse::Version)


161
162
163
# File 'lib/solve/constraint.rb', line 161

def version
  @version
end

Class Method Details

.coerce(object) ⇒ Constraint

Coerce the object into a constraint.

Parameters:

Returns:



9
10
11
12
13
14
15
# File 'lib/solve/constraint.rb', line 9

def coerce(object)
  if object.nil?
    Semverse::DEFAULT_CONSTRAINT
  else
    object.is_a?(self) ? object : new(object)
  end
end

.compare_approx(constraint, target_version) ⇒ Boolean

Parameters:

  • constraint (Semverse::Constraint)
  • target_version (Semverse::Version)

Returns:

  • (Boolean)


110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/solve/constraint.rb', line 110

def compare_approx(constraint, target_version)
  min = constraint.version
  max = if constraint.patch.nil?
          Semverse::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
          Semverse::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
          Semverse::Version.new([min.major, min.minor, min.patch, identifiers.fill(replace, -1).join(".")])
        else
          Semverse::Version.new([min.major, min.minor + 1, 0, 0])
        end
  min <= target_version && target_version < max
end

.compare_equal(constraint, target_version) ⇒ Boolean

Parameters:

  • constraint (Semverse::Constraint)
  • target_version (Semverse::Version)

Returns:

  • (Boolean)


70
71
72
# File 'lib/solve/constraint.rb', line 70

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

.compare_gt(constraint, target_version) ⇒ Boolean

Parameters:

  • constraint (Semverse::Constraint)
  • target_version (Semverse::Version)

Returns:

  • (Boolean)


78
79
80
# File 'lib/solve/constraint.rb', line 78

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

.compare_gte(constraint, target_version) ⇒ Boolean

Parameters:

  • constraint (Semverse::Constraint)
  • target_version (Semverse::Version)

Returns:

  • (Boolean)


94
95
96
# File 'lib/solve/constraint.rb', line 94

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

.compare_lt(constraint, target_version) ⇒ Boolean

Parameters:

  • constraint (Semverse::Constraint)
  • target_version (Semverse::Version)

Returns:

  • (Boolean)


86
87
88
# File 'lib/solve/constraint.rb', line 86

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

.compare_lte(constraint, target_version) ⇒ Boolean

Parameters:

  • constraint (Semverse::Constraint)
  • target_version (Semverse::Version)

Returns:

  • (Boolean)


102
103
104
# File 'lib/solve/constraint.rb', line 102

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)


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

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)


216
217
218
219
220
# File 'lib/solve/constraint.rb', line 216

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

#inspectObject



223
224
225
# File 'lib/solve/constraint.rb', line 223

def inspect
  "#<#{self.class} #{self}>"
end

#operator_typeSymbol

Returns:

  • (Symbol)


187
188
189
190
191
192
193
# File 'lib/solve/constraint.rb', line 187

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

  type
end

#satisfies?(target) ⇒ Boolean Also known as: include?

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

Parameters:

  • target (Semverse::Version, #to_s)

Returns:

  • (Boolean)


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

def satisfies?(target)
  target = Semverse::Version.coerce(target)

  return false if !(version == 0) && greedy_match?(target)

  compare(target)
end

#to_sObject



227
228
229
230
231
232
233
234
# File 'lib/solve/constraint.rb', line 227

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