| 
									
										
										
										
											2012-08-18 13:34:31 -05:00
										 |  |  | class VersionElement | 
					
						
							|  |  |  |   include Comparable | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-15 18:20:52 -06:00
										 |  |  |   protected | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   attr_reader :elem | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-18 13:34:31 -05:00
										 |  |  |   def string? | 
					
						
							| 
									
										
										
										
											2013-01-15 18:20:52 -06:00
										 |  |  |     elem.is_a? String | 
					
						
							| 
									
										
										
										
											2012-08-18 13:34:31 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def numeric? | 
					
						
							| 
									
										
										
										
											2013-01-15 18:20:52 -06:00
										 |  |  |     elem.is_a? Numeric | 
					
						
							| 
									
										
										
										
											2012-08-18 13:34:31 -05:00
										 |  |  |   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 23:24:27 -05:00
										 |  |  |     @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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-09 23:00:40 -05:00
										 |  |  |   def head? | 
					
						
							|  |  |  |     @version == 'HEAD' | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-18 13:34:31 -05:00
										 |  |  |   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) | 
					
						
							| 
									
										
										
										
											2012-08-18 13:34:31 -05:00
										 |  |  |     # 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? | 
					
						
							| 
									
										
										
										
											2012-07-09 23:00:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-18 13:34:31 -05:00
										 |  |  |     stuple, otuple = to_a, other.to_a | 
					
						
							| 
									
										
										
										
											2012-07-09 23:00:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-18 13:34:31 -05:00
										 |  |  |     max = [stuple.length, otuple.length].max | 
					
						
							| 
									
										
										
										
											2012-07-09 23:00:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-18 13:34:31 -05:00
										 |  |  |     stuple.fill(VersionElement.new(0), stuple.length, max - stuple.length) | 
					
						
							|  |  |  |     otuple.fill(VersionElement.new(0), otuple.length, max - otuple.length) | 
					
						
							| 
									
										
										
										
											2012-07-09 23:00:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-18 13:34:31 -05:00
										 |  |  |     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 | 
					
						
							| 
									
										
										
										
											2012-07-09 23:24:27 -05:00
										 |  |  |     version = _parse(spec) | 
					
						
							| 
									
										
										
										
											2012-07-10 16:10:16 -05:00
										 |  |  |     Version.new(version, true) unless version.nil? | 
					
						
							| 
									
										
										
										
											2012-07-09 23:24:27 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-07 11:59:33 -06:00
										 |  |  |   protected | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def to_a | 
					
						
							|  |  |  |     @array ||= @version.scan(/\d+|[a-zA-Z]+/).map { |e| VersionElement.new(e) } | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-09 23:24:27 -05:00
										 |  |  |   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? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-25 10:20:48 -07:00
										 |  |  |     # e.g. https://github.com/erlang/otp/tarball/OTP_R15B01 (erlang style) | 
					
						
							| 
									
										
										
										
											2012-12-15 19:06:03 +00:00
										 |  |  |     m = /[-_](R\d+[AB]\d*(-\d+)?)/.match(spec.to_s) | 
					
						
							| 
									
										
										
										
											2012-08-25 10:20:48 -07:00
										 |  |  |     return m.captures.first unless m.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-09 23:24:27 -05:00
										 |  |  |     # 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 | 
					
						
							| 
									
										
										
										
											2012-12-31 11:18:38 +01:00
										 |  |  |     m = /-((\d+\.)*\d\.\d+-(p|rc|RC)?\d+)(?:[-._](?:bin|dist|stable|src|sources))?$/.match(stem) | 
					
						
							| 
									
										
										
										
											2012-07-09 23:24:27 -05:00
										 |  |  |     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? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-25 10:20:48 -07:00
										 |  |  |     # e.g. http://www.openssl.org/source/openssl-0.9.8s.tar.gz | 
					
						
							| 
									
										
										
										
											2012-07-09 23:24:27 -05:00
										 |  |  |     m = /-([^-]+)/.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-10-16 10:31:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # e.g. http://mirrors.jenkins-ci.org/war/1.486/jenkins.war | 
					
						
							|  |  |  |     m = /\/(\d\.\d+)\//.match(spec.to_s) | 
					
						
							|  |  |  |     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 | 
					
						
							| 
									
										
										
										
											2012-07-10 21:45:17 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							| 
									
										
										
										
											2012-08-04 00:26:59 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Enable things like "MacOS.version >= :lion" | 
					
						
							|  |  |  | class MacOSVersion < Version | 
					
						
							|  |  |  |   compare do |other| | 
					
						
							|  |  |  |     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
 | 
					
						
							| 
									
										
										
										
											2012-08-22 10:10:12 -05:00
										 |  |  |       else other.to_s | 
					
						
							| 
									
										
										
										
											2012-08-04 00:26:59 -05:00
										 |  |  |       end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |