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



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# 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

Class Method Details

.correct?(version) ⇒ Boolean

True if the version string matches RubyGems’ requirements.

Returns:

  • (Boolean)


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

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)


185
186
187
188
189
190
191
# 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

.new(version) ⇒ Object

:nodoc:



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

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.



346
347
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
# 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

#approximate_recommendationObject

A recommended version for use with a ~> Requirement.



328
329
330
331
332
333
334
335
336
337
338
# 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

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



233
234
235
236
237
238
239
240
241
242
# 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

#canonical_segmentsObject

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



398
399
400
401
402
403
404
405
406
407
# 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

#encode_with(coder) ⇒ Object

:nodoc:



289
290
291
# File 'lib/rubygems/version.rb', line 289

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)


248
249
250
# File 'lib/rubygems/version.rb', line 248

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

#freezeObject



409
410
411
412
413
414
# File 'lib/rubygems/version.rb', line 409

def freeze
  prerelease?
  _segments
  canonical_segments
  super
end

#hashObject

:nodoc:



252
253
254
# File 'lib/rubygems/version.rb', line 252

def hash # :nodoc:
  canonical_segments.hash
end

#init_with(coder) ⇒ Object

:nodoc:



256
257
258
# File 'lib/rubygems/version.rb', line 256

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

#inspectObject

:nodoc:



260
261
262
# File 'lib/rubygems/version.rb', line 260

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.



268
269
270
# File 'lib/rubygems/version.rb', line 268

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)


276
277
278
279
280
281
# 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

#prerelease?Boolean

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

Returns:

  • (Boolean)


296
297
298
299
300
301
# File 'lib/rubygems/version.rb', line 296

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

#pretty_print(q) ⇒ Object

:nodoc:



303
304
305
# File 'lib/rubygems/version.rb', line 303

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.



311
312
313
314
315
316
317
318
319
# 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

#segmentsObject

:nodoc:



321
322
323
# File 'lib/rubygems/version.rb', line 321

def segments # :nodoc:
  _segments.dup
end

#versionObject Also known as: to_s

A string representation of this Version.



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

def version
  @version
end

#yaml_initialize(tag, map) ⇒ Object

:nodoc:



283
284
285
286
287
# File 'lib/rubygems/version.rb', line 283

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