From 0feb4532ff206083c08d9e20739b283b19fe1f63 Mon Sep 17 00:00:00 2001 From: Seeker Date: Sat, 1 Aug 2020 16:38:31 -0700 Subject: [PATCH 01/11] version: add major, minor, patch methods --- Library/Homebrew/version.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Library/Homebrew/version.rb b/Library/Homebrew/version.rb index 50f1b67082..c5e225eeac 100644 --- a/Library/Homebrew/version.rb +++ b/Library/Homebrew/version.rb @@ -469,6 +469,26 @@ class Version end alias eql? == + def major + tokens[0] + end + + def minor + tokens[1] + end + + def patch + tokens[2] + end + + def major_minor + Version.new([major, minor].reject(&:nil?).join(".")) + end + + def major_minor_patch + Version.new([major, minor, patch].reject(&:nil?).join(".")) + end + def empty? version.empty? end From 919e94bb9273a48ade57a2be184e9c3ee5e8dc07 Mon Sep 17 00:00:00 2001 From: Seeker Date: Sat, 1 Aug 2020 17:25:56 -0700 Subject: [PATCH 02/11] test/version_spec: add major/minor/patch examples --- Library/Homebrew/test/version_spec.rb | 70 +++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/Library/Homebrew/test/version_spec.rb b/Library/Homebrew/test/version_spec.rb index d83b25d869..e255fe9ef0 100644 --- a/Library/Homebrew/test/version_spec.rb +++ b/Library/Homebrew/test/version_spec.rb @@ -276,6 +276,76 @@ describe Version do expect(v2.to_str).to eq("HEAD-ffffff") end + describe "#major" do + it "returns major version token" do + expect(described_class.create("1").major).to be == Version::Token.create("1") + expect(described_class.create("1.2").major).to be == Version::Token.create("1") + expect(described_class.create("1.2.3").major).to be == Version::Token.create("1") + expect(described_class.create("1.2.3alpha").major).to be == Version::Token.create("1") + expect(described_class.create("1.2.3alpha4").major).to be == Version::Token.create("1") + expect(described_class.create("1.2.3beta4").major).to be == Version::Token.create("1") + expect(described_class.create("1.2.3pre4").major).to be == Version::Token.create("1") + expect(described_class.create("1.2.3rc4").major).to be == Version::Token.create("1") + expect(described_class.create("1.2.3-p4").major).to be == Version::Token.create("1") + end + end + + describe "#minor" do + it "returns minor version token" do + expect(described_class.create("1").minor).to be nil + expect(described_class.create("1.2").minor).to be == Version::Token.create("2") + expect(described_class.create("1.2.3").minor).to be == Version::Token.create("2") + expect(described_class.create("1.2.3alpha").minor).to be == Version::Token.create("2") + expect(described_class.create("1.2.3alpha4").minor).to be == Version::Token.create("2") + expect(described_class.create("1.2.3beta4").minor).to be == Version::Token.create("2") + expect(described_class.create("1.2.3pre4").minor).to be == Version::Token.create("2") + expect(described_class.create("1.2.3rc4").minor).to be == Version::Token.create("2") + expect(described_class.create("1.2.3-p4").minor).to be == Version::Token.create("2") + end + end + + describe "#patch" do + it "returns patch version token" do + expect(described_class.create("1").patch).to be nil + expect(described_class.create("1.2").patch).to be nil + expect(described_class.create("1.2.3").patch).to be == Version::Token.create("3") + expect(described_class.create("1.2.3alpha").patch).to be == Version::Token.create("3") + expect(described_class.create("1.2.3alpha4").patch).to be == Version::Token.create("3") + expect(described_class.create("1.2.3beta4").patch).to be == Version::Token.create("3") + expect(described_class.create("1.2.3pre4").patch).to be == Version::Token.create("3") + expect(described_class.create("1.2.3rc4").patch).to be == Version::Token.create("3") + expect(described_class.create("1.2.3-p4").patch).to be == Version::Token.create("3") + end + end + + describe "#major_minor" do + it "returns major.minor version" do + expect(described_class.create("1").major_minor).to be == described_class.create("1") + expect(described_class.create("1.2").major_minor).to be == described_class.create("1.2") + expect(described_class.create("1.2.3").major_minor).to be == described_class.create("1.2") + expect(described_class.create("1.2.3alpha").major_minor).to be == described_class.create("1.2") + expect(described_class.create("1.2.3alpha4").major_minor).to be == described_class.create("1.2") + expect(described_class.create("1.2.3beta4").major_minor).to be == described_class.create("1.2") + expect(described_class.create("1.2.3pre4").major_minor).to be == described_class.create("1.2") + expect(described_class.create("1.2.3rc4").major_minor).to be == described_class.create("1.2") + expect(described_class.create("1.2.3-p4").major_minor).to be == described_class.create("1.2") + end + end + + describe "#major_minor_patch" do + it "returns major.minor.patch version" do + expect(described_class.create("1").major_minor_patch).to be == described_class.create("1") + expect(described_class.create("1.2").major_minor_patch).to be == described_class.create("1.2") + expect(described_class.create("1.2.3").major_minor_patch).to be == described_class.create("1.2.3") + expect(described_class.create("1.2.3alpha").major_minor_patch).to be == described_class.create("1.2.3") + expect(described_class.create("1.2.3alpha4").major_minor_patch).to be == described_class.create("1.2.3") + expect(described_class.create("1.2.3beta4").major_minor_patch).to be == described_class.create("1.2.3") + expect(described_class.create("1.2.3pre4").major_minor_patch).to be == described_class.create("1.2.3") + expect(described_class.create("1.2.3rc4").major_minor_patch).to be == described_class.create("1.2.3") + expect(described_class.create("1.2.3-p4").major_minor_patch).to be == described_class.create("1.2.3") + end + end + describe "::parse" do it "returns a NULL version when the URL cannot be parsed" do expect(described_class.parse("https://brew.sh/blah.tar")).to be_null From f2112d67618fdff48dc6bba410c08e337f81774b Mon Sep 17 00:00:00 2001 From: Seeker Date: Tue, 11 Aug 2020 12:22:14 -0700 Subject: [PATCH 03/11] version: add helper methods to Token class --- Library/Homebrew/version.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Library/Homebrew/version.rb b/Library/Homebrew/version.rb index c5e225eeac..909ed38006 100644 --- a/Library/Homebrew/version.rb +++ b/Library/Homebrew/version.rb @@ -46,6 +46,18 @@ class Version "#<#{self.class.name} #{value.inspect}>" end + def hash + value.hash + end + + def to_f + value.to_f + end + + def to_i + value.to_i + end + def to_s value.to_s end @@ -75,6 +87,10 @@ class Version end end + def null? + true + end + def inspect "#<#{self.class.name}>" end From 972b924cea057e19582488aef229207e13c3b955 Mon Sep 17 00:00:00 2001 From: Seeker Date: Tue, 11 Aug 2020 12:23:07 -0700 Subject: [PATCH 04/11] version: allow versions to be compared against tokens --- Library/Homebrew/test/version_spec.rb | 4 ++++ Library/Homebrew/version.rb | 1 + 2 files changed, 5 insertions(+) diff --git a/Library/Homebrew/test/version_spec.rb b/Library/Homebrew/test/version_spec.rb index e255fe9ef0..60b98c2179 100644 --- a/Library/Homebrew/test/version_spec.rb +++ b/Library/Homebrew/test/version_spec.rb @@ -183,6 +183,10 @@ describe Version do expect(described_class.create("1")).to be == 1 end + it "can be compared against tokens" do + expect(described_class.create("1")).to be == Version::Token.create("1") + end + specify "comparison returns nil for non-version" do v = described_class.create("1.0") expect(v <=> Object.new).to be nil diff --git a/Library/Homebrew/version.rb b/Library/Homebrew/version.rb index 909ed38006..1b337377c9 100644 --- a/Library/Homebrew/version.rb +++ b/Library/Homebrew/version.rb @@ -446,6 +446,7 @@ class Version other = Version.new(other.to_s) if other.is_a? Integer return 1 if other.nil? + other = Version.new(other.to_s) if other.is_a? Token return 1 if other.respond_to?(:null?) && other.null? return unless other.is_a?(Version) return 0 if version == other.version From e27f7b0ed101608fbcb5e36e3cef77f3ffbda40d Mon Sep 17 00:00:00 2001 From: Seeker Date: Tue, 11 Aug 2020 12:40:35 -0700 Subject: [PATCH 05/11] audit: use version token helper methods --- Library/Homebrew/dev-cmd/audit.rb | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index c8cf5f8039..ab667f09b5 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -261,9 +261,8 @@ module Homebrew !(versioned_formulae = formula.versioned_formulae).empty? versioned_aliases = formula.aliases.grep(/.@\d/) _, last_alias_version = versioned_formulae.map(&:name).last.split("@") - major, minor, = formula.version.to_s.split(".") - alias_name_major = "#{formula.name}@#{major}" - alias_name_major_minor = "#{alias_name_major}.#{minor}" + alias_name_major = "#{formula.name}@#{formula.version.major}" + alias_name_major_minor = "#{alias_name_major}.#{formula.version.minor}" alias_name = if last_alias_version.split(".").length == 1 alias_name_major else @@ -488,11 +487,7 @@ module Homebrew return unless formula.name == "postgresql" return unless @core_tap - major_version = formula.version - .to_s - .split(".") - .first - .to_i + major_version = formula.version.major.to_i previous_major_version = major_version - 1 previous_formula_name = "postgresql@#{previous_major_version}" begin @@ -689,7 +684,7 @@ module Homebrew }.freeze # version_prefix = stable_version_string.sub(/\d+$/, "") - # version_prefix = stable_version_string.split(".")[0..1].join(".") + # version_prefix = stable.version.major_minor def audit_specs problem "Head-only (no stable download)" if head_only?(formula) @@ -753,11 +748,9 @@ module Homebrew stable_version_string = stable.version.to_s stable_url_version = Version.parse(stable.url) - _, stable_url_minor_version, = stable_url_version.to_s - .split(".", 3) - .map(&:to_i) + stable_url_minor_version = stable_url_version.minor.to_i - formula_suffix = stable_version_string.split(".").last.to_i + formula_suffix = stable.version.patch.to_i throttled_rate = THROTTLED_FORMULAE[formula.name] if throttled_rate && formula_suffix.modulo(throttled_rate).nonzero? problem "should only be updated every #{throttled_rate} releases on multiples of #{throttled_rate}" @@ -771,7 +764,7 @@ module Homebrew problem "Stable version URLs should not contain #{matched}" when %r{download\.gnome\.org/sources}, %r{ftp\.gnome\.org/pub/GNOME/sources}i - version_prefix = stable_version_string.split(".")[0..1].join(".") + version_prefix = stable.version.major_minor return if GNOME_DEVEL_ALLOWLIST[formula.name] == version_prefix return if stable_url_version < Version.create("1.0") return if stable_url_minor_version.even? From 266a944bb5dbe189eb284ce786133717a4a2113d Mon Sep 17 00:00:00 2001 From: Seeker Date: Tue, 11 Aug 2020 13:01:10 -0700 Subject: [PATCH 06/11] version/null: add major, minor, patch methods --- Library/Homebrew/version/null.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Library/Homebrew/version/null.rb b/Library/Homebrew/version/null.rb index 075c148087..b15546a6cb 100644 --- a/Library/Homebrew/version/null.rb +++ b/Library/Homebrew/version/null.rb @@ -37,6 +37,26 @@ class Version alias_method :requires_sse42?, :requires_nehalem_cpu? alias_method :requires_popcnt?, :requires_nehalem_cpu? + def major + NULL_TOKEN + end + + def minor + NULL_TOKEN + end + + def patch + NULL_TOKEN + end + + def major_minor + self + end + + def major_minor_patch + self + end + def to_f Float::NAN end From 51bc9ae3d907738643488a00e9b116c036944a3b Mon Sep 17 00:00:00 2001 From: Seeker Date: Tue, 11 Aug 2020 13:01:54 -0700 Subject: [PATCH 07/11] pkg_version: delegate major, minor, patch methods to :version --- Library/Homebrew/pkg_version.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Library/Homebrew/pkg_version.rb b/Library/Homebrew/pkg_version.rb index 5b2e7522ef..5523269fc5 100644 --- a/Library/Homebrew/pkg_version.rb +++ b/Library/Homebrew/pkg_version.rb @@ -4,11 +4,20 @@ require "version" class PkgVersion include Comparable + extend Forwardable RX = /\A(.+?)(?:_(\d+))?\z/.freeze attr_reader :version, :revision + delegate [ + :major, + :minor, + :patch, + :major_minor, + :major_minor_patch, + ] => :version + def self.parse(path) _, version, revision = *path.match(RX) version = Version.create(version) From e9b6a6df4bd6d04ecef771102c7ab257b0ac3079 Mon Sep 17 00:00:00 2001 From: Seeker Date: Tue, 11 Aug 2020 13:13:53 -0700 Subject: [PATCH 08/11] test/pkg_version_spec: add version token examples --- Library/Homebrew/test/pkg_version_spec.rb | 42 +++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Library/Homebrew/test/pkg_version_spec.rb b/Library/Homebrew/test/pkg_version_spec.rb index 474485ffe3..ee8bedd610 100644 --- a/Library/Homebrew/test/pkg_version_spec.rb +++ b/Library/Homebrew/test/pkg_version_spec.rb @@ -85,4 +85,46 @@ describe PkgVersion do expect(p1.hash).not_to eq(p4.hash) end end + + describe "#version" do + it "returns package version" do + expect(described_class.parse("1.2.3_4").version).to be == Version.create("1.2.3") + end + end + + describe "#revision" do + it "returns package revision" do + expect(described_class.parse("1.2.3_4").revision).to be == 4 + end + end + + describe "#major" do + it "returns major version token" do + expect(described_class.parse("1.2.3_4").major).to be == Version::Token.create("1") + end + end + + describe "#minor" do + it "returns minor version token" do + expect(described_class.parse("1.2.3_4").minor).to be == Version::Token.create("2") + end + end + + describe "#patch" do + it "returns patch version token" do + expect(described_class.parse("1.2.3_4").patch).to be == Version::Token.create("3") + end + end + + describe "#major_minor" do + it "returns major.minor version" do + expect(described_class.parse("1.2.3_4").major_minor).to be == Version.create("1.2") + end + end + + describe "#major_minor_patch" do + it "returns major.minor.patch version" do + expect(described_class.parse("1.2.3_4").major_minor_patch).to be == Version.create("1.2.3") + end + end end From f904cc2aea02f1ddd906e3cd62d0964d88d401ba Mon Sep 17 00:00:00 2001 From: Seeker Date: Tue, 11 Aug 2020 13:15:50 -0700 Subject: [PATCH 09/11] pkg_version: disable rubocop hash alignment --- Library/Homebrew/pkg_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Homebrew/pkg_version.rb b/Library/Homebrew/pkg_version.rb index 5523269fc5..b4b1379653 100644 --- a/Library/Homebrew/pkg_version.rb +++ b/Library/Homebrew/pkg_version.rb @@ -10,7 +10,7 @@ class PkgVersion attr_reader :version, :revision - delegate [ + delegate [ # rubocop:disable Layout/HashAlignment :major, :minor, :patch, From fb96ccf4c805ead6335b8c10419115a1e097b799 Mon Sep 17 00:00:00 2001 From: Seeker Date: Tue, 11 Aug 2020 13:58:48 -0700 Subject: [PATCH 10/11] version: allow versions to be compared against NULL_TOKEN --- Library/Homebrew/test/version_spec.rb | 5 +++++ Library/Homebrew/version.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/test/version_spec.rb b/Library/Homebrew/test/version_spec.rb index 60b98c2179..51a8641b82 100644 --- a/Library/Homebrew/test/version_spec.rb +++ b/Library/Homebrew/test/version_spec.rb @@ -184,9 +184,14 @@ describe Version do end it "can be compared against tokens" do + expect(described_class.create("2.1.0-p194")).to be > Version::Token.create("2") expect(described_class.create("1")).to be == Version::Token.create("1") end + it "can be compared against Version::NULL_TOKEN" do + expect(described_class.create("2.1.0-p194")).to be > Version::NULL_TOKEN + end + specify "comparison returns nil for non-version" do v = described_class.create("1.0") expect(v <=> Object.new).to be nil diff --git a/Library/Homebrew/version.rb b/Library/Homebrew/version.rb index 1b337377c9..b3312e3277 100644 --- a/Library/Homebrew/version.rb +++ b/Library/Homebrew/version.rb @@ -445,9 +445,9 @@ class Version # 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 1 if other.respond_to?(:null?) && other.null? return unless other.is_a?(Version) return 0 if version == other.version return 1 if head? && !other.head? From 1aceab06fba9322a7450d73426f06b2cf32fe3af Mon Sep 17 00:00:00 2001 From: Seeker Date: Wed, 12 Aug 2020 10:14:11 -0700 Subject: [PATCH 11/11] version: make major, minor, patch more idiomatic --- Library/Homebrew/version.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Library/Homebrew/version.rb b/Library/Homebrew/version.rb index b3312e3277..589bb7a304 100644 --- a/Library/Homebrew/version.rb +++ b/Library/Homebrew/version.rb @@ -487,23 +487,23 @@ class Version alias eql? == def major - tokens[0] + tokens.first end def minor - tokens[1] + tokens.second end def patch - tokens[2] + tokens.third end def major_minor - Version.new([major, minor].reject(&:nil?).join(".")) + Version.new([major, minor].compact.join(".")) end def major_minor_patch - Version.new([major, minor, patch].reject(&:nil?).join(".")) + Version.new([major, minor, patch].compact.join(".")) end def empty?