brew/Library/Homebrew/version.rb

227 lines
5.2 KiB
Ruby
Raw Normal View History

class VersionElement
include Comparable
attr_reader :elem
def initialize elem
elem = elem.to_s.downcase
@elem = case elem
when 'a', 'alpha' then 'alpha'
when 'b', 'beta' then 'beta'
when /\d+/ then elem.to_i
else elem
end
end
def <=>(other)
return unless other.is_a? VersionElement
return -1 if string? and other.numeric?
return 1 if numeric? and other.string?
return elem <=> other.elem
end
def to_s
@elem.to_s
end
def string?
@elem.is_a? String
end
def numeric?
@elem.is_a? Numeric
end
end
2012-07-09 22:51:10 -05:00
class Version
include Comparable
2012-07-10 16:10:16 -05:00
def initialize val, detected=false
2012-07-09 22:51:10 -05:00
return val if val.is_a? Version or val.nil?
@version = val.to_s
2012-07-10 16:10:16 -05:00
@detected_from_url = detected
end
def detected_from_url?
@detected_from_url
2012-07-09 22:51:10 -05:00
end
def to_a
@array ||= @version.scan(/\d+|[a-zA-Z]+/).map { |e| VersionElement.new(e) }
end
def head?
@version == 'HEAD'
end
def devel?
alpha? or beta? or rc?
end
def alpha?
to_a.any? { |e| e.to_s == 'alpha' }
end
def beta?
to_a.any? { |e| e.to_s == 'beta' }
end
def rc?
to_a.any? { |e| e.to_s == 'rc' }
2012-07-09 22:51:10 -05:00
end
def <=>(other)
# Return nil if objects aren't comparable
return unless other.is_a? Version
# Versions are equal if both are HEAD
return 0 if head? and other.head?
# HEAD is greater than any numerical version
return 1 if head? and not other.head?
return -1 if not head? and other.head?
stuple, otuple = to_a, other.to_a
max = [stuple.length, otuple.length].max
stuple.fill(VersionElement.new(0), stuple.length, max - stuple.length)
otuple.fill(VersionElement.new(0), otuple.length, max - otuple.length)
stuple <=> otuple
2012-07-09 22:51:10 -05:00
end
def to_s
@version
end
alias_method :to_str, :to_s
def self.parse spec
version = _parse(spec)
2012-07-10 16:10:16 -05:00
Version.new(version, true) unless version.nil?
end
private
def self._parse spec
spec = Pathname.new(spec) unless spec.is_a? Pathname
stem = if spec.directory?
spec.basename.to_s
elsif %r[((?:sourceforge.net|sf.net)/.*)/download$].match(spec.to_s)
Pathname.new(spec.dirname).stem
else
spec.stem
end
# GitHub tarballs, e.g. v1.2.3
m = %r[github.com/.+/(?:zip|tar)ball/v?((\d+\.)+\d+)$].match(spec.to_s)
return m.captures.first unless m.nil?
# e.g. https://github.com/sam-github/libnet/tarball/libnet-1.1.4
m = %r[github.com/.+/(?:zip|tar)ball/.*-((\d+\.)+\d+)$].match(spec.to_s)
return m.captures.first unless m.nil?
# e.g. https://github.com/isaacs/npm/tarball/v0.2.5-1
m = %r[github.com/.+/(?:zip|tar)ball/v?((\d+\.)+\d+-(\d+))$].match(spec.to_s)
return m.captures.first unless m.nil?
# e.g. https://github.com/petdance/ack/tarball/1.93_02
m = %r[github.com/.+/(?:zip|tar)ball/v?((\d+\.)+\d+_(\d+))$].match(spec.to_s)
return m.captures.first unless m.nil?
# e.g. boost_1_39_0
m = /((\d+_)+\d+)$/.match(stem)
return m.captures.first.gsub('_', '.') unless m.nil?
# e.g. foobar-4.5.1-1
# e.g. ruby-1.9.1-p243
m = /-((\d+\.)*\d\.\d+-(p|rc|RC)?\d+)$/.match(stem)
return m.captures.first unless m.nil?
# e.g. lame-398-1
m = /-((\d)+-\d)/.match(stem)
return m.captures.first unless m.nil?
# e.g. foobar-4.5.1
m = /-((\d+\.)*\d+)$/.match(stem)
return m.captures.first unless m.nil?
# e.g. foobar-4.5.1b
m = /-((\d+\.)*\d+([abc]|rc|RC)\d*)$/.match(stem)
return m.captures.first unless m.nil?
# e.g. foobar-4.5.0-beta1, or foobar-4.50-beta
m = /-((\d+\.)*\d+-beta(\d+)?)$/.match(stem)
return m.captures.first unless m.nil?
# e.g. foobar4.5.1
m = /((\d+\.)*\d+)$/.match(stem)
return m.captures.first unless m.nil?
# e.g. foobar-4.5.0-bin
m = /-((\d+\.)+\d+[abc]?)[-._](bin|dist|stable|src|sources?)$/.match(stem)
return m.captures.first unless m.nil?
# e.g. dash_0.5.5.1.orig.tar.gz (Debian style)
m = /_((\d+\.)+\d+[abc]?)[.]orig$/.match(stem)
return m.captures.first unless m.nil?
# e.g. erlang-R14B03-bottle.tar.gz (old erlang bottle style)
m = /-([^-]+)/.match(stem)
return m.captures.first unless m.nil?
# e.g. opt_src_R13B (erlang)
m = /otp_src_(.+)/.match(stem)
return m.captures.first unless m.nil?
# e.g. astyle_1.23_macosx.tar.gz
m = /_([^_]+)/.match(stem)
return m.captures.first unless m.nil?
2012-07-09 22:51:10 -05:00
end
2012-08-14 12:16:52 -05:00
# DSL for defining comparators
class << self
def compare &blk
send(:define_method, '<=>', &blk)
end
end
2012-07-09 22:51:10 -05:00
end
class VersionSchemeDetector
def initialize scheme
@scheme = scheme
end
def detect
if @scheme.is_a? Class and @scheme.ancestors.include? Version
@scheme
elsif @scheme.is_a? Symbol then detect_from_symbol
else
raise "Unknown version scheme #{@scheme} was requested."
end
end
private
def detect_from_symbol
raise "Unknown version scheme #{@scheme} was requested."
end
end
# Enable things like "MacOS.version >= :lion"
class MacOSVersion < Version
compare do |other|
case other
when Symbol, Fixnum, Float, Version
super Version.new case other
when :mountain_lion then 10.8
when :lion then 10.7
when :snow_leopard then 10.6
when :leopard then 10.5
else other
end
else
nil
end
end
end