From 77e74e7e699854664e844fcc5a0447538d16934b Mon Sep 17 00:00:00 2001 From: nandahkrishna Date: Mon, 16 Mar 2020 01:37:49 +0530 Subject: [PATCH] Adding livecheck Formula DSL --- Library/Homebrew/.rubocop.yml | 2 + Library/Homebrew/formula.rb | 38 ++++++++++++++++ Library/Homebrew/livecheck.rb | 59 +++++++++++++++++++++++++ Library/Homebrew/test/formula_spec.rb | 37 ++++++++++++++++ Library/Homebrew/test/livecheck_spec.rb | 57 ++++++++++++++++++++++++ 5 files changed, 193 insertions(+) create mode 100644 Library/Homebrew/livecheck.rb create mode 100644 Library/Homebrew/test/livecheck_spec.rb diff --git a/Library/Homebrew/.rubocop.yml b/Library/Homebrew/.rubocop.yml index 223f857a05..bdb40a9b91 100644 --- a/Library/Homebrew/.rubocop.yml +++ b/Library/Homebrew/.rubocop.yml @@ -46,6 +46,8 @@ Metrics/AbcSize: Metrics/BlockLength: Enabled: true Max: 1100 + Exclude: + - 'test/formula_spec.rb' Metrics/BlockNesting: Enabled: true Max: 5 diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 8260d9af28..f431b19dfa 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -12,6 +12,7 @@ require "build_environment" require "build_options" require "formulary" require "software_spec" +require "livecheck" require "install_renamed" require "pkg_version" require "keg" @@ -353,6 +354,16 @@ class Formula # @see .homepage= delegate homepage: :"self.class" + # The livecheck specification for the software. + # @method livecheck + # @see .livecheck= + delegate livecheck: :"self.class" + + # Is a livecheck specification defined for the software? + # @method livecheckable? + # @see .livecheckable? + delegate livecheckable?: :"self.class" + # The version for the currently active {SoftwareSpec}. # The version is autodetected from the URL and/or tag so only needs to be # declared if it cannot be autodetected correctly. @@ -2186,6 +2197,13 @@ class Formula #
homepage "https://www.example.com"
attr_rw :homepage + # Whether a livecheck specification is defined or not. + # It returns true when a livecheck block is present in the {Formula} and + # false otherwise, and is used by livecheck. + def livecheckable? + @livecheckable == true + end + # The `:startup` attribute set by {.plist_options}. # @private attr_reader :plist_startup @@ -2628,6 +2646,26 @@ class Formula define_method(:test, &block) end + # @!attribute [w] livecheck + # Livecheck can be used to check for newer versions of the software. + # This method evaluates the DSL specified in the livecheck block of the + # {Formula} (if it exists) and sets the instance variables of a Livecheck + # object accordingly. This is used by brew livecheck to check for newer + # versions of the software. + # + #
livecheck do
+    #   skip "Not maintained"
+    #   url "https://example.com/foo/releases"
+    #   regex /foo-(\d+(?:\.\d+)+)\.tar/
+    # end
+ def livecheck(&block) + @livecheck ||= Livecheck.new + return @livecheck unless block_given? + + @livecheckable = true + @livecheck.instance_eval(&block) + end + # Defines whether the {Formula}'s bottle can be used on the given Homebrew # installation. # diff --git a/Library/Homebrew/livecheck.rb b/Library/Homebrew/livecheck.rb new file mode 100644 index 0000000000..f2bf621f1e --- /dev/null +++ b/Library/Homebrew/livecheck.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +# Livecheck can be used to check for newer versions of the software. +# The livecheck DSL specified in the formula is evaluated the methods +# of this class, which set the instance variables accordingly. The +# information is used by brew livecheck when checking for newer versions +# of the software. +class Livecheck + # The reason for skipping livecheck for the formula. + # e.g. `Not maintained` + attr_reader :skip_msg + + def initialize + @regex = nil + @skip = false + @skip_msg = nil + @url = nil + end + + # Sets the regex instance variable to the argument given, returns the + # regex instance variable when no argument is given. + def regex(pattern = nil) + return @regex if pattern.nil? + + @regex = pattern + end + + # Sets the skip instance variable to true, indicating that livecheck + # must be skipped for the formula. If an argument is given and present, + # its value is assigned to the skip_msg instance variable, else nil is + # assigned. + def skip(skip_msg = nil) + @skip = true + @skip_msg = skip_msg.presence + end + + # Should livecheck be skipped for the formula? + def skip? + @skip + end + + # Sets the url instance variable to the argument given, returns the url + # instance variable when no argument is given. + def url(val = nil) + return @url if val.nil? + + @url = val + end + + # Returns a Hash of all instance variable values. + def to_hash + { + "regex" => @regex, + "skip" => @skip, + "skip_msg" => @skip_msg, + "url" => @url, + } + end +end diff --git a/Library/Homebrew/test/formula_spec.rb b/Library/Homebrew/test/formula_spec.rb index 43b0c4b2e5..6daf45f1ab 100644 --- a/Library/Homebrew/test/formula_spec.rb +++ b/Library/Homebrew/test/formula_spec.rb @@ -698,6 +698,43 @@ describe Formula do expect(f1.test_fixtures("foo")).to eq(Pathname.new("#{HOMEBREW_LIBRARY_PATH}/test/support/fixtures/foo")) end + specify "#livecheck" do + f = formula do + url "https://brew.sh/test-1.0.tbz" + livecheck do + skip "foo" + url "https://brew.sh/test/releases" + regex(/test-(\d+(?:\.\d+)+)\.tbz/) + end + end + + expect(f.livecheck.skip?).to be true + expect(f.livecheck.skip_msg).to eq("foo") + expect(f.livecheck.url).to eq("https://brew.sh/test/releases") + expect(f.livecheck.regex).to eq(/test-(\d+(?:\.\d+)+)\.tbz/) + end + + describe "#livecheckable?" do + specify "no livecheck block defined" do + f = formula do + url "https://brew.sh/test-1.0.tbz" + end + + expect(f.livecheckable?).to be false + end + + specify "livecheck block defined" do + f = formula do + url "https://brew.sh/test-1.0.tbz" + livecheck do + regex(/test-(\d+(?:.\d+)+).tbz/) + end + end + + expect(f.livecheckable?).to be true + end + end + specify "dependencies" do f1 = formula "f1" do url "f1-1.0" diff --git a/Library/Homebrew/test/livecheck_spec.rb b/Library/Homebrew/test/livecheck_spec.rb new file mode 100644 index 0000000000..f975548cda --- /dev/null +++ b/Library/Homebrew/test/livecheck_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require "livecheck" + +describe Livecheck do + subject(:livecheckable) { described_class.new } + + describe "#regex" do + it "returns nil if unset" do + expect(livecheckable.regex).to be nil + end + + it "returns the Regex if set" do + livecheckable.regex(/foo/) + expect(livecheckable.regex).to eq(/foo/) + end + end + + describe "#skip" do + it "sets the instance variable skip to true and skip_msg to nil when the argument is not present" do + livecheckable.skip + expect(livecheckable.instance_variable_get(:@skip)).to be true + expect(livecheckable.instance_variable_get(:@skip_msg)).to be nil + end + + it "sets the instance variable skip to true and skip_msg to the argument when present" do + livecheckable.skip("foo") + expect(livecheckable.instance_variable_get(:@skip)).to be true + expect(livecheckable.instance_variable_get(:@skip_msg)).to eq("foo") + end + end + + describe "#skip?" do + it "returns the value of the instance variable skip" do + expect(livecheckable.skip?).to be false + livecheckable.skip + expect(livecheckable.skip?).to be true + end + end + + describe "#url" do + it "returns nil if unset" do + expect(livecheckable.url).to be nil + end + + it "returns the URL if set" do + livecheckable.url("foo") + expect(livecheckable.url).to eq("foo") + end + end + + describe "#to_hash" do + it "returns a Hash of all instance variables" do + expect(livecheckable.to_hash).to eq({ "regex"=>nil, "skip"=>false, "skip_msg"=>nil, "url"=>nil }) + end + end +end