class Gem::Version

Public Class Methods

True if the version string matches RubyGems’ requirements.

# File lib/rubygems/version.rb, line 174
def self.correct?(version)
  version.nil? || ANCHORED_VERSION_PATTERN.match?(version.to_s)
end

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)
# File lib/rubygems/version.rb, line 185
def self.create(input)
  if self === input # check yourself before you wreck yourself
    input
  else
    new input
  end
end

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

# File lib/rubygems/version.rb, line 207
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
end

Public Instance Methods

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.

# File lib/rubygems/version.rb, line 346
def <=>(other)
  if String === other
    return unless self.class.correct?(other)
    return self <=> self.class.new(other)
  end

  return unless Gem::Version === other
  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
end

A recommended version for use with a ~> Requirement.

# File lib/rubygems/version.rb, line 328
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

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.

# File lib/rubygems/version.rb, line 233
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

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

# File lib/rubygems/version.rb, line 398
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

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”.

# File lib/rubygems/version.rb, line 248
def eql?(other)
  self.class === other && @version == other.version
end
Calls superclass method Object#freeze
# File lib/rubygems/version.rb, line 409
def freeze
  prerelease?
  _segments
  canonical_segments
  super
end

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

# File lib/rubygems/version.rb, line 268
def marshal_dump
  [@version]
end

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

# File lib/rubygems/version.rb, line 276
def marshal_load(array)
  string = array[0]
  raise TypeError, "wrong version string" unless string.is_a?(String)

  initialize string
end

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

# File lib/rubygems/version.rb, line 296
def prerelease?
  unless instance_variable_defined? :@prerelease
    @prerelease = /[a-zA-Z]/.match?(version)
  end
  @prerelease
end

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

# File lib/rubygems/version.rb, line 311
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
Alias for: version

A string representation of this Version.

# File lib/rubygems/version.rb, line 165
def version
  @version
end
Also aliased as: to_s

Protected Instance Methods

# File lib/rubygems/version.rb, line 418
def _segments
  # segments is lazy so it can pick up version values that come from
  # old marshaled versions, which don't go through marshal_load.
  # since this version object is cached in @@all, its @segments should be frozen
  @segments ||= partition_segments(@version)
end
# File lib/rubygems/version.rb, line 425
def partition_segments(ver)
  ver.scan(/\d+|[a-z]+/i).map! do |s|
    /\A\d/.match?(s) ? s.to_i : -s
  end.freeze
end