Class: SemanticPuppet::VersionRange
- Inherits:
-
Object
- Object
- SemanticPuppet::VersionRange
- Defined in:
- lib/semantic_puppet/version_range.rb
Overview
A Semantic Version Range.
Defined Under Namespace
Classes: AbstractRange, AllRange, ComparatorRange, EqRange, GtEqRange, GtRange, LtEqRange, LtRange, MinMaxRange
Constant Summary collapse
- UPPER_X =
'X'.freeze
- LOWER_X =
'x'.freeze
- STAR =
'*'.freeze
- NR =
'0|[1-9][0-9]*'.freeze
- XR =
'(x|X|\*|' + NR + ')'.freeze
- XR_NC =
'(?:x|X|\*|' + NR + ')'.freeze
- PART =
'(?:[0-9A-Za-z-]+)'.freeze
- PARTS =
PART + '(?:\.' + PART + ')*'.freeze
- QUALIFIER =
'(?:-(' + PARTS + '))?(?:\+(' + PARTS + '))?'.freeze
- QUALIFIER_NC =
'(?:-' + PARTS + ')?(?:\+' + PARTS + ')?'.freeze
- PARTIAL =
XR_NC + '(?:\.' + XR_NC + '(?:\.' + XR_NC + QUALIFIER_NC + ')?)?'.freeze
- SIMPLE =
The ~> isn't in the spec but allowed
'([<>=~^]|<=|>=|~>|~=)?(' + PARTIAL + ')'.freeze
- SIMPLE_EXPR =
/\A#{SIMPLE}\z/.freeze
- SIMPLE_WITH_EXTRA_WS =
'([<>=~^]|<=|>=)?\s+(' + PARTIAL + ')'.freeze
- SIMPLE_WITH_EXTRA_WS_EXPR =
/\A#{SIMPLE_WITH_EXTRA_WS}\z/.freeze
- HYPHEN =
'(' + PARTIAL + ')\s+-\s+(' + PARTIAL + ')'.freeze
- HYPHEN_EXPR =
/\A#{HYPHEN}\z/.freeze
- PARTIAL_EXPR =
/\A#{XR}(?:\.#{XR}(?:\.#{XR}#{QUALIFIER})?)?\z/.freeze
- LOGICAL_OR =
/\s*\|\|\s*/.freeze
- RANGE_SPLIT =
/\s+/.freeze
- EMPTY_RANGE =
A range that matches no versions
VersionRange.new([], nil).freeze
- ALL_RANGE =
VersionRange.new([AllRange::SINGLETON], '*')
Instance Attribute Summary collapse
-
#ranges ⇒ Object
readonly
private
Provides read access to the ranges.
Class Method Summary collapse
-
.parse(range_string) ⇒ VersionRange
Parses a version range string into a comparable VersionRange instance.
Instance Method Summary collapse
-
#begin ⇒ Version
Returns the version that denotes the beginning of this range.
-
#end ⇒ Version
Returns the version that denotes the end of this range.
- #eql?(range) ⇒ Boolean (also: #==)
-
#exclude_begin? ⇒ Boolean
Returns
true
if the beginning is excluded from the range. -
#exclude_end? ⇒ Boolean
Returns
true
if the end is excluded from the range. - #hash ⇒ Object
-
#include?(version) ⇒ Boolean
(also: #member?, #cover?, #===)
true
if the given version is included in the range. -
#initialize(ranges, string, exclude_end = false) ⇒ VersionRange
constructor
private
Creates a new version range.
-
#inspect ⇒ String
Returns a canonical string representation of this range, assembled from the internal matchers.
-
#intersection(other) ⇒ VersionRange
(also: #&)
Computes the intersection of a pair of ranges.
-
#to_s ⇒ String
Returns a string representation of this range.
Constructor Details
#initialize(from, to, exclude_end = false) ⇒ VersionRange #initialize(ranges, string) ⇒ VersionRange
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Creates a new version range
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/semantic_puppet/version_range.rb', line 224 def initialize(ranges, string, exclude_end = false) unless ranges.is_a?(Array) lb = GtEqRange.new(ranges) if exclude_end ub = LtRange.new(string) string = ">=#{string} <#{ranges}" else ub = LtEqRange.new(string) string = "#{string} - #{ranges}" end ranges = [MinMaxRange.create(lb, ub)] end ranges.compact! merge_happened = true while ranges.size > 1 && merge_happened # merge ranges if possible merge_happened = false result = [] until ranges.empty? unmerged = [] x = ranges.pop result << ranges.reduce(x) do |memo, y| merged = memo.merge(y) if merged.nil? unmerged << y else merge_happened = true memo = merged end memo end ranges = unmerged end ranges = result.reverse! end ranges = [LtRange::MATCH_NOTHING] if ranges.empty? @ranges = ranges @string = string.nil? ? ranges.join(' || ') : string end |
Instance Attribute Details
#ranges ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Provides read access to the ranges. For internal use only
210 211 212 |
# File 'lib/semantic_puppet/version_range.rb', line 210 def ranges @ranges end |
Class Method Details
.parse(range_string) ⇒ VersionRange
Parses a version range string into a comparable SemanticPuppet::VersionRange instance.
Currently parsed version range string may take any of the following: forms:
- Regular Semantic Version strings
- ex.
"1.0.0"
,"1.2.3-pre"
- ex.
- Partial Semantic Version strings
- ex.
"1.0.x"
,"1"
,"2.X"
,"3.*"
,
- ex.
- Inequalities
- ex.
"> 1.0.0"
,"<3.2.0"
,">=4.0.0"
- ex.
- Approximate Caret Versions
- ex.
"^1"
,"^3.2"
,"^4.1.0"
- ex.
- Approximate Tilde Versions
- ex.
"~1.0.0"
,"~ 3.2.0"
,"~4.0.0"
- ex.
- Inclusive Ranges
- ex.
"1.0.0 - 1.3.9"
- ex.
- Range Intersections
- ex.
">1.0.0 <=2.3.0"
- ex.
- Combined ranges
- ex,
">=1.0.0 <2.3.0 || >=2.5.0 <3.0.0"
- ex,
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 |
# File 'lib/semantic_puppet/version_range.rb', line 64 def self.parse(range_string) # Remove extra whitespace after operators. Such whitespace should not cause a split range_set = range_string.gsub(/([><=~^])(?:\s+|\s*v)/, '\1') ranges = range_set.split(LOGICAL_OR) return ALL_RANGE if ranges.empty? new(ranges.map do |range| if range =~ HYPHEN_EXPR MinMaxRange.create(GtEqRange.new(parse_version($1)), LtEqRange.new(parse_version($2))) else # Split on whitespace simples = range.split(RANGE_SPLIT).map do |simple| match_data = SIMPLE_EXPR.match(simple) raise ArgumentError, "Unparsable version range: \"#{range_string}\"" unless match_data operand = match_data[2] # Case based on operator case match_data[1] when '~', '~>', '~=' parse_tilde(operand) when '^' parse_caret(operand) when '>' parse_gt_version(operand) when '>=' GtEqRange.new(parse_version(operand)) when '<' LtRange.new(parse_version(operand)) when '<=' parse_lteq_version(operand) when '=' parse_xrange(operand) else parse_xrange(operand) end end simples.size == 1 ? simples[0] : MinMaxRange.create(*simples) end end.uniq, range_string).freeze end |
Instance Method Details
#begin ⇒ Version
Returns the version that denotes the beginning of this range.
Since this really is an OR between disparate ranges, it may have multiple beginnings. This method
returns nil
if that is the case.
282 283 284 |
# File 'lib/semantic_puppet/version_range.rb', line 282 def begin @ranges.size == 1 ? @ranges[0].begin : nil end |
#end ⇒ Version
Returns the version that denotes the end of this range.
Since this really is an OR between disparate ranges, it may have multiple ends. This method
returns nil
if that is the case.
293 294 295 |
# File 'lib/semantic_puppet/version_range.rb', line 293 def end @ranges.size == 1 ? @ranges[0].end : nil end |
#eql?(range) ⇒ Boolean Also known as: ==
266 267 268 |
# File 'lib/semantic_puppet/version_range.rb', line 266 def eql?(range) range.is_a?(VersionRange) && @ranges.eql?(range.ranges) end |
#exclude_begin? ⇒ Boolean
Returns true
if the beginning is excluded from the range.
Since this really is an OR between disparate ranges, it may have multiple beginnings. This method
returns nil
if that is the case.
304 305 306 |
# File 'lib/semantic_puppet/version_range.rb', line 304 def exclude_begin? @ranges.size == 1 ? @ranges[0].exclude_begin? : nil end |
#exclude_end? ⇒ Boolean
Returns true
if the end is excluded from the range.
Since this really is an OR between disparate ranges, it may have multiple ends. This method
returns nil
if that is the case.
315 316 317 |
# File 'lib/semantic_puppet/version_range.rb', line 315 def exclude_end? @ranges.size == 1 ? @ranges[0].exclude_end? : nil end |
#hash ⇒ Object
271 272 273 |
# File 'lib/semantic_puppet/version_range.rb', line 271 def hash @ranges.hash end |
#include?(version) ⇒ Boolean Also known as: member?, cover?, ===
Returns true
if the given version is included in the range.
321 322 323 |
# File 'lib/semantic_puppet/version_range.rb', line 321 def include?(version) @ranges.any? { |range| range.include?(version) && (version.stable? || range.test_prerelease?(version)) } end |
#inspect ⇒ String
Returns a canonical string representation of this range, assembled from the internal matchers.
357 358 359 |
# File 'lib/semantic_puppet/version_range.rb', line 357 def inspect @ranges.join(' || ') end |
#intersection(other) ⇒ VersionRange Also known as: &
Computes the intersection of a pair of ranges. If the ranges have no useful intersection, an empty range is returned.
334 335 336 337 338 339 340 |
# File 'lib/semantic_puppet/version_range.rb', line 334 def intersection(other) raise ArgumentError, "value must be a #{self.class.name}" unless other.is_a?(VersionRange) result = @ranges.map { |range| other.ranges.map { |o_range| range.intersection(o_range) } }.flatten result.compact! result.uniq! result.empty? ? EMPTY_RANGE : VersionRange.new(result, nil) end |
#to_s ⇒ String
Returns a string representation of this range. This will be the string that was used when the range was parsed.
348 349 350 |
# File 'lib/semantic_puppet/version_range.rb', line 348 def to_s @string end |