brew/Library/Homebrew/version.rb

687 lines
18 KiB
Ruby
Raw Normal View History

2021-01-16 11:49:01 -08:00
# typed: true
# frozen_string_literal: true
require "pkg_version"
2016-11-03 16:28:16 -07:00
require "version/null"
2020-08-09 02:59:18 +02:00
# A formula's version.
#
# @api private
class Version
2020-10-20 12:03:48 +02:00
extend T::Sig
include Comparable
2021-01-16 11:49:01 -08:00
sig { params(name: T.any(String, Symbol), full: T::Boolean).returns(Regexp) }
def self.formula_optionally_versioned_regex(name, full: true)
/#{"^" if full}#{Regexp.escape(name)}(@\d[\d.]*)?#{"$" if full}/
end
# A part of a {Version}.
class Token
2020-10-20 12:03:48 +02:00
extend T::Sig
2021-01-16 11:49:01 -08:00
extend T::Helpers
abstract!
2020-10-20 12:03:48 +02:00
include Comparable
2021-01-16 11:49:01 -08:00
sig { params(val: String).returns(Token) }
def self.create(val)
raise TypeError, "Token value must be a string; got a #{val.class} (#{val})" unless val.respond_to?(:to_str)
case val
when /\A#{AlphaToken::PATTERN}\z/o then AlphaToken
when /\A#{BetaToken::PATTERN}\z/o then BetaToken
when /\A#{RCToken::PATTERN}\z/o then RCToken
when /\A#{PreToken::PATTERN}\z/o then PreToken
when /\A#{PatchToken::PATTERN}\z/o then PatchToken
2020-10-04 14:43:32 -04:00
when /\A#{PostToken::PATTERN}\z/o then PostToken
when /\A#{NumericToken::PATTERN}\z/o then NumericToken
when /\A#{StringToken::PATTERN}\z/o then StringToken
end.new(val)
end
2021-01-16 11:49:01 -08:00
sig { params(val: T.untyped).returns(T.nilable(Token)) }
def self.from(val)
2021-01-16 11:49:01 -08:00
return NULL_TOKEN if val.nil? || (val.respond_to?(:null?) && val.null?)
case val
when Token then val
when String then Token.create(val)
when Integer then Token.create(val.to_s)
end
end
2021-01-16 11:49:01 -08:00
sig { returns(T.nilable(T.any(String, Integer))) }
attr_reader :value
2013-04-15 15:00:57 -05:00
2021-01-16 11:49:01 -08:00
sig { params(value: T.nilable(T.any(String, Integer))).void }
def initialize(value)
2021-01-16 11:49:01 -08:00
@value = T.let(value, T.untyped)
end
2021-01-16 11:49:01 -08:00
sig { abstract.params(other: T.untyped).returns(T.nilable(Integer)) }
def <=>(other); end
2020-10-20 12:03:48 +02:00
sig { returns(String) }
def inspect
"#<#{self.class.name} #{value.inspect}>"
end
2013-06-05 23:30:55 -05:00
2021-01-16 11:49:01 -08:00
sig { returns(Integer) }
def hash
value.hash
end
2021-01-16 11:49:01 -08:00
sig { returns(Float) }
def to_f
value.to_f
end
2021-01-16 11:49:01 -08:00
sig { returns(Integer) }
def to_i
value.to_i
end
2021-01-16 11:49:01 -08:00
sig { returns(String) }
2013-06-05 23:30:55 -05:00
def to_s
value.to_s
end
alias to_str to_s
2015-03-17 21:37:03 -04:00
2020-10-20 12:03:48 +02:00
sig { returns(T::Boolean) }
2015-03-17 21:37:03 -04:00
def numeric?
false
end
2021-01-16 11:49:01 -08:00
sig { returns(T::Boolean) }
def null?
false
end
end
2020-08-09 02:59:18 +02:00
# A pseudo-token representing the absence of a token.
class NullToken < Token
2020-10-20 12:03:48 +02:00
extend T::Sig
2021-01-16 11:49:01 -08:00
sig { override.returns(NilClass) }
attr_reader :value
sig { void }
2020-08-09 02:59:18 +02:00
def initialize
super(nil)
end
2021-01-16 11:49:01 -08:00
sig { override.params(other: T.untyped).returns(T.nilable(Integer)) }
def <=>(other)
return unless other = Token.from(other)
case other
2015-03-17 21:37:03 -04:00
when NullToken
0
when NumericToken
other.value.zero? ? 0 : -1
2017-06-27 03:17:23 -07:00
when AlphaToken, BetaToken, PreToken, RCToken
1
else
-1
end
end
2021-01-16 11:49:01 -08:00
sig { override.returns(T::Boolean) }
def null?
true
end
2021-01-16 11:49:01 -08:00
sig { override.returns(String) }
def inspect
"#<#{self.class.name}>"
end
end
2020-08-09 02:59:18 +02:00
private_constant :NullToken
2020-08-09 02:59:18 +02:00
# Represents the absence of a token.
2019-04-19 21:46:20 +09:00
NULL_TOKEN = NullToken.new.freeze
2020-08-09 02:59:18 +02:00
# A token string.
class StringToken < Token
PATTERN = /[a-z]+/i.freeze
2021-01-16 11:49:01 -08:00
sig { override.returns(String) }
attr_reader :value
2020-08-19 17:12:32 +01:00
2021-01-16 11:49:01 -08:00
sig { params(value: String).void }
def initialize(value)
super(value.to_s)
end
2021-01-16 11:49:01 -08:00
sig { override.params(other: T.untyped).returns(T.nilable(Integer)) }
def <=>(other)
return unless other = Token.from(other)
case other
when StringToken
value <=> other.value
when NumericToken, NullToken
2021-01-16 11:49:01 -08:00
-T.must(other <=> self)
end
end
end
2020-08-09 02:59:18 +02:00
# A token consisting of only numbers.
class NumericToken < Token
2018-11-02 17:18:07 +00:00
PATTERN = /[0-9]+/i.freeze
2020-10-20 12:03:48 +02:00
extend T::Sig
2021-01-16 11:49:01 -08:00
sig { override.returns(Integer) }
attr_reader :value
2020-08-19 17:12:32 +01:00
2021-01-16 11:49:01 -08:00
sig { params(value: T.any(String, Integer)).void }
def initialize(value)
super(value.to_i)
end
2021-01-16 11:49:01 -08:00
sig { override.params(other: T.untyped).returns(T.nilable(Integer)) }
def <=>(other)
return unless other = Token.from(other)
case other
when NumericToken
value <=> other.value
when StringToken
1
when NullToken
2021-01-16 11:49:01 -08:00
-T.must(other <=> self)
end
end
2015-03-17 21:37:03 -04:00
2021-01-16 11:49:01 -08:00
sig { override.returns(T::Boolean) }
2015-03-17 21:37:03 -04:00
def numeric?
true
end
end
2020-08-09 02:59:18 +02:00
# A token consisting of an alphabetic and a numeric part.
class CompositeToken < StringToken
2021-01-16 11:49:01 -08:00
sig { returns(Integer) }
def rev
value[/[0-9]+/].to_i
end
end
2012-07-09 22:51:10 -05:00
# A token representing the part of a version designating it as an alpha release.
class AlphaToken < CompositeToken
2018-11-02 17:18:07 +00:00
PATTERN = /alpha[0-9]*|a[0-9]+/i.freeze
2021-01-16 11:49:01 -08:00
sig { override.params(other: T.untyped).returns(T.nilable(Integer)) }
def <=>(other)
return unless other = Token.from(other)
case other
when AlphaToken
rev <=> other.rev
2020-10-04 14:43:32 -04:00
when BetaToken, RCToken, PreToken, PatchToken, PostToken
2017-06-27 03:17:23 -07:00
-1
else
super
end
end
2012-07-10 16:10:16 -05:00
end
# A token representing the part of a version designating it as a beta release.
class BetaToken < CompositeToken
2018-11-02 17:18:07 +00:00
PATTERN = /beta[0-9]*|b[0-9]+/i.freeze
2021-01-16 11:49:01 -08:00
sig { override.params(other: T.untyped).returns(T.nilable(Integer)) }
def <=>(other)
return unless other = Token.from(other)
case other
when BetaToken
rev <=> other.rev
when AlphaToken
1
2020-10-04 14:43:32 -04:00
when PreToken, RCToken, PatchToken, PostToken
2017-06-27 03:17:23 -07:00
-1
else
super
end
end
end
# A token representing the part of a version designating it as a pre-release.
2017-06-27 03:17:23 -07:00
class PreToken < CompositeToken
2018-11-02 17:18:07 +00:00
PATTERN = /pre[0-9]*/i.freeze
2017-06-27 03:17:23 -07:00
2021-01-16 11:49:01 -08:00
sig { override.params(other: T.untyped).returns(T.nilable(Integer)) }
2017-06-27 03:17:23 -07:00
def <=>(other)
return unless other = Token.from(other)
2017-06-27 03:17:23 -07:00
case other
when PreToken
rev <=> other.rev
when AlphaToken, BetaToken
1
2020-10-04 14:43:32 -04:00
when RCToken, PatchToken, PostToken
-1
else
super
end
end
2012-07-09 22:51:10 -05:00
end
# A token representing the part of a version designating it as a release candidate.
class RCToken < CompositeToken
2018-11-02 17:18:07 +00:00
PATTERN = /rc[0-9]*/i.freeze
2021-01-16 11:49:01 -08:00
sig { override.params(other: T.untyped).returns(T.nilable(Integer)) }
def <=>(other)
return unless other = Token.from(other)
case other
when RCToken
rev <=> other.rev
2017-06-27 03:17:23 -07:00
when AlphaToken, BetaToken, PreToken
1
2020-10-04 14:43:32 -04:00
when PatchToken, PostToken
-1
else
super
end
end
end
# A token representing the part of a version designating it as a patch release.
class PatchToken < CompositeToken
2018-11-02 17:18:07 +00:00
PATTERN = /p[0-9]*/i.freeze
2021-01-16 11:49:01 -08:00
sig { override.params(other: T.untyped).returns(T.nilable(Integer)) }
def <=>(other)
return unless other = Token.from(other)
case other
when PatchToken
rev <=> other.rev
2017-06-27 03:17:23 -07:00
when AlphaToken, BetaToken, RCToken, PreToken
1
else
super
end
end
end
# A token representing the part of a version designating it as a post release.
2020-10-04 14:43:32 -04:00
class PostToken < CompositeToken
PATTERN = /.post[0-9]+/i.freeze
2021-01-16 11:49:01 -08:00
sig { override.params(other: T.untyped).returns(T.nilable(Integer)) }
2020-10-04 14:43:32 -04:00
def <=>(other)
return unless other = Token.from(other)
case other
when PostToken
rev <=> other.rev
when AlphaToken, BetaToken, RCToken, PreToken
1
else
super
end
end
end
2014-04-03 11:19:57 -05:00
SCAN_PATTERN = Regexp.union(
AlphaToken::PATTERN,
BetaToken::PATTERN,
2017-06-27 03:17:23 -07:00
PreToken::PATTERN,
2014-04-03 11:19:57 -05:00
RCToken::PATTERN,
PatchToken::PATTERN,
2020-10-04 14:43:32 -04:00
PostToken::PATTERN,
2014-04-03 11:19:57 -05:00
NumericToken::PATTERN,
StringToken::PATTERN,
2019-04-19 21:46:20 +09:00
).freeze
2020-08-09 02:59:18 +02:00
private_constant :SCAN_PATTERN
2014-04-03 11:19:57 -05:00
2021-01-16 11:49:01 -08:00
sig { params(url: T.any(String, Pathname), specs: T.untyped).returns(Version) }
2020-08-09 02:59:18 +02:00
def self.detect(url, **specs)
parse(specs.fetch(:tag, url), detected_from_url: true)
end
2021-01-16 11:49:01 -08:00
sig { params(val: String).returns(Version) }
2016-06-18 20:33:03 +03:00
def self.create(val)
raise TypeError, "Version value must be a string; got a #{val.class} (#{val})" unless val.respond_to?(:to_str)
2016-06-18 20:33:03 +03:00
if val.to_str.start_with?("HEAD")
HeadVersion.new(val)
else
Version.new(val)
end
end
2021-01-16 11:49:01 -08:00
sig { params(spec: T.any(String, Pathname), detected_from_url: T::Boolean).returns(Version) }
2020-08-09 02:59:18 +02:00
def self.parse(spec, detected_from_url: false)
version = _parse(spec, detected_from_url: detected_from_url)
2020-08-09 02:59:18 +02:00
version.nil? ? NULL : new(version, detected_from_url: detected_from_url)
2013-02-06 22:25:02 -06:00
end
2021-01-16 11:49:01 -08:00
sig { params(spec: T.any(String, Pathname), detected_from_url: T::Boolean).returns(T.nilable(String)) }
def self._parse(spec, detected_from_url:)
spec = CGI.unescape(spec.to_s) if detected_from_url
spec = Pathname.new(spec) unless spec.is_a? Pathname
spec_s = spec.to_s
stem = if spec.directory?
2021-01-16 11:49:01 -08:00
spec.basename.to_s
elsif spec_s.match?(%r{((?:sourceforge\.net|sf\.net)/.*)/download$})
2021-01-16 11:49:01 -08:00
spec.dirname.stem
elsif spec_s.match?(/\.[^a-zA-Z]+$/) # rubocop:disable Lint/DuplicateBranch
spec.basename.to_s
else
spec.stem
end
2017-05-01 22:42:57 +02:00
# date-based versioning
# e.g. ltopers-v2017-04-14.tar.gz
m = /-v?(\d{4}-\d{2}-\d{2})/.match(stem)
return m.captures.first unless m.nil?
2013-04-27 15:21:05 -05:00
# GitHub tarballs
# e.g. https://github.com/foo/bar/tarball/v1.2.3
# e.g. https://github.com/sam-github/libnet/tarball/libnet-1.1.4
# e.g. https://github.com/isaacs/npm/tarball/v0.2.5-1
# e.g. https://github.com/petdance/ack/tarball/1.93_02
2016-07-13 16:19:51 +08:00
m = %r{github\.com/.+/(?:zip|tar)ball/(?:v|\w+-)?((?:\d+[-._])+\d*)$}.match(spec_s)
return m.captures.first unless m.nil?
# e.g. https://github.com/erlang/otp/tarball/OTP_R15B01 (erlang style)
m = /[-_]([Rr]\d+[AaBb]\d*(?:-\d+)?)/.match(spec_s)
return m.captures.first unless m.nil?
# e.g. boost_1_39_0
2013-04-27 15:21:06 -05:00
m = /((?:\d+_)+\d+)$/.match(stem)
2021-01-16 11:49:01 -08:00
return T.must(m.captures.first).tr("_", ".") unless m.nil?
# e.g. foobar-4.5.1-1
# e.g. unrtf_0.20.4-1
# e.g. ruby-1.9.1-p243
m = /[-_]((?:\d+\.)*\d+\.\d+-(?:p|rc|RC)?\d+)(?:[-._](?i:bin|dist|stable|src|sources?|final|full))?$/.match(stem)
return m.captures.first unless m.nil?
# URL with no extension
# e.g. https://waf.io/waf-1.8.12
# e.g. https://codeload.github.com/gsamokovarov/jump/tar.gz/v0.7.1
m = /[-v]((?:\d+\.)*\d+)$/.match(spec_s)
return m.captures.first unless m.nil?
# e.g. lame-398-1
2020-02-23 10:23:35 -08:00
m = /-(\d+-\d+)/.match(stem)
return m.captures.first unless m.nil?
# e.g. foobar-4.5.1
2013-04-27 15:21:06 -05:00
m = /-((?:\d+\.)*\d+)$/.match(stem)
return m.captures.first unless m.nil?
2020-10-04 14:43:32 -04:00
# e.g. foobar-4.5.1.post1
m = /-((?:\d+\.)*\d+(.post\d+)?)$/.match(stem)
return m.captures.first unless m.nil?
# e.g. foobar-4.5.1b
2013-04-27 15:21:06 -05:00
m = /-((?:\d+\.)*\d+(?:[abc]|rc|RC)\d*)$/.match(stem)
return m.captures.first unless m.nil?
# e.g. foobar-4.5.0-alpha5, foobar-4.5.0-beta1, or foobar-4.50-beta
m = /-((?:\d+\.)*\d+-(?:alpha|beta|rc)\d*)$/.match(stem)
return m.captures.first unless m.nil?
# e.g. https://ftpmirror.gnu.org/libidn/libidn-1.29-win64.zip
# e.g. https://ftpmirror.gnu.org/libmicrohttpd/libmicrohttpd-0.9.17-w32.zip
m = /-(\d+\.\d+(?:\.\d+)?)-w(?:in)?(?:32|64)$/.match(stem)
return m.captures.first unless m.nil?
# Opam packages
# e.g. https://opam.ocaml.org/archives/sha.1.9+opam.tar.gz
# e.g. https://opam.ocaml.org/archives/lablgtk.2.18.3+opam.tar.gz
# e.g. https://opam.ocaml.org/archives/easy-format.1.0.2+opam.tar.gz
m = /\.(\d+\.\d+(?:\.\d+)?)\+opam$/.match(stem)
return m.captures.first unless m.nil?
# e.g. https://ftpmirror.gnu.org/mtools/mtools-4.0.18-1.i686.rpm
# e.g. https://ftpmirror.gnu.org/autogen/autogen-5.5.7-5.i386.rpm
# e.g. https://ftpmirror.gnu.org/libtasn1/libtasn1-2.8-x86.zip
# e.g. https://ftpmirror.gnu.org/libtasn1/libtasn1-2.8-x64.zip
# e.g. https://ftpmirror.gnu.org/mtools/mtools_4.0.18_i386.deb
m = /[-_](\d+\.\d+(?:\.\d+)?(?:-\d+)?)[-_.](?:i[36]86|x86|x64(?:[-_](?:32|64))?)$/.match(stem)
return m.captures.first unless m.nil?
# e.g. https://registry.npmjs.org/@angular/cli/-/cli-1.3.0-beta.1.tgz
# e.g. https://github.com/dlang/dmd/archive/v2.074.0-beta1.tar.gz
# e.g. https://github.com/dlang/dmd/archive/v2.074.0-rc1.tar.gz
# e.g. https://github.com/premake/premake-core/releases/download/v5.0.0-alpha10/premake-5.0.0-alpha10-src.zip
m = /[-.vV]?((?:\d+\.)+\d+[-_.]?(?i:alpha|beta|pre|rc)\.?\d{,2})/.match(stem)
return m.captures.first unless m.nil?
# e.g. foobar4.5.1
2013-04-27 15:21:06 -05:00
m = /((?:\d+\.)*\d+)$/.match(stem)
return m.captures.first unless m.nil?
# e.g. foobar-4.5.0-bin
m = /[-vV]((?:\d+\.)+\d+[abc]?)[-._](?i:bin|dist|stable|src|sources?|final|full)$/.match(stem)
return m.captures.first unless m.nil?
# dash version style
# e.g. http://www.antlr.org/download/antlr-3.4-complete.jar
# e.g. https://cdn.nuxeo.com/nuxeo-9.2/nuxeo-server-9.2-tomcat.zip
# e.g. https://search.maven.org/remotecontent?filepath=com/facebook/presto/presto-cli/0.181/presto-cli-0.181-executable.jar
# e.g. https://search.maven.org/remotecontent?filepath=org/fusesource/fuse-extra/fusemq-apollo-mqtt/1.3/fusemq-apollo-mqtt-1.3-uber.jar
# e.g. https://search.maven.org/remotecontent?filepath=org/apache/orc/orc-tools/1.2.3/orc-tools-1.2.3-uber.jar
m = /-((?:\d+\.)+\d+)-/.match(stem)
return m.captures.first unless m.nil?
# e.g. dash_0.5.5.1.orig.tar.gz (Debian style)
2013-04-27 15:21:06 -05:00
m = /_((?:\d+\.)+\d+[abc]?)[.]orig$/.match(stem)
return m.captures.first unless m.nil?
# e.g. https://www.openssl.org/source/openssl-0.9.8s.tar.gz
2020-02-28 14:33:34 -05:00
m = /-v?(\d[^-]+)/.match(stem)
return m.captures.first unless m.nil?
# e.g. astyle_1.23_macosx.tar.gz
2020-02-28 14:33:34 -05:00
m = /_v?(\d[^_]+)/.match(stem)
return m.captures.first unless m.nil?
# e.g. http://mirrors.jenkins-ci.org/war/1.486/jenkins.war
# e.g. https://github.com/foo/bar/releases/download/0.10.11/bar.phar
# e.g. https://github.com/clojure/clojurescript/releases/download/r1.9.293/cljs.jar
# e.g. https://github.com/fibjs/fibjs/releases/download/v0.6.1/fullsrc.zip
# e.g. https://wwwlehre.dhbw-stuttgart.de/~sschulz/WORK/E_DOWNLOAD/V_1.9/E.tgz
# e.g. https://github.com/JustArchi/ArchiSteamFarm/releases/download/2.3.2.0/ASF.zip
# e.g. https://people.gnome.org/~newren/eg/download/1.7.5.2/eg
2020-02-23 10:23:35 -08:00
m = %r{/([rvV]_?)?(\d+\.\d+(\.\d+){,2})}.match(spec_s)
2018-09-17 19:44:12 +02:00
return m.captures.second unless m.nil?
2013-01-27 22:34:53 +00:00
2018-10-03 21:03:22 +00:00
# e.g. https://www.ijg.org/files/jpegsrc.v8d.tar.gz
2013-01-27 22:34:53 +00:00
m = /\.v(\d+[a-z]?)/.match(stem)
return m.captures.first unless m.nil?
# e.g. https://secure.php.net/get/php-7.1.10.tar.bz2/from/this/mirror
m = /[-.vV]?((?:\d+\.)+\d+(?:[-_.]?(?i:alpha|beta|pre|rc)\.?\d{,2})?)/.match(spec_s)
return m.captures.first unless m.nil?
2012-07-09 22:51:10 -05:00
end
private_class_method :_parse
sig { params(val: T.any(PkgVersion, String, Version), detected_from_url: T::Boolean).void }
2020-08-09 02:59:18 +02:00
def initialize(val, detected_from_url: false)
raise TypeError, "Version value must be a string; got a #{val.class} (#{val})" unless val.respond_to?(:to_str)
2018-09-17 02:45:00 +02:00
@version = val.to_str
2020-08-09 02:59:18 +02:00
@detected_from_url = detected_from_url
end
2021-01-16 11:49:01 -08:00
sig { returns(T::Boolean) }
def detected_from_url?
2020-08-09 02:59:18 +02:00
@detected_from_url
end
2021-01-16 11:49:01 -08:00
sig { returns(T::Boolean) }
def head?
false
end
2021-01-16 11:49:01 -08:00
sig { returns(T::Boolean) }
def null?
false
end
2021-01-16 11:49:01 -08:00
sig { params(other: T.untyped).returns(T.nilable(Integer)) }
def <=>(other)
# Needed to retain API compatibility with older string comparisons
# for compiler versions, etc.
other = Version.new(other) if other.is_a? String
# Used by the *_build_version comparisons, which formerly returned Fixnum
other = Version.new(other.to_s) if other.is_a? Integer
return 1 if other.nil?
return 1 if other.respond_to?(:null?) && other.null?
other = Version.new(other.to_s) if other.is_a? Token
return unless other.is_a?(Version)
return 0 if version == other.version
return 1 if head? && !other.head?
return -1 if !head? && other.head?
return 0 if head? && other.head?
ltokens = tokens
rtokens = other.tokens
max = max(ltokens.length, rtokens.length)
l = r = 0
while l < max
a = ltokens[l] || NULL_TOKEN
b = rtokens[r] || NULL_TOKEN
if a == b
l += 1
r += 1
next
2020-11-13 17:21:51 +01:00
elsif a.numeric? && !b.numeric?
return 1 if a > NULL_TOKEN
2018-09-17 02:45:00 +02:00
l += 1
2020-11-13 17:21:51 +01:00
elsif !a.numeric? && b.numeric?
return -1 if b > NULL_TOKEN
2018-09-17 02:45:00 +02:00
r += 1
2020-11-13 17:21:51 +01:00
else
return a <=> b
end
end
0
end
alias eql? ==
2021-01-16 11:49:01 -08:00
sig { returns(T.nilable(Token)) }
def major
tokens.first
end
2021-01-16 11:49:01 -08:00
sig { returns(T.nilable(Token)) }
def minor
tokens.second
end
2021-01-16 11:49:01 -08:00
sig { returns(T.nilable(Token)) }
def patch
tokens.third
end
2021-01-16 11:49:01 -08:00
sig { returns(Version) }
def major_minor
Version.new([major, minor].compact.join("."))
end
2021-01-16 11:49:01 -08:00
sig { returns(Version) }
def major_minor_patch
Version.new([major, minor, patch].compact.join("."))
end
2021-01-16 11:49:01 -08:00
sig { returns(T::Boolean) }
2020-06-27 21:03:16 -04:00
def empty?
version.empty?
end
2021-01-16 11:49:01 -08:00
sig { returns(Integer) }
def hash
version.hash
end
2021-01-16 11:49:01 -08:00
sig { returns(Float) }
def to_f
version.to_f
end
2021-01-16 11:49:01 -08:00
sig { returns(Integer) }
def to_i
version.to_i
end
2021-01-16 11:49:01 -08:00
sig { returns(String) }
def to_s
version.dup
end
alias to_str to_s
protected
2021-01-16 11:49:01 -08:00
sig { returns(String) }
attr_reader :version
2021-01-16 11:49:01 -08:00
sig { returns(T::Array[Token]) }
def tokens
@tokens ||= tokenize
end
private
2021-01-16 11:49:01 -08:00
sig { params(a: Integer, b: Integer).returns(Integer) }
def max(a, b)
(a > b) ? a : b
end
2021-01-16 11:49:01 -08:00
sig { returns(T::Array[Token]) }
def tokenize
2021-01-16 11:49:01 -08:00
version.scan(SCAN_PATTERN).map { |token| Token.create(T.cast(token, String)) }
end
2012-07-09 22:51:10 -05:00
end
2016-06-18 20:33:03 +03:00
2020-11-05 15:19:56 -05:00
# A formula's HEAD version.
# @see https://docs.brew.sh/Formula-Cookbook#unstable-versions-head Unstable versions (head)
2020-08-09 02:59:18 +02:00
#
# @api private
2016-06-18 20:33:03 +03:00
class HeadVersion < Version
2020-10-20 12:03:48 +02:00
extend T::Sig
2021-01-16 11:49:01 -08:00
sig { returns(T.nilable(String)) }
2016-06-18 20:33:03 +03:00
attr_reader :commit
2020-08-09 02:59:18 +02:00
def initialize(*)
2016-06-18 20:33:03 +03:00
super
@commit = @version[/^HEAD-(.+)$/, 1]
end
2021-01-16 11:49:01 -08:00
sig { params(commit: T.nilable(String)).void }
2016-06-18 20:33:03 +03:00
def update_commit(commit)
@commit = commit
@version = if commit
"HEAD-#{commit}"
else
"HEAD"
end
end
2020-10-20 12:03:48 +02:00
sig { returns(T::Boolean) }
2016-06-18 20:33:03 +03:00
def head?
true
end
end