diff --git a/Library/Homebrew/ast_constants.rb b/Library/Homebrew/ast_constants.rb index 18a80c4a00..0d73f78d44 100644 --- a/Library/Homebrew/ast_constants.rb +++ b/Library/Homebrew/ast_constants.rb @@ -17,6 +17,7 @@ FORMULA_COMPONENT_PRECEDENCE_LIST = T.let([ [{ name: :head, type: :method_call }], [{ name: :stable, type: :block_call }], [{ name: :livecheck, type: :block_call }], + [{ name: :no_autobump!, type: :method_call }], [{ name: :bottle, type: :block_call }], [{ name: :pour_bottle?, type: :block_call }], [{ name: :head, type: :block_call }], diff --git a/Library/Homebrew/cask/cask.rb b/Library/Homebrew/cask/cask.rb index a48af3acb2..c1bf04a6ff 100644 --- a/Library/Homebrew/cask/cask.rb +++ b/Library/Homebrew/cask/cask.rb @@ -371,6 +371,8 @@ module Cask "url" => url, "url_specs" => url_specs, "version" => version, + "autobump" => autobump?, + "no_autobump_message" => no_autobump_message, "installed" => installed_version, "installed_time" => install_time&.to_i, "bundle_version" => bundle_long_version, diff --git a/Library/Homebrew/cask/dsl.rb b/Library/Homebrew/cask/dsl.rb index cf9f3ee108..14fc10b91f 100644 --- a/Library/Homebrew/cask/dsl.rb +++ b/Library/Homebrew/cask/dsl.rb @@ -102,6 +102,10 @@ module Cask :livecheck, :livecheck_defined?, :livecheckable?, # TODO: remove once `#livecheckable?` is removed + :no_autobump!, + :autobump?, + :no_autobump_defined?, + :no_autobump_message, :on_system_blocks_exist?, :on_system_block_min_os, :depends_on_set_in_block?, @@ -112,7 +116,7 @@ module Cask include OnSystem::MacOSAndLinux - attr_reader :cask, :token, :artifacts, :deprecation_date, :deprecation_reason, + attr_reader :cask, :token, :no_autobump_message, :artifacts, :deprecation_date, :deprecation_reason, :deprecation_replacement_cask, :deprecation_replacement_formula, :disable_date, :disable_reason, :disable_replacement_cask, :disable_replacement_formula, :on_system_block_min_os @@ -147,6 +151,8 @@ module Cask @livecheck = T.let(Livecheck.new(cask), Livecheck) @livecheck_defined = T.let(false, T::Boolean) @name = T.let([], T::Array[String]) + @autobump = T.let(true, T::Boolean) + @no_autobump_defined = T.let(false, T::Boolean) @on_system_blocks_exist = T.let(false, T::Boolean) @os = T.let(nil, T.nilable(String)) @on_system_block_min_os = T.let(nil, T.nilable(MacOSVersion)) @@ -540,6 +546,26 @@ module Cask @livecheck_defined == true end + def no_autobump!(because:) + raise ArgumentError, "`because` argument must be a string!" unless because.is_a?(String) + + if !@cask.allow_reassignment && @no_autobump_defined + raise CaskInvalidError.new(cask, "'no_autobump_defined' stanza may only appear once.") + end + + @no_autobump_defined = true + @no_autobump_message = because + @autobump = false + end + + def autobump? + @autobump == true + end + + def no_autobump_defined? + @no_autobump_defined == true + end + # Declare that a cask is no longer functional or supported. # # NOTE: A warning will be shown when trying to install this cask. diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index ab09573ae2..7a396fe8c0 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -213,6 +213,9 @@ class Formula sig { returns(T::Boolean) } attr_accessor :follow_installed_alias + sig { returns(T.nilable(String)) } + attr_reader :no_autobump_message + alias follow_installed_alias? follow_installed_alias # Whether or not to force the use of a bottle. @@ -242,6 +245,9 @@ class Formula @head = T.let(nil, T.nilable(SoftwareSpec)) @stable = T.let(nil, T.nilable(SoftwareSpec)) + @autobump = T.let(true, T::Boolean) + @no_autobump_message = T.let(nil, T.nilable(String)) + @force_bottle = T.let(force_bottle, T::Boolean) @tap = T.let(tap, T.nilable(Tap)) @@ -474,6 +480,14 @@ class Formula # @see .livecheckable? delegate livecheckable?: :"self.class" + delegate no_autobump!: :"self.class" + + delegate autobump?: :"self.class" + + delegate no_autobump_defined?: :"self.class" + + delegate no_autobump_message: :"self.class" + # Is a service specification defined for the software? # @!method service? # @see .service? @@ -2484,6 +2498,8 @@ class Formula "urls" => urls_hash, "revision" => revision, "version_scheme" => version_scheme, + "autobump" => autobump?, + "no_autobump_message" => no_autobump_message, "bottle" => {}, "pour_bottle_only_if" => self.class.pour_bottle_only_if&.to_s, "keg_only" => keg_only?, @@ -4182,6 +4198,25 @@ class Formula @livecheck.instance_eval(&block) end + # Method that excludes the formula from the autobump list. + # + # @api public + sig { params(because: String).returns(T.untyped) } + def no_autobump!(because:) + @no_autobump_defined = T.let(true, T.nilable(T::Boolean)) + @no_autobump_message = T.let(because, T.nilable(String)) + @autobump = T.let(false, T.nilable(T::Boolean)) + end + + sig { returns(T::Boolean) } + def autobump? = @autobump == true + + sig { returns(T::Boolean) } + def no_autobump_defined? = @no_autobump_defined == true + + sig { returns(T.nilable(String)) } + attr_reader :no_autobump_message + # Service can be used to define services. # This method evaluates the DSL specified in the service block of the # {Formula} (if it exists) and sets the instance variables of a Service diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 5dd9e2ec4c..e948a26800 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -291,6 +291,10 @@ module Formulary end end + if (no_autobump_msg = json_formula["no_autobump_msg"]) + no_autobump! because: no_autobump_msg + end + bottles_stable = json_formula["bottle"]["stable"].presence if bottles_stable diff --git a/Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi b/Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi index efe31aafaa..432c8570d4 100644 --- a/Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi +++ b/Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi @@ -30,6 +30,9 @@ class Cask::Cask sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) } def auto_updates(*args, &block); end + sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) } + def autobump?(*args, &block); end + sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) } def bash_completion(*args, &block); end @@ -141,6 +144,9 @@ class Cask::Cask sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) } def name(*args, &block); end + sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) } + def no_autobump_msg(*args, &block); end + sig { params(args: T.untyped, block: T.untyped).returns(T.nilable(MacOSVersion)) } def on_system_block_min_os(*args, &block); end diff --git a/Library/Homebrew/sorbet/rbi/dsl/formula.rbi b/Library/Homebrew/sorbet/rbi/dsl/formula.rbi index d8b7825bdb..315e5a687a 100644 --- a/Library/Homebrew/sorbet/rbi/dsl/formula.rbi +++ b/Library/Homebrew/sorbet/rbi/dsl/formula.rbi @@ -6,6 +6,9 @@ class Formula + sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) } + def autobump?(*args, &block); end + sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) } def allow_network_access!(*args, &block); end diff --git a/Library/Homebrew/test/cask/dsl_spec.rb b/Library/Homebrew/test/cask/dsl_spec.rb index b799279c02..1d9b5cb5a3 100644 --- a/Library/Homebrew/test/cask/dsl_spec.rb +++ b/Library/Homebrew/test/cask/dsl_spec.rb @@ -155,6 +155,24 @@ RSpec.describe Cask::DSL, :cask do end end + describe "no_autobump! stanze" do + it "returns true if no_autobump! is not set" do + expect(cask.autobump?).to eq(true) + end + + context "when no_autobump! is set" do + let(:cask) do + Cask::Cask.new("checksum-cask") do + no_autobump! because: "some reason" + end + end + it "returns false" do + expect(cask.autobump?).to eq(false) + expect(cask.no_autobump_message).to eq("some reason") + end + end + end + describe "language stanza" do context "when language is set explicitly" do subject(:cask) do diff --git a/Library/Homebrew/test/support/fixtures/cask/everything.json b/Library/Homebrew/test/support/fixtures/cask/everything.json index d3d981258f..ddb9889084 100644 --- a/Library/Homebrew/test/support/fixtures/cask/everything.json +++ b/Library/Homebrew/test/support/fixtures/cask/everything.json @@ -16,6 +16,8 @@ "user_agent": ":fake" }, "version": "1.2.3", + "autobump": true, + "no_autobump_msg": null, "installed": null, "installed_time": null, "bundle_version": null,