Class: Vers::Constraint

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

Overview

Represents a single version constraint (e.g., “>=1.2.3”, “!=2.0.0”)

A constraint consists of an operator and a version. This class handles parsing constraint strings and converting them to intervals.

Examples

constraint = Vers::Constraint.new(">=", "1.2.3")
constraint.operator  # => ">="
constraint.version   # => "1.2.3"
constraint.to_interval # => [1.2.3,+∞)

Constant Summary collapse

OPERATORS =

Valid constraint operators as defined in the vers spec

%w[= != < <= > >=].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(operator, version) ⇒ Constraint

Creates a new constraint with the given operator and version

Parameters:

  • operator (String)

    The constraint operator (=, !=, <, <=, >, >=)

  • version (String)

    The version string

Raises:

  • (ArgumentError)

    if operator is invalid



30
31
32
33
34
35
# File 'lib/vers/constraint.rb', line 30

def initialize(operator, version)
  raise ArgumentError, "Invalid operator: #{operator}" unless OPERATORS.include?(operator)
  
  @operator = operator
  @version = version
end

Instance Attribute Details

#operatorObject (readonly)

Returns the value of attribute operator.



21
22
23
# File 'lib/vers/constraint.rb', line 21

def operator
  @operator
end

#versionObject (readonly)

Returns the value of attribute version.



21
22
23
# File 'lib/vers/constraint.rb', line 21

def version
  @version
end

Class Method Details

.parse(constraint_string) ⇒ Constraint

Parses a constraint string into operator and version components

Examples

Vers::Constraint.parse(">=1.2.3")  # => #<Vers::Constraint:0x... @operator=">=", @version="1.2.3">
Vers::Constraint.parse("!=2.0.0")  # => #<Vers::Constraint:0x... @operator="!=", @version="2.0.0">

Parameters:

  • constraint_string (String)

    The constraint string to parse

Returns:

Raises:

  • (ArgumentError)

    if the constraint string is invalid



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

def self.parse(constraint_string)
  return new("=", constraint_string) unless constraint_string.match(/^[!<>=]/)
  
  if constraint_string.start_with?("!=")
    version = constraint_string[2..-1]
    raise ArgumentError, "Invalid constraint format: #{constraint_string}" if version.empty?
    new("!=", version)
  elsif constraint_string.start_with?(">=")
    version = constraint_string[2..-1]
    raise ArgumentError, "Invalid constraint format: #{constraint_string}" if version.empty?
    new(">=", version)
  elsif constraint_string.start_with?("<=")
    version = constraint_string[2..-1]
    raise ArgumentError, "Invalid constraint format: #{constraint_string}" if version.empty?
    new("<=", version)
  elsif constraint_string.start_with?(">")
    version = constraint_string[1..-1]
    raise ArgumentError, "Invalid constraint format: #{constraint_string}" if version.empty?
    new(">", version)
  elsif constraint_string.start_with?("<")
    version = constraint_string[1..-1]
    raise ArgumentError, "Invalid constraint format: #{constraint_string}" if version.empty?
    new("<", version)
  elsif constraint_string.start_with?("=")
    version = constraint_string[1..-1]
    raise ArgumentError, "Invalid constraint format: #{constraint_string}" if version.empty?
    new("=", version)
  else
    raise ArgumentError, "Invalid constraint format: #{constraint_string}"
  end
end

Instance Method Details

#==(other) ⇒ Object



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

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

#exclusion?Boolean

Returns true if this is an exclusion constraint (!=)

Returns:

  • (Boolean)


114
115
116
# File 'lib/vers/constraint.rb', line 114

def exclusion?
  operator == "!="
end

#hashObject



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

def hash
  [operator, version].hash
end

#satisfies?(version_string) ⇒ Boolean

Checks if a version satisfies this constraint

Parameters:

  • version_string (String)

    The version to check

Returns:

  • (Boolean)

    true if the version satisfies the constraint



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/vers/constraint.rb', line 124

def satisfies?(version_string)
  case operator
  when "="
    Version.compare(version_string, version) == 0
  when "!="
    Version.compare(version_string, version) != 0
  when ">"
    Version.compare(version_string, version) > 0
  when ">="
    Version.compare(version_string, version) >= 0
  when "<"
    Version.compare(version_string, version) < 0
  when "<="
    Version.compare(version_string, version) <= 0
  end
end

#to_intervalInterval

Converts this constraint to an interval representation

Examples

Vers::Constraint.new(">=", "1.2.3").to_interval  # => [1.2.3,+∞)
Vers::Constraint.new("=", "1.0.0").to_interval   # => [1.0.0,1.0.0]

Returns:

  • (Interval)

    The interval representation of this constraint



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/vers/constraint.rb', line 91

def to_interval
  case operator
  when "="
    Interval.exact(version)
  when "!="
    # != constraints need special handling in ranges - they create exclusions
    nil
  when ">"
    Interval.greater_than(version, inclusive: false)
  when ">="
    Interval.greater_than(version, inclusive: true)
  when "<"
    Interval.less_than(version, inclusive: false)
  when "<="
    Interval.less_than(version, inclusive: true)
  end
end

#to_sString

String representation of this constraint

Returns:

  • (String)

    The constraint as a string



146
147
148
# File 'lib/vers/constraint.rb', line 146

def to_s
  "#{operator}#{version}"
end