module Luffa VERSION = '1.0.7' # A model of a software release version that can be used to compare two versions. # # Calabash and RunLoop try very hard to comply with Semantic Versioning rules. # However, the semantic versioning spec is incompatible with RubyGem's patterns # for pre-release gems. # # > "But returning to the practical: No release version of SemVer is compatible with Rubygems." - _David Kellum_ # # Calabash and RunLoop version numbers will be in the form `..[.pre]`. # # @see http://semver.org/ # @see http://gravitext.com/2012/07/22/versioning.html class Version # @!attribute [rw] major # @return [Integer] the major version attr_accessor :major # @!attribute [rw] minor # @return [Integer] the minor version attr_accessor :minor # @!attribute [rw] patch # @return [Integer] the patch version attr_accessor :patch # @!attribute [rw] pre # @return [Boolean] true if this is a pre-release version attr_accessor :pre # @!attribute [rw] pre_version # @return [Integer] if this is a pre-release version, returns the # pre-release version; otherwise this is nil attr_accessor :pre_version # Creates a new Version instance with all the attributes set. # # @example # version = Version.new(0.10.1) # version.major => 0 # version.minor => 10 # version.patch => 1 # version.pre => false # version.pre_release => nil # # @example # version = Version.new(1.6.3.pre5) # version.major => 1 # version.minor => 6 # version.patch => 3 # version.pre => true # version.pre_release => 5 # # @param [String] version the version string to parse. # @raise [ArgumentError] if version is not in the form 5, 6.1, 7.1.2, 8.2.3.pre1 def initialize(version) tokens = version.strip.split('.') count = tokens.count if tokens.empty? raise ArgumentError, "expected '#{version}' to be like 5, 6.1, 7.1.2, 8.2.3.pre1" end if count < 4 and tokens.any? { |elm| elm =~ /\D/ } raise ArgumentError, "expected '#{version}' to be like 5, 6.1, 7.1.2, 8.2.3.pre1" end if count == 4 @pre = tokens[3] pre_tokens = @pre.scan(/\D+|\d+/) @pre_version = pre_tokens[1].to_i if pre_tokens.count == 2 end @major, @minor, @patch = version.split('.').map(&:to_i) end # Returns an string representation of this version. # @return [String] a string in the form `..[.pre]` def to_s str = [major, minor, patch].compact.join('.') str = "#{str}.#{pre}" if pre str end # Compare this version to another for equality. # @param [Version] other the version to compare against # @return [Boolean] true if this Version is the same as `other` def == (other) Version.compare(self, other) == 0 end # Compare this version to another for inequality. # @param [Version] other the version to compare against # @return [Boolean] true if this Version is not the same as `other` def != (other) Version.compare(self, other) != 0 end # Is this version less-than another version? # @param [Version] other the version to compare against # @return [Boolean] true if this Version is less-than `other` def < (other) Version.compare(self, other) < 0 end # Is this version greater-than another version? # @param [Version] other the version to compare against # @return [Boolean] true if this Version is greater-than `other` def > (other) Version.compare(self, other) > 0 end # Is this version less-than or equal to another version? # @param [Version] other the version to compare against # @return [Boolean] true if this Version is less-than or equal `other` def <= (other) Version.compare(self, other) <= 0 end # Is this version greater-than or equal to another version? # @param [Version] other the version to compare against # @return [Boolean] true if this Version is greater-than or equal `other` def >= (other) Version.compare(self, other) >= 0 end # Compare version `a` to version `b`. # # @example # compare Version.new(0.10.0), Version.new(0.9.0) => 1 # compare Version.new(0.9.0), Version.new(0.10.0) => -1 # compare Version.new(0.9.0), Version.new(0.9.0) => 0 # # @return [Integer] an integer `(-1, 1)` def self.compare(a, b) if a.major != b.major return a.major > b.major ? 1 : -1 end if a.minor != b.minor return a.minor.to_i > b.minor.to_i ? 1 : -1 end if a.patch != b.patch return a.patch.to_i > b.patch.to_i ? 1 : -1 end return -1 if a.pre and (not a.pre_version) and b.pre_version return 1 if a.pre_version and b.pre and (not b.pre_version) return -1 if a.pre and (not b.pre) return 1 if (not a.pre) and b.pre return -1 if a.pre_version and (not b.pre_version) return 1 if (not a.pre_version) and b.pre_version if a.pre_version != b.pre_version return a.pre_version.to_i > b.pre_version.to_i ? 1 : -1 end 0 end end end