mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/rubygems: update to 1.3.6.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26728 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
65544f575b
commit
b551e8c8b3
119 changed files with 2735 additions and 2613 deletions
|
@ -1,9 +1,3 @@
|
|||
#--
|
||||
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
|
||||
# All rights reserved.
|
||||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
##
|
||||
# The Version class processes string versions into comparable
|
||||
# values. A version string should normally be a series of numbers
|
||||
|
@ -24,72 +18,153 @@
|
|||
# 2. 1.0.b
|
||||
# 3. 1.0.a
|
||||
# 4. 0.9
|
||||
#
|
||||
# == How Software Changes
|
||||
#
|
||||
# Users expect to be able to specify a version constraint that gives them
|
||||
# some reasonable expectation that new versions of a library will work with
|
||||
# their software if the version constraint is true, and not work with their
|
||||
# software if the version constraint is false. In other words, the perfect
|
||||
# system will accept all compatible versions of the library and reject all
|
||||
# incompatible versions.
|
||||
#
|
||||
# Libraries change in 3 ways (well, more than 3, but stay focused here!).
|
||||
#
|
||||
# 1. The change may be an implementation detail only and have no effect on
|
||||
# the client software.
|
||||
# 2. The change may add new features, but do so in a way that client software
|
||||
# written to an earlier version is still compatible.
|
||||
# 3. The change may change the public interface of the library in such a way
|
||||
# that old software is no longer compatible.
|
||||
#
|
||||
# Some examples are appropriate at this point. Suppose I have a Stack class
|
||||
# that supports a <tt>push</tt> and a <tt>pop</tt> method.
|
||||
#
|
||||
# === Examples of Category 1 changes:
|
||||
#
|
||||
# * Switch from an array based implementation to a linked-list based
|
||||
# implementation.
|
||||
# * Provide an automatic (and transparent) backing store for large stacks.
|
||||
#
|
||||
# === Examples of Category 2 changes might be:
|
||||
#
|
||||
# * Add a <tt>depth</tt> method to return the current depth of the stack.
|
||||
# * Add a <tt>top</tt> method that returns the current top of stack (without
|
||||
# changing the stack).
|
||||
# * Change <tt>push</tt> so that it returns the item pushed (previously it
|
||||
# had no usable return value).
|
||||
#
|
||||
# === Examples of Category 3 changes might be:
|
||||
#
|
||||
# * Changes <tt>pop</tt> so that it no longer returns a value (you must use
|
||||
# <tt>top</tt> to get the top of the stack).
|
||||
# * Rename the methods to <tt>push_item</tt> and <tt>pop_item</tt>.
|
||||
#
|
||||
# == RubyGems Rational Versioning
|
||||
#
|
||||
# * Versions shall be represented by three non-negative integers, separated
|
||||
# by periods (e.g. 3.1.4). The first integers is the "major" version
|
||||
# number, the second integer is the "minor" version number, and the third
|
||||
# integer is the "build" number.
|
||||
#
|
||||
# * A category 1 change (implementation detail) will increment the build
|
||||
# number.
|
||||
#
|
||||
# * A category 2 change (backwards compatible) will increment the minor
|
||||
# version number and reset the build number.
|
||||
#
|
||||
# * A category 3 change (incompatible) will increment the major build number
|
||||
# and reset the minor and build numbers.
|
||||
#
|
||||
# * Any "public" release of a gem should have a different version. Normally
|
||||
# that means incrementing the build number. This means a developer can
|
||||
# generate builds all day long for himself, but as soon as he/she makes a
|
||||
# public release, the version must be updated.
|
||||
#
|
||||
# === Examples
|
||||
#
|
||||
# Let's work through a project lifecycle using our Stack example from above.
|
||||
#
|
||||
# Version 0.0.1:: The initial Stack class is release.
|
||||
# Version 0.0.2:: Switched to a linked=list implementation because it is
|
||||
# cooler.
|
||||
# Version 0.1.0:: Added a <tt>depth</tt> method.
|
||||
# Version 1.0.0:: Added <tt>top</tt> and made <tt>pop</tt> return nil
|
||||
# (<tt>pop</tt> used to return the old top item).
|
||||
# Version 1.1.0:: <tt>push</tt> now returns the value pushed (it used it
|
||||
# return nil).
|
||||
# Version 1.1.1:: Fixed a bug in the linked list implementation.
|
||||
# Version 1.1.2:: Fixed a bug introduced in the last fix.
|
||||
#
|
||||
# Client A needs a stack with basic push/pop capability. He writes to the
|
||||
# original interface (no <tt>top</tt>), so his version constraint looks
|
||||
# like:
|
||||
#
|
||||
# gem 'stack', '~> 0.0'
|
||||
#
|
||||
# Essentially, any version is OK with Client A. An incompatible change to
|
||||
# the library will cause him grief, but he is willing to take the chance (we
|
||||
# call Client A optimistic).
|
||||
#
|
||||
# Client B is just like Client A except for two things: (1) He uses the
|
||||
# <tt>depth</tt> method and (2) he is worried about future
|
||||
# incompatibilities, so he writes his version constraint like this:
|
||||
#
|
||||
# gem 'stack', '~> 0.1'
|
||||
#
|
||||
# The <tt>depth</tt> method was introduced in version 0.1.0, so that version
|
||||
# or anything later is fine, as long as the version stays below version 1.0
|
||||
# where incompatibilities are introduced. We call Client B pessimistic
|
||||
# because he is worried about incompatible future changes (it is OK to be
|
||||
# pessimistic!).
|
||||
#
|
||||
# == Preventing Version Catastrophe:
|
||||
#
|
||||
# From: http://blog.zenspider.com/2008/10/rubygems-howto-preventing-cata.html
|
||||
#
|
||||
# Let's say you're depending on the fnord gem version 2.y.z. If you
|
||||
# specify your dependency as ">= 2.0.0" then, you're good, right? What
|
||||
# happens if fnord 3.0 comes out and it isn't backwards compatible
|
||||
# with 2.y.z? Your stuff will break as a result of using ">=". The
|
||||
# better route is to specify your dependency with a "spermy" version
|
||||
# specifier. They're a tad confusing, so here is how the dependency
|
||||
# specifiers work:
|
||||
#
|
||||
# Specification From ... To (exclusive)
|
||||
# ">= 3.0" 3.0 ... ∞
|
||||
# "~> 3.0" 3.0 ... 4.0
|
||||
# "~> 3.0.0" 3.0.0 ... 3.1
|
||||
# "~> 3.5" 3.5 ... 4.0
|
||||
# "~> 3.5.0" 3.5.0 ... 3.6
|
||||
|
||||
class Gem::Version
|
||||
|
||||
class Part
|
||||
include Comparable
|
||||
|
||||
attr_reader :value
|
||||
|
||||
def initialize(value)
|
||||
@value = (value =~ /\A\d+\z/) ? value.to_i : value
|
||||
end
|
||||
|
||||
def to_s
|
||||
self.value.to_s
|
||||
end
|
||||
|
||||
def inspect
|
||||
@value
|
||||
end
|
||||
|
||||
def alpha?
|
||||
String === value
|
||||
end
|
||||
|
||||
def numeric?
|
||||
Fixnum === value
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
if self.numeric? && other.alpha? then
|
||||
1
|
||||
elsif self.alpha? && other.numeric? then
|
||||
-1
|
||||
else
|
||||
self.value <=> other.value
|
||||
end
|
||||
end
|
||||
|
||||
def succ
|
||||
self.class.new(self.value.succ)
|
||||
end
|
||||
end
|
||||
|
||||
include Comparable
|
||||
|
||||
VERSION_PATTERN = '[0-9]+(\.[0-9a-z]+)*'
|
||||
VERSION_PATTERN = '[0-9]+(\.[0-9a-zA-Z]+)*' # :nodoc:
|
||||
ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})*\s*\z/ # :nodoc:
|
||||
|
||||
##
|
||||
# A string representation of this Version.
|
||||
|
||||
attr_reader :version
|
||||
alias to_s version
|
||||
|
||||
def self.correct?(version)
|
||||
pattern = /\A\s*(#{VERSION_PATTERN})*\s*\z/
|
||||
##
|
||||
# True if the +version+ string matches RubyGems' requirements.
|
||||
|
||||
version.is_a? Integer or
|
||||
version =~ pattern or
|
||||
version.to_s =~ pattern
|
||||
def self.correct? version
|
||||
version.to_s =~ ANCHORED_VERSION_PATTERN
|
||||
end
|
||||
|
||||
##
|
||||
# Factory method to create a Version object. Input may be a Version or a
|
||||
# String. Intended to simplify client code.
|
||||
# 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)
|
||||
# ver3 = Version.create(nil) # -> nil
|
||||
|
||||
def self.create(input)
|
||||
def self.create input
|
||||
if input.respond_to? :version then
|
||||
input
|
||||
elsif input.nil? then
|
||||
|
@ -103,149 +178,129 @@ class Gem::Version
|
|||
# Constructs a Version from the +version+ string. A version string is a
|
||||
# series of digits or ASCII letters separated by dots.
|
||||
|
||||
def initialize(version)
|
||||
def initialize version
|
||||
raise ArgumentError, "Malformed version number string #{version}" unless
|
||||
self.class.correct?(version)
|
||||
|
||||
self.version = version
|
||||
@version = version.to_s
|
||||
@version.strip!
|
||||
|
||||
segments # prime @segments
|
||||
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.b2 => 5.4, are ignored.
|
||||
|
||||
def bump
|
||||
segments = self.segments.dup
|
||||
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
|
||||
|
||||
##
|
||||
# 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".
|
||||
|
||||
def eql? other
|
||||
self.class === other and segments == other.segments
|
||||
end
|
||||
|
||||
def hash # :nodoc:
|
||||
segments.hash
|
||||
end
|
||||
|
||||
def inspect # :nodoc:
|
||||
"#<#{self.class} #{@version.inspect}>"
|
||||
"#<#{self.class} #{version.inspect}>"
|
||||
end
|
||||
|
||||
##
|
||||
# Dump only the raw version string, not the complete object
|
||||
# Dump only the raw version string, not the complete object. It's a
|
||||
# string for backwards (RubyGems 1.3.5 and earlier) compatibility.
|
||||
|
||||
def marshal_dump
|
||||
[@version]
|
||||
[version]
|
||||
end
|
||||
|
||||
##
|
||||
# Load custom marshal format
|
||||
# Load custom marshal format. It's a string for backwards (RubyGems
|
||||
# 1.3.5 and earlier) compatibility.
|
||||
|
||||
def marshal_load(array)
|
||||
self.version = array[0]
|
||||
def marshal_load array
|
||||
initialize array[0]
|
||||
end
|
||||
|
||||
def parts
|
||||
@parts ||= normalize
|
||||
end
|
||||
|
||||
##
|
||||
# Strip ignored trailing zeros.
|
||||
|
||||
def normalize
|
||||
parts_arr = parse_parts_from_version_string
|
||||
if parts_arr.length != 1
|
||||
parts_arr.pop while parts_arr.last && parts_arr.last.value == 0
|
||||
parts_arr = [Part.new(0)] if parts_arr.empty?
|
||||
end
|
||||
parts_arr
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the text representation of the version
|
||||
|
||||
def to_s
|
||||
@version
|
||||
end
|
||||
|
||||
def to_yaml_properties
|
||||
['@version']
|
||||
end
|
||||
|
||||
def version=(version)
|
||||
@version = version.to_s.strip
|
||||
normalize
|
||||
end
|
||||
|
||||
##
|
||||
# A version is considered a prerelease if any part contains a letter.
|
||||
# A version is considered a prerelease if it contains a letter.
|
||||
|
||||
def prerelease?
|
||||
parts.any? { |part| part.alpha? }
|
||||
@prerelease ||= segments.any? { |s| String === s }
|
||||
end
|
||||
|
||||
def pretty_print q # :nodoc:
|
||||
q.text "Gem::Version.new(#{version.inspect})"
|
||||
end
|
||||
##
|
||||
# The release for this version (e.g. 1.2.0.a -> 1.2.0).
|
||||
# Non-prerelease versions return themselves.
|
||||
|
||||
def release
|
||||
return self unless prerelease?
|
||||
|
||||
segments = self.segments.dup
|
||||
segments.pop while segments.any? { |s| String === s }
|
||||
self.class.new segments.join('.')
|
||||
end
|
||||
|
||||
def segments # :nodoc:
|
||||
|
||||
# @segments is lazy so it can pick up @version values that come
|
||||
# from old marshaled versions, which don't go through
|
||||
# marshal_load. +segments+ is called in +initialize+ to "prime
|
||||
# the pump" in normal cases.
|
||||
|
||||
@segments ||= @version.scan(/[0-9a-z]+/i).map do |s|
|
||||
/^\d+$/ =~ s ? s.to_i : s
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# The release for this version (e.g. 1.2.0.a -> 1.2.0)
|
||||
# Non-prerelease versions return themselves
|
||||
def release
|
||||
return self unless prerelease?
|
||||
rel_parts = parts.dup
|
||||
rel_parts.pop while rel_parts.any? { |part| part.alpha? }
|
||||
self.class.new(rel_parts.join('.'))
|
||||
end
|
||||
# A recommended version for use with a ~> Requirement.
|
||||
|
||||
def yaml_initialize(tag, values)
|
||||
self.version = values['version']
|
||||
def spermy_recommendation
|
||||
segments = self.segments.dup
|
||||
|
||||
segments.pop while segments.any? { |s| String === s }
|
||||
segments.pop while segments.size > 2
|
||||
segments.push 0 while segments.size < 2
|
||||
|
||||
"~> #{segments.join(".")}"
|
||||
end
|
||||
|
||||
##
|
||||
# Compares this version with +other+ returning -1, 0, or 1 if the other
|
||||
# version is larger, the same, or smaller than this one.
|
||||
|
||||
def <=>(other)
|
||||
def <=> other
|
||||
return 1 unless other # HACK: comparable with nil? why?
|
||||
return nil unless self.class === other
|
||||
return 1 unless other
|
||||
mine, theirs = balance(self.parts.dup, other.parts.dup)
|
||||
mine <=> theirs
|
||||
|
||||
lhsize = segments.size
|
||||
rhsize = other.segments.size
|
||||
limit = (lhsize > rhsize ? lhsize : rhsize) - 1
|
||||
|
||||
0.upto(limit) do |i|
|
||||
lhs, rhs = segments[i] || 0, other.segments[i] || 0
|
||||
|
||||
return -1 if String === lhs && Numeric === rhs
|
||||
return 1 if Numeric === lhs && String === rhs
|
||||
return lhs <=> rhs if lhs != rhs
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
def balance(a, b)
|
||||
a << Part.new(0) while a.size < b.size
|
||||
b << Part.new(0) while b.size < a.size
|
||||
[a, b]
|
||||
end
|
||||
|
||||
##
|
||||
# A Version is only eql? to another version if it has the same version
|
||||
# string. "1.0" is not the same version as "1".
|
||||
|
||||
def eql?(other)
|
||||
self.class === other and @version == other.version
|
||||
end
|
||||
|
||||
def hash # :nodoc:
|
||||
@version.hash
|
||||
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 are ignored. (e.g 5.3.1.b2 => 5.4)
|
||||
|
||||
def bump
|
||||
parts = parse_parts_from_version_string
|
||||
parts.pop while parts.any? { |part| part.alpha? }
|
||||
parts.pop if parts.size > 1
|
||||
parts[-1] = parts[-1].succ
|
||||
self.class.new(parts.join("."))
|
||||
end
|
||||
|
||||
def parse_parts_from_version_string # :nodoc:
|
||||
@version.to_s.scan(/[0-9a-z]+/i).map { |s| Part.new(s) }
|
||||
end
|
||||
|
||||
def pretty_print(q) # :nodoc:
|
||||
q.text "Gem::Version.new(#{@version.inspect})"
|
||||
end
|
||||
|
||||
#:stopdoc:
|
||||
|
||||
require 'rubygems/requirement'
|
||||
|
||||
##
|
||||
# Gem::Requirement's original definition is nested in Version.
|
||||
# Although an inappropriate place, current gems specs reference the nested
|
||||
# class name explicitly. To remain compatible with old software loading
|
||||
# gemspecs, we leave a copy of original definition in Version, but define an
|
||||
# alias Gem::Requirement for use everywhere else.
|
||||
|
||||
Requirement = ::Gem::Requirement
|
||||
|
||||
# :startdoc:
|
||||
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue