mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
Merge pull request #19786 from botantony/autobump
formula/cask: add `no_autobump` method
This commit is contained in:
commit
335933f67c
@ -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 }],
|
||||
|
7
Library/Homebrew/autobump_constants.rb
Normal file
7
Library/Homebrew/autobump_constants.rb
Normal file
@ -0,0 +1,7 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
# TODO: add more reasons here
|
||||
NO_AUTOBUMP_REASONS_LIST = T.let({
|
||||
incompatible_version_format: "incompatible version format",
|
||||
}.freeze, T::Hash[Symbol, String])
|
@ -371,6 +371,9 @@ module Cask
|
||||
"url" => url,
|
||||
"url_specs" => url_specs,
|
||||
"version" => version,
|
||||
"autobump" => autobump?,
|
||||
"no_autobump_message" => no_autobump_message,
|
||||
"skip_livecheck" => livecheck.skip?,
|
||||
"installed" => installed_version,
|
||||
"installed_time" => install_time&.to_i,
|
||||
"bundle_version" => bundle_long_version,
|
||||
|
@ -1,6 +1,7 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "autobump_constants"
|
||||
require "locale"
|
||||
require "lazy_object"
|
||||
require "livecheck"
|
||||
@ -102,6 +103,9 @@ module Cask
|
||||
:livecheck,
|
||||
:livecheck_defined?,
|
||||
:livecheckable?, # TODO: remove once `#livecheckable?` is removed
|
||||
:no_autobump!,
|
||||
:autobump?,
|
||||
: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,37 @@ module Cask
|
||||
@livecheck_defined == true
|
||||
end
|
||||
|
||||
# Excludes the cask from autobump list.
|
||||
#
|
||||
# TODO: limit this method to the official taps only (f.e. raise
|
||||
# an error if `!tap.official?`)
|
||||
#
|
||||
# @api public
|
||||
sig { params(because: T.any(String, Symbol)).void }
|
||||
def no_autobump!(because:)
|
||||
if because.is_a?(Symbol) && !NO_AUTOBUMP_REASONS_LIST.key?(because)
|
||||
raise ArgumentError, "'because' argument should use valid symbol or a string!"
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
# Is the cask in autobump list?
|
||||
def autobump?
|
||||
@autobump == true
|
||||
end
|
||||
|
||||
# Is no_autobump! method defined?
|
||||
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.
|
||||
|
@ -81,8 +81,8 @@ module Homebrew
|
||||
Whoops, the #{cask.token} cask has its version update
|
||||
pull requests automatically opened by BrewTestBot every ~3 hours!
|
||||
We'd still love your contributions, though, so try another one
|
||||
that's not in the autobump list:
|
||||
#{Formatter.url("#{cask.tap.remote}/blob/master/.github/autobump.txt")}
|
||||
that is excluded from autobump list (i.e. it has 'no_autobump!'
|
||||
method or 'livecheck' block with 'skip'.)
|
||||
EOS
|
||||
|
||||
odie "You have too many PRs open: close or merge some first!" if GitHub.too_many_open_prs?(cask.tap)
|
||||
|
@ -117,8 +117,8 @@ module Homebrew
|
||||
Whoops, the #{formula.name} formula has its version update
|
||||
pull requests automatically opened by BrewTestBot every ~3 hours!
|
||||
We'd still love your contributions, though, so try another one
|
||||
that's not in the autobump list:
|
||||
#{Formatter.url("#{tap.remote}/blob/master/.github/autobump.txt")}
|
||||
that is excluded from autobump list (i.e. it has 'no_autobump!'
|
||||
method or 'livecheck' block with 'skip'.)
|
||||
EOS
|
||||
|
||||
odie "You have too many PRs open: close or merge some first!" if GitHub.too_many_open_prs?(tap)
|
||||
|
@ -58,7 +58,7 @@ module Homebrew
|
||||
|
||||
conflicts "--cask", "--formula"
|
||||
conflicts "--tap=", "--installed"
|
||||
conflicts "--tap=", "--no-auto"
|
||||
conflicts "--tap=", "--no-autobump"
|
||||
conflicts "--eval-all", "--installed"
|
||||
conflicts "--installed", "--auto"
|
||||
conflicts "--no-pull-requests", "--open-pr"
|
||||
|
@ -100,10 +100,7 @@ module Homebrew
|
||||
tap = formula_or_cask.tap
|
||||
next false if tap.nil?
|
||||
|
||||
autobump_lists[tap] ||= begin
|
||||
autobump_path = tap.path/".github/autobump.txt"
|
||||
autobump_path.exist? ? autobump_path.readlines.map(&:strip) : []
|
||||
end
|
||||
autobump_lists[tap] ||= tap.autobump
|
||||
|
||||
name = formula_or_cask.respond_to?(:token) ? formula_or_cask.token : formula_or_cask.name
|
||||
next unless autobump_lists[tap].include?(name)
|
||||
|
@ -1,6 +1,7 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "autobump_constants"
|
||||
require "cache_store"
|
||||
require "did_you_mean"
|
||||
require "formula_support"
|
||||
@ -213,6 +214,13 @@ class Formula
|
||||
sig { returns(T::Boolean) }
|
||||
attr_accessor :follow_installed_alias
|
||||
|
||||
# Message that explains why the formula was excluded from autobump list.
|
||||
# Returns `nil` if no message is specified.
|
||||
#
|
||||
# @see .no_autobump!
|
||||
sig { returns(T.nilable(T.any(String, Symbol))) }
|
||||
attr_reader :no_autobump_message
|
||||
|
||||
alias follow_installed_alias? follow_installed_alias
|
||||
|
||||
# Whether or not to force the use of a bottle.
|
||||
@ -242,6 +250,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(T.any(String, Symbol)))
|
||||
|
||||
@force_bottle = T.let(force_bottle, T::Boolean)
|
||||
|
||||
@tap = T.let(tap, T.nilable(Tap))
|
||||
@ -474,6 +485,23 @@ class Formula
|
||||
# @see .livecheckable?
|
||||
delegate livecheckable?: :"self.class"
|
||||
|
||||
# Exclude the formula from autobump list.
|
||||
# @!method no_autobump!
|
||||
# @see .no_autobump!
|
||||
delegate no_autobump!: :"self.class"
|
||||
|
||||
# Is the formula in autobump list?
|
||||
# @!method autobump?
|
||||
# @see .autobump?
|
||||
delegate autobump?: :"self.class"
|
||||
|
||||
# Is no_autobump! method defined?
|
||||
# @!method no_autobump_defined?
|
||||
# @see .no_autobump_defined?
|
||||
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 +2512,9 @@ class Formula
|
||||
"urls" => urls_hash,
|
||||
"revision" => revision,
|
||||
"version_scheme" => version_scheme,
|
||||
"autobump" => autobump?,
|
||||
"no_autobump_message" => no_autobump_message,
|
||||
"skip_livecheck" => livecheck.skip?,
|
||||
"bottle" => {},
|
||||
"pour_bottle_only_if" => self.class.pour_bottle_only_if&.to_s,
|
||||
"keg_only" => keg_only?,
|
||||
@ -4182,6 +4213,40 @@ class Formula
|
||||
@livecheck.instance_eval(&block)
|
||||
end
|
||||
|
||||
# Method that excludes the formula from the autobump list.
|
||||
#
|
||||
# TODO: limit this method to the official taps only (f.e. raise
|
||||
# an error if `!tap.official?`)
|
||||
#
|
||||
# @api public
|
||||
sig { params(because: T.any(String, Symbol)).void }
|
||||
def no_autobump!(because:)
|
||||
if because.is_a?(Symbol) && !NO_AUTOBUMP_REASONS_LIST.key?(because)
|
||||
raise ArgumentError, "'because' argument should use valid symbol or a string!"
|
||||
end
|
||||
|
||||
@no_autobump_defined = T.let(true, T.nilable(T::Boolean))
|
||||
@no_autobump_message = T.let(because, T.nilable(T.any(String, Symbol)))
|
||||
@autobump = T.let(false, T.nilable(T::Boolean))
|
||||
end
|
||||
|
||||
# Is the formula in autobump list?
|
||||
sig { returns(T::Boolean) }
|
||||
def autobump?
|
||||
@autobump != false # @autobump may be `nil`
|
||||
end
|
||||
|
||||
# Is no_autobump! method defined?
|
||||
sig { returns(T::Boolean) }
|
||||
def no_autobump_defined? = @no_autobump_defined == true
|
||||
|
||||
# Message that explains why the formula was excluded from autobump list.
|
||||
# Returns `nil` if no message is specified.
|
||||
#
|
||||
# @see .no_autobump!
|
||||
sig { returns(T.nilable(T.any(String, Symbol))) }
|
||||
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
|
||||
|
@ -291,6 +291,10 @@ module Formulary
|
||||
end
|
||||
end
|
||||
|
||||
if (because = json_formula["no_autobump_msg"])
|
||||
no_autobump!(because:)
|
||||
end
|
||||
|
||||
bottles_stable = json_formula["bottle"]["stable"].presence
|
||||
|
||||
if bottles_stable
|
||||
|
@ -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_message(*args, &block); end
|
||||
|
||||
sig { params(args: T.untyped, block: T.untyped).returns(T.nilable(MacOSVersion)) }
|
||||
def on_system_block_min_os(*args, &block); end
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -985,13 +985,27 @@ class Tap
|
||||
# Array with autobump names
|
||||
sig { returns(T::Array[String]) }
|
||||
def autobump
|
||||
@autobump ||= if (autobump_file = path/HOMEBREW_TAP_AUTOBUMP_FILE).file?
|
||||
autobump_packages = if core_cask_tap?
|
||||
Homebrew::API::Cask.all_casks
|
||||
else
|
||||
Homebrew::API::Formula.all_formulae
|
||||
end
|
||||
|
||||
@autobump ||= autobump_packages.select do |_, p|
|
||||
p["autobump"] == true && !p["skip_livecheck"] && !(p["deprecated"] || p["disabled"])
|
||||
end.keys
|
||||
|
||||
if @autobump.empty?
|
||||
@autobump = if (autobump_file = path/HOMEBREW_TAP_AUTOBUMP_FILE).file?
|
||||
autobump_file.readlines(chomp: true)
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
@autobump
|
||||
end
|
||||
|
||||
# Whether this {Tap} allows running bump commands on the given {Formula} or {Cask}.
|
||||
sig { params(formula_or_cask_name: String).returns(T::Boolean) }
|
||||
def allow_bump?(formula_or_cask_name)
|
||||
|
@ -155,6 +155,25 @@ 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 be(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 be(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
|
||||
|
@ -16,6 +16,9 @@
|
||||
"user_agent": ":fake"
|
||||
},
|
||||
"version": "1.2.3",
|
||||
"autobump": true,
|
||||
"no_autobump_message": null,
|
||||
"skip_livecheck": false,
|
||||
"installed": null,
|
||||
"installed_time": null,
|
||||
"bundle_version": null,
|
||||
|
@ -652,6 +652,7 @@ _brew_bundle() {
|
||||
__brewcomp "
|
||||
--all
|
||||
--cask
|
||||
--check
|
||||
--cleanup
|
||||
--debug
|
||||
--describe
|
||||
|
@ -507,6 +507,7 @@ __fish_brew_complete_sub_cmd 'bundle' 'env'
|
||||
__fish_brew_complete_sub_cmd 'bundle' 'edit'
|
||||
__fish_brew_complete_arg 'bundle' -l all -d '`list` all dependencies'
|
||||
__fish_brew_complete_arg 'bundle' -l cask -d '`list` or `dump` Homebrew cask dependencies'
|
||||
__fish_brew_complete_arg 'bundle' -l check -d 'Check that all dependencies in the Brewfile are installed before running `exec`, `sh`, or `env`'
|
||||
__fish_brew_complete_arg 'bundle' -l cleanup -d '`install` performs cleanup operation, same as running `cleanup --force`. This is enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and `--global` is passed'
|
||||
__fish_brew_complete_arg 'bundle' -l debug -d 'Display any debugging information'
|
||||
__fish_brew_complete_arg 'bundle' -l describe -d '`dump` adds a description comment above each line, unless the dependency does not have a description. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set'
|
||||
|
@ -540,14 +540,14 @@ _brew_bump() {
|
||||
'--full-name[Print formulae/casks with fully-qualified names]' \
|
||||
'--help[Show this message]' \
|
||||
'(--tap --eval-all --auto)--installed[Check formulae and casks that are currently installed]' \
|
||||
'--no-autobump[Ignore formulae/casks in autobump list (official repositories only)]' \
|
||||
'(--tap)--no-autobump[Ignore formulae/casks in autobump list (official repositories only)]' \
|
||||
'--no-fork[Don'\''t try to fork the repository]' \
|
||||
'(--open-pr)--no-pull-requests[Do not retrieve pull requests from GitHub]' \
|
||||
'(--no-pull-requests)--open-pr[Open a pull request for the new version if none have been opened yet]' \
|
||||
'--quiet[Make some output more quiet]' \
|
||||
'--repology[Use Repology to check for outdated packages]' \
|
||||
'--start-with[Letter or word that the list of package results should alphabetically follow]' \
|
||||
'(--installed --no-auto)--tap[Check formulae and casks within the given tap, specified as user`/`repo]' \
|
||||
'(--installed --no-autobump)--tap[Check formulae and casks within the given tap, specified as user`/`repo]' \
|
||||
'--verbose[Make some output more verbose]' \
|
||||
- formula \
|
||||
'(--cask)--formula[Check only formulae]' \
|
||||
@ -650,6 +650,7 @@ _brew_bundle() {
|
||||
_arguments \
|
||||
'(--no-vscode)--all[`list` all dependencies]' \
|
||||
'--cask[`list` or `dump` Homebrew cask dependencies]' \
|
||||
'--check[Check that all dependencies in the Brewfile are installed before running `exec`, `sh`, or `env`]' \
|
||||
'--cleanup[`install` performs cleanup operation, same as running `cleanup --force`. This is enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and `--global` is passed]' \
|
||||
'--debug[Display any debugging information]' \
|
||||
'--describe[`dump` adds a description comment above each line, unless the dependency does not have a description. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set]' \
|
||||
|
@ -199,7 +199,7 @@ By default, only Homebrew formula dependencies are listed.
|
||||
of the corresponding type. Passing `--formula` also removes matches against
|
||||
formula aliases and old formula names.
|
||||
|
||||
`brew bundle exec` *`command`*
|
||||
`brew bundle exec` \[--check\] *`command`*
|
||||
|
||||
: Run an external command in an isolated build environment based on the
|
||||
`Brewfile` dependencies.
|
||||
@ -210,11 +210,11 @@ commands like `bundle install`, `npm install`, etc. It will also add compiler
|
||||
flags which will help with finding keg-only dependencies like `openssl`,
|
||||
`icu4c`, etc.
|
||||
|
||||
`brew bundle sh`
|
||||
`brew bundle sh` \[--check\]
|
||||
|
||||
: Run your shell in a `brew bundle exec` environment.
|
||||
|
||||
`brew bundle env`
|
||||
`brew bundle env` \[--check\]
|
||||
|
||||
: Print the environment variables that would be set in a `brew bundle exec`
|
||||
environment.
|
||||
@ -319,6 +319,11 @@ flags which will help with finding keg-only dependencies like `openssl`,
|
||||
|
||||
: `cleanup` casks using the `zap` command instead of `uninstall`.
|
||||
|
||||
`--check`
|
||||
|
||||
: Check that all dependencies in the Brewfile are installed before running
|
||||
`exec`, `sh`, or `env`.
|
||||
|
||||
### `casks`
|
||||
|
||||
List all locally installable casks including short names.
|
||||
|
@ -124,15 +124,15 @@ Add entries to your \fBBrewfile\fP\&\. Adds formulae by default\. Use \fB\-\-cas
|
||||
\fBbrew bundle remove\fP \fIname\fP [\.\.\.]
|
||||
Remove entries that match \fBname\fP from your \fBBrewfile\fP\&\. Use \fB\-\-formula\fP, \fB\-\-cask\fP, \fB\-\-tap\fP, \fB\-\-mas\fP, \fB\-\-whalebrew\fP or \fB\-\-vscode\fP to remove only entries of the corresponding type\. Passing \fB\-\-formula\fP also removes matches against formula aliases and old formula names\.
|
||||
.TP
|
||||
\fBbrew bundle exec\fP \fIcommand\fP
|
||||
\fBbrew bundle exec\fP [\-\-check] \fIcommand\fP
|
||||
Run an external command in an isolated build environment based on the \fBBrewfile\fP dependencies\.
|
||||
.P
|
||||
This sanitized build environment ignores unrequested dependencies, which makes sure that things you didn\[u2019]t specify in your \fBBrewfile\fP won\[u2019]t get picked up by commands like \fBbundle install\fP, \fBnpm install\fP, etc\. It will also add compiler flags which will help with finding keg\-only dependencies like \fBopenssl\fP, \fBicu4c\fP, etc\.
|
||||
.TP
|
||||
\fBbrew bundle sh\fP
|
||||
\fBbrew bundle sh\fP [\-\-check]
|
||||
Run your shell in a \fBbrew bundle exec\fP environment\.
|
||||
.TP
|
||||
\fBbrew bundle env\fP
|
||||
\fBbrew bundle env\fP [\-\-check]
|
||||
Print the environment variables that would be set in a \fBbrew bundle exec\fP environment\.
|
||||
.TP
|
||||
\fB\-\-file\fP
|
||||
@ -197,6 +197,9 @@ Temporarily start services while running the \fBexec\fP or \fBsh\fP command\. Th
|
||||
.TP
|
||||
\fB\-\-zap\fP
|
||||
\fBcleanup\fP casks using the \fBzap\fP command instead of \fBuninstall\fP\&\.
|
||||
.TP
|
||||
\fB\-\-check\fP
|
||||
Check that all dependencies in the Brewfile are installed before running \fBexec\fP, \fBsh\fP, or \fBenv\fP\&\.
|
||||
.SS "\fBcasks\fP"
|
||||
List all locally installable casks including short names\.
|
||||
.SS "\fBcleanup\fP \fR[\fIoptions\fP] \fR[\fIformula\fP|\fIcask\fP \.\.\.]"
|
||||
|
Loading…
x
Reference in New Issue
Block a user