Class: Gem::Version

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/rubygems/version.rb,
lib/rubygems/requirement.rb

Constant Summary collapse

VERSION_PATTERN =

:nodoc:

'[0-9]+(?>\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?'
ANCHORED_VERSION_PATTERN =

:nodoc:

/\A\s*(#{VERSION_PATTERN})?\s*\z/
RADIX_OPT =

:nodoc:

[9_500, 3_500, 260_000, 22_227, 24].freeze
Requirement =

This is needed for compatibility with older yaml gemspecs.

Gem::Requirement
@@all =
{}
@@bump =
{}
@@release =
{}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(version) ⇒ Version

Constructs a Version from the version string. A version string is a series of digits or ASCII letters separated by dots.



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/rubygems/version.rb', line 208

def initialize(version)
  unless self.class.correct?(version)
    raise ArgumentError, "Malformed version number string #{version}"
  end

  # If version is an empty string convert it to 0
  version = 0 if version.nil? || (version.is_a?(String) && /\A\s*\Z/.match?(version))

  @version = version.to_s

  # optimization to avoid allocation when given an integer, since we know
  # it's to_s won't have any spaces or dashes
  unless version.is_a?(Integer)
    @version = @version.strip
    @version.gsub!("-",".pre.")
  end
  @version = -@version
  @segments = nil
  @sort_key = compute_sort_key
end

Class Method Details

.correct?(version) ⇒ Boolean

True if the version string matches RubyGems’ requirements.

Returns:

  • (Boolean)


175
176
177
# File 'lib/rubygems/version.rb', line 175

def self.correct?(version)
  version.nil? || ANCHORED_VERSION_PATTERN.match?(version.to_s)
end

.create(input) ⇒ Object

Factory method to create a Version object. Input may be a Version or a String. Intended to simplify client code.

ver1 = Version.create('1.3.17')   # -> (Version object)
ver2 = Version.create(ver1)       # -> (ver1)


186
187
188
189
190
191
192
# File 'lib/rubygems/version.rb', line 186

def self.create(input)
  if self === input # check yourself before you wreck yourself
    input
  else
    new input
  end
end

.new(version) ⇒ Object

:nodoc:



198
199
200
201
202
# File 'lib/rubygems/version.rb', line 198

def self.new(version) # :nodoc:
  return super unless self == Gem::Version

  @@all[version] ||= super
end

Instance Method Details

#<=>(other) ⇒ Object

Compares this version with other returning -1, 0, or 1 if the other version is larger, the same, or smaller than this one. other must be an instance of Gem::Version, comparing with other types may raise an exception.



348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'lib/rubygems/version.rb', line 348

def <=>(other)
  if Gem::Version === other
    # Fast path for comparison when available.
    if @sort_key && other.sort_key
      return @sort_key <=> other.sort_key
    end

    return 0 if @version == other.version || canonical_segments == other.canonical_segments

    lhsegments = canonical_segments
    rhsegments = other.canonical_segments

    lhsize = lhsegments.size
    rhsize = rhsegments.size
    limit  = (lhsize > rhsize ? rhsize : lhsize)

    i = 0

    while i < limit
      lhs = lhsegments[i]
      rhs = rhsegments[i]
      i += 1

      next      if lhs == rhs
      return -1 if String  === lhs && Numeric === rhs
      return  1 if Numeric === lhs && String  === rhs

      return lhs <=> rhs
    end

    lhs = lhsegments[i]

    if lhs.nil?
      rhs = rhsegments[i]

      while i < rhsize
        return 1 if String === rhs
        return -1 unless rhs.zero?
        rhs = rhsegments[i += 1]
      end
    else
      while i < lhsize
        return -1 if String === lhs
        return 1 unless lhs.zero?
        lhs = lhsegments[i += 1]
      end
    end

    0
  elsif String === other
    return unless self.class.correct?(other)
    self <=> self.class.new(other)
  end
end

#approximate_recommendationObject

A recommended version for use with a ~> Requirement.



330
331
332
333
334
335
336
337
338
339
340
# File 'lib/rubygems/version.rb', line 330

def approximate_recommendation
  segments = self.segments

  segments.pop    while segments.any? {|s| String === s }
  segments.pop    while segments.size > 2
  segments.push 0 while segments.size < 2

  recommendation = "~> #{segments.join(".")}"
  recommendation += ".a" if prerelease?
  recommendation
end

#bumpObject

Return a new version object where the next to the last revision number is one greater (e.g., 5.3.1 => 5.4).

Pre-release (alpha) parts, e.g, 5.3.1.b.2 => 5.4, are ignored.



235
236
237
238
239
240
241
242
243
244
# File 'lib/rubygems/version.rb', line 235

def bump
  @@bump[self] ||= begin
                     segments = self.segments
                     segments.pop while segments.any? {|s| String === s }
                     segments.pop if segments.size > 1

                     segments[-1] = segments[-1].succ
                     self.class.new segments.join(".")
                   end
end

#canonical_segmentsObject

remove trailing zeros segments before first letter or at the end of the version



404
405
406
407
408
409
410
411
412
413
# File 'lib/rubygems/version.rb', line 404

def canonical_segments
  @canonical_segments ||= begin
    # remove trailing 0 segments, using dot or letter as anchor
    # may leave a trailing dot which will be ignored by partition_segments
    canonical_version = @version.sub(/(?<=[a-zA-Z.])[.0]+\z/, "")
    # remove 0 segments before the first letter in a prerelease version
    canonical_version.sub!(/(?<=\.|\A)[0.]+(?=[a-zA-Z])/, "") if prerelease?
    partition_segments(canonical_version)
  end
end

#encode_with(coder) ⇒ Object

:nodoc:



291
292
293
# File 'lib/rubygems/version.rb', line 291

def encode_with(coder) # :nodoc:
  coder.add "version", @version
end

#eql?(other) ⇒ Boolean

A Version is only eql? to another version if it’s specified to the same precision. Version “1.0” is not the same as version “1”.

Returns:

  • (Boolean)


250
251
252
# File 'lib/rubygems/version.rb', line 250

def eql?(other)
  self.class === other && @version == other.version
end

#freezeObject



415
416
417
418
419
420
# File 'lib/rubygems/version.rb', line 415

def freeze
  prerelease?
  _segments
  canonical_segments
  super
end

#hashObject

:nodoc:



254
255
256
# File 'lib/rubygems/version.rb', line 254

def hash # :nodoc:
  canonical_segments.hash
end

#init_with(coder) ⇒ Object

:nodoc:



258
259
260
# File 'lib/rubygems/version.rb', line 258

def init_with(coder) # :nodoc:
  yaml_initialize coder.tag, coder.map
end

#inspectObject

:nodoc:



262
263
264
# File 'lib/rubygems/version.rb', line 262

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

#marshal_dumpObject

Dump only the raw version string, not the complete object. It’s a string for backwards (RubyGems 1.3.5 and earlier) compatibility.



270
271
272
# File 'lib/rubygems/version.rb', line 270

def marshal_dump
  [@version]
end

#marshal_load(array) ⇒ Object

Load custom marshal format. It’s a string for backwards (RubyGems 1.3.5 and earlier) compatibility.

Raises:

  • (TypeError)


278
279
280
281
282
283
# File 'lib/rubygems/version.rb', line 278

def marshal_load(array)
  string = array[0]
  raise TypeError, "wrong version string" unless string.is_a?(String)

  initialize string
end

#prerelease?Boolean

A version is considered a prerelease if it contains a letter.

Returns:

  • (Boolean)


298
299
300
301
302
303
# File 'lib/rubygems/version.rb', line 298

def prerelease?
  unless instance_variable_defined? :@prerelease
    @prerelease = /[a-zA-Z]/.match?(version)
  end
  @prerelease
end

#pretty_print(q) ⇒ Object

:nodoc:



305
306
307
# File 'lib/rubygems/version.rb', line 305

def pretty_print(q) # :nodoc:
  q.text "Gem::Version.new(#{version.inspect})"
end

#releaseObject

The release for this version (e.g. 1.2.0.a -> 1.2.0). Non-prerelease versions return themselves.



313
314
315
316
317
318
319
320
321
# File 'lib/rubygems/version.rb', line 313

def release
  @@release[self] ||= if prerelease?
    segments = self.segments
    segments.pop while segments.any? {|s| String === s }
    self.class.new segments.join(".")
  else
    self
  end
end

#segmentsObject

:nodoc:



323
324
325
# File 'lib/rubygems/version.rb', line 323

def segments # :nodoc:
  _segments.dup
end

#versionObject Also known as: to_s

A string representation of this Version.



166
167
168
# File 'lib/rubygems/version.rb', line 166

def version
  @version
end

#yaml_initialize(tag, map) ⇒ Object

:nodoc:



285
286
287
288
289
# File 'lib/rubygems/version.rb', line 285

def yaml_initialize(tag, map) # :nodoc:
  @version = -map["version"]
  @segments = nil
  @hash = nil
end