diff --git a/Library/Homebrew/caveats.rb b/Library/Homebrew/caveats.rb
index 4a233a0acd..1769f7ce76 100644
--- a/Library/Homebrew/caveats.rb
+++ b/Library/Homebrew/caveats.rb
@@ -19,8 +19,8 @@ class Caveats
sig { returns(String) }
def caveats
caveats = []
+ build = formula.build
begin
- build = formula.build
formula.build = Tab.for_formula(formula)
string = formula.caveats.to_s
caveats << "#{string.chomp}\n" unless string.empty?
diff --git a/Library/Homebrew/cmd/info.rb b/Library/Homebrew/cmd/info.rb
index 495b85aa6e..5b9fda067d 100644
--- a/Library/Homebrew/cmd/info.rb
+++ b/Library/Homebrew/cmd/info.rb
@@ -209,16 +209,18 @@ module Homebrew
formulae.map(&:to_hash)
end
when :v2
- formulae, casks = if all
- [
- Formula.all(eval_all: args.eval_all?).sort,
- Cask::Cask.all(eval_all: args.eval_all?).sort_by(&:full_name),
- ]
- elsif args.installed?
- [Formula.installed.sort, Cask::Caskroom.casks.sort_by(&:full_name)]
- else
- args.named.to_formulae_to_casks
- end
+ formulae, casks = T.let(
+ if all
+ [
+ Formula.all(eval_all: args.eval_all?).sort,
+ Cask::Cask.all(eval_all: args.eval_all?).sort_by(&:full_name),
+ ]
+ elsif args.installed?
+ [Formula.installed.sort, Cask::Caskroom.casks.sort_by(&:full_name)]
+ else
+ T.cast(args.named.to_formulae_to_casks, [T::Array[Formula], T::Array[Cask::Cask]])
+ end, [T::Array[Formula], T::Array[Cask::Cask]]
+ )
if args.variations?
{
diff --git a/Library/Homebrew/cmd/list.rb b/Library/Homebrew/cmd/list.rb
index 538baed2c1..4bfdc6e912 100644
--- a/Library/Homebrew/cmd/list.rb
+++ b/Library/Homebrew/cmd/list.rb
@@ -123,7 +123,8 @@ module Homebrew
raise UsageError, "Cannot use #{flags.join(", ")} with formula arguments." unless args.no_named?
formulae = if args.t?
- Formula.installed.sort_by { |formula| test("M", formula.rack) }.reverse!
+ # See https://ruby-doc.org/3.2/Kernel.html#method-i-test
+ Formula.installed.sort_by { |formula| T.cast(test("M", formula.rack.to_s), Time) }.reverse!
elsif args.full_name?
Formula.installed.sort { |a, b| tap_and_name_comparison.call(a.full_name, b.full_name) }
else
diff --git a/Library/Homebrew/cmd/missing.rb b/Library/Homebrew/cmd/missing.rb
index 41cce0329d..b30184cbf8 100644
--- a/Library/Homebrew/cmd/missing.rb
+++ b/Library/Homebrew/cmd/missing.rb
@@ -33,7 +33,7 @@ module Homebrew
end
ff.each do |f|
- missing = f.missing_dependencies(hide: args.hide)
+ missing = f.missing_dependencies(hide: args.hide || [])
next if missing.empty?
Homebrew.failed = true
diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb
index f9d34f4425..91395f4e98 100644
--- a/Library/Homebrew/cmd/update-report.rb
+++ b/Library/Homebrew/cmd/update-report.rb
@@ -161,7 +161,7 @@ module Homebrew
end
next unless formula.any_version_installed?
- keg = formula.installed_kegs.last
+ keg = formula.installed_kegs.fetch(-1)
tab = keg.tab
# force a `brew upgrade` from the linuxbrew-core version to the homebrew-core version (even if lower)
tab.source["versions"]["version_scheme"] = -1
diff --git a/Library/Homebrew/cmd/uses.rb b/Library/Homebrew/cmd/uses.rb
index 6583a4c45b..a515751a3d 100644
--- a/Library/Homebrew/cmd/uses.rb
+++ b/Library/Homebrew/cmd/uses.rb
@@ -106,9 +106,9 @@ module Homebrew
# We can only get here if `used_formulae_missing` is false, thus there are no UnavailableFormula.
used_formulae = T.cast(used_formulae, T::Array[Formula])
if show_formulae_and_casks || args.formula?
- deps += used_formulae.map(&:runtime_installed_formula_dependents)
- .reduce(&:&)
- .select(&:any_version_installed?)
+ deps += T.must(used_formulae.map(&:runtime_installed_formula_dependents)
+ .reduce(&:&))
+ .select(&:any_version_installed?)
end
if show_formulae_and_casks || args.cask?
deps += select_used_dependents(
diff --git a/Library/Homebrew/dev-cmd/bump.rb b/Library/Homebrew/dev-cmd/bump.rb
index f635e5b229..8e4245a91a 100644
--- a/Library/Homebrew/dev-cmd/bump.rb
+++ b/Library/Homebrew/dev-cmd/bump.rb
@@ -115,7 +115,7 @@ module Homebrew
end
end
- formulae_and_casks = formulae_and_casks&.sort_by do |formula_or_cask|
+ formulae_and_casks = formulae_and_casks.sort_by do |formula_or_cask|
formula_or_cask.respond_to?(:token) ? formula_or_cask.token : formula_or_cask.name
end
diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb
index 1b0b1608a7..8ff7381748 100644
--- a/Library/Homebrew/diagnostic.rb
+++ b/Library/Homebrew/diagnostic.rb
@@ -63,7 +63,7 @@ module Homebrew
end
end
- sig { params(list: T::Array[String], string: String).returns(String) }
+ sig { params(list: T::Array[T.any(Formula, Pathname, String)], string: String).returns(String) }
def inject_file_list(list, string)
list.reduce(string.dup) { |acc, elem| acc << " #{elem}\n" }
.freeze
diff --git a/Library/Homebrew/extend/os/linux/cmd/update-report.rb b/Library/Homebrew/extend/os/linux/cmd/update-report.rb
index 25947f07c4..e70a6c03f8 100644
--- a/Library/Homebrew/extend/os/linux/cmd/update-report.rb
+++ b/Library/Homebrew/extend/os/linux/cmd/update-report.rb
@@ -24,7 +24,7 @@ module Homebrew
end
next unless recursive_runtime_dependencies.map(&:name).include? "gcc"
- keg = formula.installed_kegs.last
+ keg = formula.installed_kegs.fetch(-1)
tab = keg.tab
# Force reinstallation upon `brew upgrade` to fix the bottle RPATH.
tab.source["versions"]["version_scheme"] = -1
diff --git a/Library/Homebrew/extend/os/linux/dependency_collector.rb b/Library/Homebrew/extend/os/linux/dependency_collector.rb
index 8fe62f954c..1da5bf3313 100644
--- a/Library/Homebrew/extend/os/linux/dependency_collector.rb
+++ b/Library/Homebrew/extend/os/linux/dependency_collector.rb
@@ -48,9 +48,9 @@ module OS
built_global_dep_tree!
end
- sig { params(name: String).returns(T.nilable(Formula)) }
+ sig { params(name: String).returns(T.nilable(::Formula)) }
def formula_for(name)
- @formula_for ||= T.let({}, T.nilable(T::Hash[String, Formula]))
+ @formula_for ||= T.let({}, T.nilable(T::Hash[String, ::Formula]))
@formula_for[name] ||= ::Formula[name]
rescue FormulaUnavailableError
nil
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index b316caa4b1..ce3aebd066 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -1,4 +1,4 @@
-# typed: true # rubocop:todo Sorbet/StrictSigil
+# typed: strict
# frozen_string_literal: true
require "attrable"
@@ -233,44 +233,44 @@ class Formula
# Now that we have an instance, it's too late to make any changes to the class-level definition.
self.class.freeze
- @name = name
- @unresolved_path = path
- @path = path.resolved_path
- @alias_path = alias_path
- @alias_name = (File.basename(alias_path) if alias_path)
- @revision = self.class.revision || 0
- @version_scheme = self.class.version_scheme || 0
+ @name = T.let(name, String)
+ @unresolved_path = T.let(path, Pathname)
+ @path = T.let(path.resolved_path, Pathname)
+ @alias_path = T.let(alias_path, T.nilable(Pathname))
+ @alias_name = T.let((File.basename(alias_path) if alias_path), T.nilable(String))
+ @revision = T.let(self.class.revision || 0, Integer)
+ @version_scheme = T.let(self.class.version_scheme || 0, Integer)
+ @head = T.let(nil, T.nilable(SoftwareSpec))
+ @stable = T.let(nil, T.nilable(SoftwareSpec))
- @force_bottle = force_bottle
+ @force_bottle = T.let(force_bottle, T::Boolean)
- @tap = tap
+ @tap = T.let(tap, T.nilable(Tap))
@tap ||= if path == Formulary.core_path(name)
CoreTap.instance
else
Tap.from_path(path)
end
- @full_name = full_name_with_optional_tap(name)
- @full_alias_name = full_name_with_optional_tap(@alias_name)
+ @full_name = T.let(T.must(full_name_with_optional_tap(name)), String)
+ @full_alias_name = T.let(full_name_with_optional_tap(@alias_name), T.nilable(String))
self.class.spec_syms.each do |sym|
spec_eval sym
end
- @active_spec = determine_active_spec(spec)
- @active_spec_sym = if head?
- :head
- else
- :stable
- end
+ @active_spec = T.let(determine_active_spec(spec), SoftwareSpec)
+ @active_spec_sym = T.let(head? ? :head : :stable, Symbol)
validate_attributes!
- @build = active_spec.build
- @pin = FormulaPin.new(self)
- @follow_installed_alias = true
- @prefix_returns_versioned_prefix = false
- @oldname_locks = []
+ @build = T.let(active_spec.build, T.any(BuildOptions, Tab))
+ @pin = T.let(FormulaPin.new(self), FormulaPin)
+ @follow_installed_alias = T.let(true, T::Boolean)
+ @prefix_returns_versioned_prefix = T.let(false, T.nilable(T::Boolean))
+ @oldname_locks = T.let([], T::Array[FormulaLock])
+ @on_system_blocks_exist = T.let(false, T::Boolean)
end
+ sig { params(spec_sym: Symbol).void }
def active_spec=(spec_sym)
spec = send(spec_sym)
raise FormulaSpecificationError, "#{spec_sym} spec is not available for #{full_name}" unless spec
@@ -287,6 +287,7 @@ class Formula
Requirement.clear_cache
end
+ sig { params(build_options: T.any(BuildOptions, Tab)).void }
def build=(build_options)
old_options = @build
@build = build_options
@@ -301,6 +302,7 @@ class Formula
private
# Allow full name logic to be re-used between names, aliases and installed aliases.
+ sig { params(name: T.nilable(String)).returns(T.nilable(String)) }
def full_name_with_optional_tap(name)
if name.nil? || @tap.nil? || @tap.core_tap?
name
@@ -309,6 +311,7 @@ class Formula
end
end
+ sig { params(name: T.any(String, Symbol)).void }
def spec_eval(name)
spec = self.class.send(name).dup
return unless spec.url
@@ -321,11 +324,13 @@ class Formula
sig { params(spec: SoftwareSpec).void }
def add_global_deps_to_spec(spec); end
+ sig { params(requested: T.any(String, Symbol)).returns(SoftwareSpec) }
def determine_active_spec(requested)
spec = send(requested) || stable || head
spec || raise(FormulaSpecificationError, "#{full_name}: formula requires at least a URL")
end
+ sig { void }
def validate_attributes!
if name.blank? || name.match?(/\s/) || !Utils.safe_filename?(name)
raise FormulaValidationError.new(full_name, :name, name)
@@ -363,11 +368,13 @@ class Formula
installed_alias_path&.basename&.to_s
end
+ sig { returns(T.nilable(String)) }
def full_installed_alias_name
full_name_with_optional_tap(installed_alias_name)
end
# The path that was specified to find this formula.
+ sig { returns(T.nilable(Pathname)) }
def specified_path
return Homebrew::API::Formula.cached_json_file_path if loaded_from_api?
return alias_path if alias_path&.exist?
@@ -380,21 +387,25 @@ class Formula
end
# The name specified to find this formula.
+ sig { returns(String) }
def specified_name
alias_name || name
end
# The name (including tap) specified to find this formula.
+ sig { returns(String) }
def full_specified_name
full_alias_name || full_name
end
# The name specified to install this formula.
+ sig { returns(String) }
def installed_specified_name
installed_alias_name || name
end
# The name (including tap) specified to install this formula.
+ sig { returns(String) }
def full_installed_specified_name
full_installed_alias_name || full_name
end
@@ -429,7 +440,7 @@ class Formula
# The Bottle object for the currently active {SoftwareSpec}.
sig { returns(T.nilable(Bottle)) }
def bottle
- @bottle ||= Bottle.new(self, bottle_specification) if bottled?
+ @bottle ||= T.let(Bottle.new(self, bottle_specification), T.nilable(Bottle)) if bottled?
end
# The Bottle object for given tag.
@@ -592,12 +603,13 @@ class Formula
# @api internal
sig { returns(T::Array[String]) }
def oldnames
- @oldnames ||= if (tap = self.tap)
- Tap.tap_migration_oldnames(tap, name) +
- tap.formula_reverse_renames.fetch(name, [])
- else
- []
- end
+ @oldnames ||= T.let(
+ if (tap = self.tap)
+ Tap.tap_migration_oldnames(tap, name) + tap.formula_reverse_renames.fetch(name, [])
+ else
+ []
+ end, T.nilable(T::Array[String])
+ )
end
# All aliases for the formula.
@@ -605,11 +617,13 @@ class Formula
# @api internal
sig { returns(T::Array[String]) }
def aliases
- @aliases ||= if (tap = self.tap)
- tap.alias_reverse_table.fetch(full_name, []).map { _1.split("/").last }
- else
- []
- end
+ @aliases ||= T.let(
+ if (tap = self.tap)
+ tap.alias_reverse_table.fetch(full_name, []).map { _1.split("/").fetch(-1) }
+ else
+ []
+ end, T.nilable(T::Array[String])
+ )
end
# The {Resource}s for the currently active {SoftwareSpec}.
@@ -672,6 +686,7 @@ class Formula
# You probably want {#opt_prefix} instead.
#
# @api internal
+ sig { returns(Pathname) }
def linked_keg
linked_keg = possible_names.map { |name| HOMEBREW_LINKED_KEGS/name }
.find(&:directory?)
@@ -680,6 +695,7 @@ class Formula
HOMEBREW_LINKED_KEGS/name
end
+ sig { returns(T.nilable(PkgVersion)) }
def latest_head_version
head_versions = installed_prefixes.filter_map do |pn|
pn_pkgversion = PkgVersion.parse(pn.basename.to_s)
@@ -691,11 +707,13 @@ class Formula
end
end
+ sig { returns(T.nilable(Pathname)) }
def latest_head_prefix
head_version = latest_head_version
prefix(head_version) if head_version
end
+ sig { params(version: PkgVersion, fetch_head: T::Boolean).returns(T::Boolean) }
def head_version_outdated?(version, fetch_head: false)
tab = Tab.for_keg(prefix(version))
@@ -712,9 +730,10 @@ class Formula
end
# The latest prefix for this formula. Checks for {#head} and then {#stable}'s {#prefix}
+ sig { returns(Pathname) }
def latest_installed_prefix
if head && (head_version = latest_head_version) && !head_version_outdated?(head_version)
- latest_head_prefix
+ T.must(latest_head_prefix)
elsif stable && (stable_prefix = prefix(PkgVersion.new(T.must(stable).version, revision))).directory?
stable_prefix
else
@@ -753,6 +772,7 @@ class Formula
end
# If a formula's linked keg points to the prefix.
+ sig { params(version: T.any(String, PkgVersion)).returns(T::Boolean) }
def prefix_linked?(version = pkg_version)
return false unless linked?
@@ -775,6 +795,7 @@ class Formula
end
# All currently installed prefix directories.
+ sig { returns(T::Array[Pathname]) }
def installed_prefixes
possible_names.map { |name| HOMEBREW_CELLAR/name }
.select(&:directory?)
@@ -1213,9 +1234,10 @@ class Formula
end
# Runs a block with the given log type in effect for its duration.
- def with_logging(log_type)
+ sig { params(log_type: String, _block: T.proc.void).void }
+ def with_logging(log_type, &_block)
old_log_type = @active_log_type
- @active_log_type = log_type
+ @active_log_type = T.let(log_type, T.nilable(String))
yield
ensure
@active_log_type = old_log_type
@@ -1253,6 +1275,7 @@ class Formula
# ```
#
# @see https://www.unix.com/man-page/all/5/plist/ plist(5)
man page
+ sig { returns(NilClass) }
def plist
odisabled "`Formula#plist`", "`Homebrew::Service`"
nil
@@ -1289,8 +1312,9 @@ class Formula
end
# The service specification of the software.
+ sig { returns(Homebrew::Service) }
def service
- @service ||= Homebrew::Service.new(self, &self.class.service)
+ @service ||= T.let(Homebrew::Service.new(self, &self.class.service), T.nilable(Homebrew::Service))
end
# A stable path for this formula, when installed. Contains the formula name
@@ -1418,7 +1442,7 @@ class Formula
sig { void }
def run_post_install
- @prefix_returns_versioned_prefix = true
+ @prefix_returns_versioned_prefix = T.let(true, T.nilable(T::Boolean))
build = self.build
begin
@@ -1443,7 +1467,7 @@ class Formula
end
ensure
self.build = build
- @prefix_returns_versioned_prefix = false
+ @prefix_returns_versioned_prefix = T.let(false, T.nilable(T::Boolean))
end
end
@@ -1494,13 +1518,14 @@ class Formula
# @see .skip_clean
sig { params(path: Pathname).returns(T::Boolean) }
def skip_clean?(path)
- return true if path.extname == ".la" && self.class.skip_clean_paths.include?(:la)
+ return true if path.extname == ".la" && T.must(self.class.skip_clean_paths).include?(:la)
to_check = path.relative_path_from(prefix).to_s
- self.class.skip_clean_paths.include? to_check
+ T.must(self.class.skip_clean_paths).include? to_check
end
# @see .link_overwrite
+ sig { params(path: Pathname).returns(T::Boolean) }
def link_overwrite?(path)
# Don't overwrite files not created by Homebrew.
return false if path.stat.uid != HOMEBREW_ORIGINAL_BREW_FILE.stat.uid
@@ -1528,10 +1553,10 @@ class Formula
end
end
to_check = path.relative_path_from(HOMEBREW_PREFIX).to_s
- self.class.link_overwrite_paths.any? do |p|
- p == to_check ||
- to_check.start_with?("#{p.chomp("/")}/") ||
- /^#{Regexp.escape(p).gsub('\*', ".*?")}$/.match?(to_check)
+ T.must(self.class.link_overwrite_paths).any? do |p|
+ p.to_s == to_check ||
+ to_check.start_with?("#{p.to_s.chomp("/")}/") ||
+ /^#{Regexp.escape(p.to_s).gsub('\*', ".*?")}$/.match?(to_check)
end
end
@@ -1601,6 +1626,7 @@ class Formula
false
end
+ sig { void }
def patch
return if patchlist.empty?
@@ -1629,7 +1655,7 @@ class Formula
_blk: T.proc.params(arg0: Formula, arg1: Mktemp).void).void
}
def brew(fetch: true, keep_tmp: false, debug_symbols: false, interactive: false, &_blk)
- @prefix_returns_versioned_prefix = true
+ @prefix_returns_versioned_prefix = T.let(true, T.nilable(T::Boolean))
active_spec.fetch if fetch
stage(interactive:, debug_symbols:) do |staging|
staging.retain! if keep_tmp || debug_symbols
@@ -1658,12 +1684,13 @@ class Formula
end
end
ensure
- @prefix_returns_versioned_prefix = false
+ @prefix_returns_versioned_prefix = T.let(false, T.nilable(T::Boolean))
end
+ sig { returns(T::Array[String]) }
def lock
- @lock = FormulaLock.new(name)
- @lock.lock
+ @lock = T.let(FormulaLock.new(name), T.nilable(FormulaLock))
+ T.must(@lock).lock
oldnames.each do |oldname|
next unless (oldname_rack = HOMEBREW_CELLAR/oldname).exist?
@@ -1675,6 +1702,7 @@ class Formula
end
end
+ sig { returns(T::Array[FormulaLock]) }
def unlock
@lock&.unlock
@oldname_locks.each(&:unlock)
@@ -1696,6 +1724,7 @@ class Formula
!oldnames_to_migrate.empty? && !rack.exist?
end
+ sig { params(fetch_head: T::Boolean).returns(T::Array[Keg]) }
def outdated_kegs(fetch_head: false)
raise Migrator::MigrationNeededError.new(oldnames_to_migrate.first, name) if migration_needed?
@@ -1736,6 +1765,7 @@ class Formula
installed_alias_target_changed? && !latest_formula.latest_version_installed?
end
+ sig { returns(T.nilable(Formula)) }
def current_installed_alias_target
Formulary.factory(T.must(installed_alias_name)) if installed_alias_path
end
@@ -1765,10 +1795,12 @@ class Formula
# If the alias has changed value, return the new formula.
# Otherwise, return self.
+ sig { returns(Formula) }
def latest_formula
- installed_alias_target_changed? ? current_installed_alias_target : self
+ installed_alias_target_changed? ? T.must(current_installed_alias_target) : self
end
+ sig { returns(T::Array[Formula]) }
def old_installed_formulae
# If this formula isn't the current target of the alias,
# it doesn't make sense to say that other formulae are older versions of it
@@ -1800,6 +1832,7 @@ class Formula
delegate unpin: :@pin
+ sig { params(other: T.untyped).returns(T::Boolean) }
def ==(other)
self.class == other.class &&
name == other.name &&
@@ -1807,16 +1840,19 @@ class Formula
end
alias eql? ==
+ sig { returns(Integer) }
def hash
name.hash
end
+ sig { params(other: BasicObject).returns(T.nilable(Integer)) }
def <=>(other)
- return unless other.is_a?(Formula)
-
- name <=> other.name
+ case other
+ when Formula then name <=> other.name
+ end
end
+ sig { returns(T::Array[String]) }
def possible_names
[name, *oldnames, *aliases].compact
end
@@ -1923,7 +1959,7 @@ class Formula
# Standard parameters for npm builds.
#
# @api public
- sig { params(prefix: T.any(String, Pathname, FalseClass)).returns(T::Array[String]) }
+ sig { params(prefix: T.any(NilClass, String, Pathname)).returns(T::Array[String]) }
def std_npm_args(prefix: libexec)
require "language/node"
@@ -1936,7 +1972,7 @@ class Formula
#
# @api public
sig {
- params(prefix: T.any(String, Pathname, FalseClass),
+ params(prefix: T.any(FalseClass, String, Pathname),
build_isolation: T::Boolean).returns(T::Array[String])
}
def std_pip_args(prefix: self.prefix, build_isolation: false)
@@ -2232,32 +2268,40 @@ class Formula
end
# an array of all core {Formula} names
+ sig { returns(T::Array[String]) }
def self.core_names
CoreTap.instance.formula_names
end
# an array of all tap {Formula} names
+ sig { returns(T::Array[String]) }
def self.tap_names
- @tap_names ||= Tap.reject(&:core_tap?).flat_map(&:formula_names).sort
+ @tap_names ||= T.let(Tap.reject(&:core_tap?).flat_map(&:formula_names).sort, T.nilable(T::Array[String]))
end
# an array of all tap {Formula} files
+ sig { returns(T::Array[Pathname]) }
def self.tap_files
- @tap_files ||= Tap.reject(&:core_tap?).flat_map(&:formula_files)
+ @tap_files ||= T.let(Tap.reject(&:core_tap?).flat_map(&:formula_files), T.nilable(T::Array[Pathname]))
end
# an array of all {Formula} names
+ sig { returns(T::Array[String]) }
def self.names
- @names ||= (core_names + tap_names.map { |name| name.split("/").last }).uniq.sort
+ @names ||= T.let((core_names + tap_names.map do |name|
+ name.split("/").fetch(-1)
+ end).uniq.sort, T.nilable(T::Array[String]))
end
# an array of all {Formula} names, which the tap formulae have the fully-qualified name
+ sig { returns(T::Array[String]) }
def self.full_names
- @full_names ||= core_names + tap_names
+ @full_names ||= T.let(core_names + tap_names, T.nilable(T::Array[String]))
end
# an array of all {Formula}
# this should only be used when users specify `--all` to a command
+ sig { params(eval_all: T::Boolean).returns(T::Array[Formula]) }
def self.all(eval_all: false)
if !eval_all && !Homebrew::EnvConfig.eval_all?
raise ArgumentError, "Formula#all without `--eval-all` or HOMEBREW_EVAL_ALL"
@@ -2275,6 +2319,7 @@ class Formula
end
# An array of all racks currently installed.
+ sig { returns(T::Array[Pathname]) }
def self.racks
Formula.cache[:racks] ||= if HOMEBREW_CELLAR.directory?
HOMEBREW_CELLAR.subdirs.reject do |rack|
@@ -2292,6 +2337,7 @@ class Formula
end
# An array of all installed {Formula}
+ sig { returns(T::Array[Formula]) }
def self.installed
Formula.cache[:installed] ||= racks.flat_map do |rack|
Formulary.from_rack(rack)
@@ -2300,6 +2346,7 @@ class Formula
end.uniq(&:name)
end
+ sig { params(alias_path: T.nilable(Pathname)).returns(T::Array[Formula]) }
def self.installed_with_alias_path(alias_path)
return [] if alias_path.nil?
@@ -2307,36 +2354,46 @@ class Formula
end
# an array of all alias files of core {Formula}
+ sig { returns(T::Array[Pathname]) }
def self.core_alias_files
CoreTap.instance.alias_files
end
# an array of all core aliases
+ sig { returns(T::Array[String]) }
def self.core_aliases
CoreTap.instance.aliases
end
# an array of all tap aliases
+ sig { returns(T::Array[String]) }
def self.tap_aliases
- @tap_aliases ||= Tap.reject(&:core_tap?).flat_map(&:aliases).sort
+ @tap_aliases ||= T.let(Tap.reject(&:core_tap?).flat_map(&:aliases).sort, T.nilable(T::Array[String]))
end
# an array of all aliases
+ sig { returns(T::Array[String]) }
def self.aliases
- @aliases ||= (core_aliases + tap_aliases.map { |name| name.split("/").last }).uniq.sort
+ @aliases ||= T.let((core_aliases + tap_aliases.map do |name|
+ name.split("/").fetch(-1)
+ end).uniq.sort, T.nilable(T::Array[String]))
end
# an array of all aliases as fully-qualified names
+ sig { returns(T::Array[String]) }
def self.alias_full_names
- @alias_full_names ||= core_aliases + tap_aliases
+ @alias_full_names ||= T.let(core_aliases + tap_aliases, T.nilable(T::Array[String]))
end
# Returns a list of approximately matching formula names, but not the complete match
+ sig { params(name: String).returns(T::Array[String]) }
def self.fuzzy_search(name)
- @spell_checker ||= DidYouMean::SpellChecker.new(dictionary: Set.new(names + full_names).to_a)
- @spell_checker.correct(name)
+ @spell_checker ||= T.let(DidYouMean::SpellChecker.new(dictionary: Set.new(names + full_names).to_a),
+ T.nilable(DidYouMean::SpellChecker))
+ T.cast(@spell_checker.correct(name), T::Array[String])
end
+ sig { params(name: T.any(Pathname, String)).returns(Formula) }
def self.[](name)
Formulary.factory(name)
end
@@ -2362,6 +2419,7 @@ class Formula
requirements.none?(MacOSRequirement) && requirements.none?(LinuxRequirement)
end
+ sig { params(options: T::Hash[Symbol, String]).void }
def print_tap_action(options = {})
return unless tap?
@@ -2369,6 +2427,7 @@ class Formula
ohai "#{verb} #{name} from #{tap}"
end
+ sig { returns(T.nilable(String)) }
def tap_git_head
tap&.git_head
rescue TapUnavailableError
@@ -2380,12 +2439,13 @@ class Formula
# !attr[r] conflicts
# @api internal
sig { returns(T::Array[FormulaConflict]) }
- def conflicts = self.class.conflicts
+ def conflicts = T.must(self.class.conflicts)
# Returns a list of Dependency objects in an installable order, which
# means if a depends on b then b will be ordered before a in this list
#
# @api internal
+ sig { params(block: T.nilable(T.proc.params(arg0: Formula, arg1: Dependency).void)).returns(T::Array[Dependency]) }
def recursive_dependencies(&block)
cache_key = "Formula#recursive_dependencies" unless block
Dependency.expand(self, cache_key:, &block)
@@ -2394,6 +2454,7 @@ class Formula
# The full set of Requirements for this formula's dependency tree.
#
# @api internal
+ sig { params(block: T.nilable(T.proc.params(arg0: Formula, arg1: Requirement).void)).returns(Requirements) }
def recursive_requirements(&block)
cache_key = "Formula#recursive_requirements" unless block
Requirement.expand(self, cache_key:, &block)
@@ -2431,6 +2492,7 @@ class Formula
# Returns a list of Dependency objects that are required at runtime.
#
# @api internal
+ sig { params(read_from_tab: T::Boolean, undeclared: T::Boolean).returns(T::Array[Dependency]) }
def runtime_dependencies(read_from_tab: true, undeclared: true)
deps = if read_from_tab && undeclared &&
(tab_deps = any_installed_keg&.runtime_dependencies)
@@ -2452,6 +2514,7 @@ class Formula
end
# Returns a list of {Formula} objects that are required at runtime.
+ sig { params(read_from_tab: T::Boolean, undeclared: T::Boolean).returns(T::Array[Formula]) }
def runtime_formula_dependencies(read_from_tab: true, undeclared: true)
cache_key = "#{full_name}-#{read_from_tab}-#{undeclared}"
@@ -2466,6 +2529,7 @@ class Formula
end
end
+ sig { returns(T::Array[Formula]) }
def runtime_installed_formula_dependents
# `any_installed_keg` and `runtime_dependencies` `select`s ensure
# that we don't end up with something `Formula#runtime_dependencies` can't
@@ -2485,8 +2549,8 @@ class Formula
# Returns a list of formulae depended on by this formula that aren't
# installed.
- def missing_dependencies(hide: nil)
- hide ||= []
+ sig { params(hide: T::Array[String]).returns(T::Array[Formula]) }
+ def missing_dependencies(hide: [])
runtime_formula_dependencies.select do |f|
hide.include?(f.name) || f.installed_prefixes.empty?
end
@@ -2506,6 +2570,7 @@ class Formula
Checksum.new(Digest::SHA256.file(path).hexdigest) if path.exist?
end
+ sig { params(dependables: T::Hash[Symbol, T.untyped]).returns(T::Array[T::Hash[Symbol, T.untyped]]) }
def merge_spec_dependables(dependables)
# We have a hash of specs names (stable/head) to dependency lists.
# Merge all of the dependency lists together, removing any duplicates.
@@ -2521,6 +2586,7 @@ class Formula
end
private :merge_spec_dependables
+ sig { returns(T::Hash[String, T.untyped]) }
def to_hash
hsh = {
"name" => name,
@@ -2607,6 +2673,7 @@ class Formula
hsh
end
+ sig { returns(T::Hash[String, T.untyped]) }
def to_hash_with_variations
hash = to_hash
@@ -2648,6 +2715,7 @@ class Formula
end
# Returns the bottle information for a formula.
+ sig { returns(T::Hash[String, T.untyped]) }
def bottle_hash
hash = {}
stable_spec = stable
@@ -2678,6 +2746,7 @@ class Formula
hash
end
+ sig { returns(T::Hash[String, T::Hash[String, T.untyped]]) }
def urls_hash
hash = {}
@@ -2703,6 +2772,7 @@ class Formula
hash
end
+ sig { returns(T::Array[T::Hash[String, T.untyped]]) }
def serialized_requirements
requirements = self.class.spec_syms.to_h do |sym|
[sym, send(sym)&.requirements]
@@ -2728,11 +2798,13 @@ class Formula
end
end
+ sig { returns(T.nilable(String)) }
def caveats_with_placeholders
caveats&.gsub(HOMEBREW_PREFIX, HOMEBREW_PREFIX_PLACEHOLDER)
&.gsub(HOMEBREW_CELLAR, HOMEBREW_CELLAR_PLACEHOLDER)
end
+ sig { returns(T::Hash[String, T.untyped]) }
def dependencies_hash
# Create a hash of spec names (stable/head) to the list of dependencies under each
dependencies = self.class.spec_syms.to_h do |sym|
@@ -2797,6 +2869,7 @@ class Formula
hash
end
+ sig { params(spec_symbol: Symbol).returns(T.nilable(T::Hash[String, T.untyped])) }
def internal_dependencies_hash(spec_symbol)
raise ArgumentError, "Unsupported spec: #{spec_symbol}" unless [:stable, :head].include?(spec_symbol)
return unless (spec = public_send(spec_symbol))
@@ -2815,6 +2888,7 @@ class Formula
end
end
+ sig { returns(T.nilable(T::Boolean)) }
def on_system_blocks_exist?
self.class.on_system_blocks_exist? || @on_system_blocks_exist
end
@@ -2831,13 +2905,15 @@ class Formula
active_spec.fetch(verify_download_integrity:, timeout:, quiet:)
end
+ sig { params(filename: T.any(Pathname, String)).void }
def verify_download_integrity(filename)
odeprecated "Formula#verify_download_integrity", "Resource#verify_download_integrity on Formula#resource"
active_spec.verify_download_integrity(filename)
end
+ sig { params(keep_tmp: T::Boolean).returns(T.untyped) }
def run_test(keep_tmp: false)
- @prefix_returns_versioned_prefix = true
+ @prefix_returns_versioned_prefix = T.let(true, T.nilable(T::Boolean))
test_env = {
TMPDIR: HOMEBREW_TEMP,
@@ -2854,9 +2930,9 @@ class Formula
mktemp("#{name}-test") do |staging|
staging.retain! if keep_tmp
- @testpath = T.must(staging.tmpdir)
+ @testpath = T.let(staging.tmpdir, T.nilable(Pathname))
test_env[:HOME] = @testpath
- setup_home @testpath
+ setup_home T.must(@testpath)
begin
with_logging("test") do
with_env(test_env) do
@@ -2870,8 +2946,8 @@ class Formula
end
end
ensure
- @prefix_returns_versioned_prefix = false
- @testpath = nil
+ @prefix_returns_versioned_prefix = T.let(false, T.nilable(T::Boolean))
+ @testpath = T.let(nil, T.nilable(Pathname))
end
sig { returns(T::Boolean) }
@@ -2879,8 +2955,10 @@ class Formula
method(:test).owner != Formula
end
+ sig { returns(T.nilable(T::Boolean)) }
def test; end
+ sig { params(file: T.any(Pathname, String)).returns(Pathname) }
def test_fixtures(file)
HOMEBREW_LIBRARY_PATH/"test/support/fixtures"/file
end
@@ -2898,6 +2976,7 @@ class Formula
# system "make", "install"
# end
# ```
+ sig { void }
def install; end
# Sometimes we have to change a bit before we install. Mostly we
@@ -2958,6 +3037,7 @@ class Formula
end
# Returns a list of Dependency objects that are declared in the formula.
+ sig { returns(T::Array[Dependency]) }
def declared_runtime_dependencies
cache_key = "Formula#declared_runtime_dependencies" unless build.any_args_or_options?
Dependency.expand(self, cache_key:) do |_, dependency|
@@ -2974,6 +3054,7 @@ class Formula
# Returns a list of Dependency objects that are not declared in the formula
# but the formula links to.
+ sig { returns(T::Array[Dependency]) }
def undeclared_runtime_dependencies
keg = any_installed_keg
return [] unless keg
@@ -3060,7 +3141,7 @@ class Formula
end
ohai "#{cmd} #{pretty_args * " "}".strip
- @exec_count ||= 0
+ @exec_count ||= T.let(0, T.nilable(Integer))
@exec_count += 1
logfn = format("#{logs}/#{active_log_prefix}%02d.%s",
exec_count: @exec_count,
@@ -3108,7 +3189,7 @@ class Formula
end
end
- Process.wait(T.must(pid))
+ Process.wait(pid)
$stdout.flush
@@ -3199,6 +3280,7 @@ class Formula
# A version of `FileUtils.mkdir` that also changes to that folder in
# a block.
+ sig { params(name: T.any(String, Pathname), block: T.nilable(T.proc.void)).returns(T.untyped) }
def mkdir(name, &block)
result = FileUtils.mkdir_p(name)
return result unless block
@@ -3218,6 +3300,7 @@ class Formula
end
end
+ sig { void }
def fetch_patches
patchlist.select(&:external?).each(&:fetch)
end
@@ -3229,7 +3312,7 @@ class Formula
T.must(bottle).fetch_tab
end
- sig { returns(Hash) }
+ sig { returns(T::Hash[String, T.untyped]) }
def bottle_tab_attributes
return {} unless bottled?
@@ -3238,15 +3321,25 @@ class Formula
private
+ sig { void }
def prepare_patches
patchlist.grep(DATAPatch) { |p| p.path = path }
end
# Returns the prefix for a given formula version number.
+ sig { params(version: T.any(String, Pathname, PkgVersion)).returns(Pathname) }
def versioned_prefix(version)
- rack/version
+ rack/version.to_s
end
+ sig {
+ params(
+ cmd: T.any(String, Pathname),
+ args: T::Array[T.any(String, Integer, Pathname, Symbol)],
+ out: IO,
+ logfn: T.nilable(String),
+ ).void
+ }
def exec_cmd(cmd, args, out, logfn)
ENV["HOMEBREW_CC_LOG_PATH"] = logfn
@@ -3275,6 +3368,7 @@ class Formula
end
# Common environment variables used at both build and test time.
+ sig { returns(T::Hash[Symbol, String]) }
def common_stage_test_env
{
_JAVA_OPTIONS: "-Duser.home=#{HOMEBREW_CACHE}/java_cache",
@@ -3287,10 +3381,11 @@ class Formula
}
end
- def stage(interactive: false, debug_symbols: false)
+ sig { params(interactive: T::Boolean, debug_symbols: T::Boolean, _block: T.proc.params(arg0: Mktemp).void).void }
+ def stage(interactive: false, debug_symbols: false, &_block)
active_spec.stage(debug_symbols:) do |staging|
- @source_modified_time = active_spec.source_modified_time
- @buildpath = Pathname.pwd
+ @source_modified_time = T.let(active_spec.source_modified_time, T.nilable(Time))
+ @buildpath = T.let(Pathname.pwd, T.nilable(Pathname))
env_home = T.must(buildpath)/".brew_home"
mkdir_p env_home
@@ -3314,7 +3409,7 @@ class Formula
yield staging
end
ensure
- @buildpath = nil
+ @buildpath = T.let(nil, T.nilable(Pathname))
end
end
end
@@ -3328,23 +3423,25 @@ class Formula
# Initialise instance variables for each subclass. These need to be initialised before the class is frozen,
# and some DSL may never be called so it can't be done lazily.
+ sig { params(child: T::Class[Formula]).void }
def inherited(child)
super
child.instance_eval do
# Ensure this is synced with `freeze`
- @stable = SoftwareSpec.new(flags: build_flags)
- @head = HeadSoftwareSpec.new(flags: build_flags)
- @livecheck = Livecheck.new(self)
- @conflicts = []
- @skip_clean_paths = Set.new
- @link_overwrite_paths = Set.new
- @loaded_from_api = false
- @network_access_allowed = SUPPORTED_NETWORK_ACCESS_PHASES.to_h do |phase|
+ @stable = T.let(SoftwareSpec.new(flags: build_flags), T.nilable(SoftwareSpec))
+ @head = T.let(HeadSoftwareSpec.new(flags: build_flags), T.nilable(HeadSoftwareSpec))
+ @livecheck = T.let(Livecheck.new(self), T.nilable(Livecheck))
+ @conflicts = T.let([], T.nilable(T::Array[FormulaConflict]))
+ @skip_clean_paths = T.let(Set.new, T.nilable(T::Set[T.any(String, Symbol)]))
+ @link_overwrite_paths = T.let(Set.new, T.nilable(T::Set[String]))
+ @loaded_from_api = T.let(false, T.nilable(T::Boolean))
+ @network_access_allowed = T.let(SUPPORTED_NETWORK_ACCESS_PHASES.to_h do |phase|
[phase, DEFAULT_NETWORK_ACCESS_ALLOWED]
- end
+ end, T.nilable(T::Hash[Symbol, T::Boolean]))
end
end
+ sig { returns(T.self_type) }
def freeze
specs.each(&:freeze)
@livecheck.freeze
@@ -3354,6 +3451,9 @@ class Formula
super
end
+ sig { returns(T::Hash[Symbol, T::Boolean]) }
+ def network_access_allowed = T.must(@network_access_allowed)
+
# Whether this formula was loaded using the formulae.brew.sh API
attr_predicate :loaded_from_api?
@@ -3362,6 +3462,7 @@ class Formula
attr_predicate :on_system_blocks_exist?
# The reason for why this software is not linked (by default) to {::HOMEBREW_PREFIX}.
+ sig { returns(T.nilable(KegOnlyReason)) }
attr_reader :keg_only_reason
# A one-line description of the software. Used by users to get an overview
@@ -3430,11 +3531,15 @@ class Formula
# @see https://docs.brew.sh/License-Guidelines Homebrew License Guidelines
# @see https://spdx.github.io/spdx-spec/latest/annexes/spdx-license-expressions/ SPDX license expression guide
# @api public
+ sig {
+ params(args: T.any(NilClass, String, Symbol, T::Hash[T.any(String, Symbol), T.anything]))
+ .returns(T.any(NilClass, String, Symbol, T::Hash[T.any(String, Symbol), T.anything]))
+ }
def license(args = nil)
if args.nil?
@licenses
else
- @licenses = args
+ @licenses = T.let(args, T.any(NilClass, String, Symbol, T::Hash[T.any(String, Symbol), T.anything]))
end
end
@@ -3462,12 +3567,12 @@ class Formula
def allow_network_access!(phases = [])
phases_array = Array(phases)
if phases_array.empty?
- @network_access_allowed.each_key { |phase| @network_access_allowed[phase] = true }
+ network_access_allowed.each_key { |phase| network_access_allowed[phase] = true }
else
phases_array.each do |phase|
raise ArgumentError, "Unknown phase: #{phase}" unless SUPPORTED_NETWORK_ACCESS_PHASES.include?(phase)
- @network_access_allowed[phase] = true
+ network_access_allowed[phase] = true
end
end
end
@@ -3496,12 +3601,12 @@ class Formula
def deny_network_access!(phases = [])
phases_array = Array(phases)
if phases_array.empty?
- @network_access_allowed.each_key { |phase| @network_access_allowed[phase] = false }
+ network_access_allowed.each_key { |phase| network_access_allowed[phase] = false }
else
phases_array.each do |phase|
raise ArgumentError, "Unknown phase: #{phase}" unless SUPPORTED_NETWORK_ACCESS_PHASES.include?(phase)
- @network_access_allowed[phase] = false
+ network_access_allowed[phase] = false
end
end
end
@@ -3512,7 +3617,7 @@ class Formula
raise ArgumentError, "Unknown phase: #{phase}" unless SUPPORTED_NETWORK_ACCESS_PHASES.include?(phase)
env_var = Homebrew::EnvConfig.send(:"formula_#{phase}_network")
- env_var.nil? ? @network_access_allowed[phase] : env_var == "allow"
+ env_var.nil? ? network_access_allowed[phase] : env_var == "allow"
end
# The homepage for the software. Used by users to get more information
@@ -3561,13 +3666,21 @@ class Formula
@service_block.present?
end
- sig { returns(T::Array[FormulaConflict]) }
+ sig { returns(T.nilable(T::Array[FormulaConflict])) }
attr_reader :conflicts
- attr_reader :skip_clean_paths, :link_overwrite_paths, :pour_bottle_only_if
+ sig { returns(T.nilable(T::Set[T.any(String, Symbol)])) }
+ attr_reader :skip_clean_paths
+
+ sig { returns(T.nilable(T::Set[String])) }
+ attr_reader :link_overwrite_paths
+
+ sig { returns(T.nilable(Symbol)) }
+ attr_reader :pour_bottle_only_if
# If `pour_bottle?` returns `false` the user-visible reason to display for
# why they cannot use the bottle.
+ sig { returns(T.nilable(String)) }
attr_accessor :pour_bottle_check_unsatisfied_reason
# Used for creating new Homebrew versions of software without new upstream
@@ -3608,11 +3721,13 @@ class Formula
val.nil? ? @version_scheme : @version_scheme = T.let(val, T.nilable(Integer))
end
+ sig { returns(T::Array[Symbol]) }
def spec_syms
[:stable, :head].freeze
end
# A list of the {.stable} and {.head} {SoftwareSpec}s.
+ sig { returns(T::Array[SoftwareSpec]) }
def specs
spec_syms.map do |sym|
send(sym)
@@ -3643,6 +3758,7 @@ class Formula
#
# @!attribute [w] url
# @api public
+ sig { params(val: String, specs: T::Hash[Symbol, T.any(String, Symbol)]).void }
def url(val, specs = {})
stable.url(val, specs)
end
@@ -3659,6 +3775,7 @@ class Formula
# ```
#
# @api public
+ sig { params(val: T.nilable(String)).void }
def version(val = nil)
stable.version(val)
end
@@ -3678,6 +3795,7 @@ class Formula
# ```
#
# @api public
+ sig { params(val: String).void }
def mirror(val)
stable.mirror(val)
end
@@ -3696,6 +3814,7 @@ class Formula
# ```
#
# @api public
+ sig { params(val: String).void }
def sha256(val)
stable.sha256(val)
end
@@ -3729,11 +3848,13 @@ class Formula
stable.bottle(&block)
end
+ sig { returns(String) }
def build
stable.build
end
# Get the `BUILD_FLAGS` from the formula's namespace set in `Formulary::load_formula`.
+ sig { returns(T::Array[String]) }
def build_flags
namespace = T.must(to_s.split("::")[0..-2]).join("::")
return [] if namespace.empty?
@@ -3760,10 +3881,11 @@ class Formula
# ```
#
# @api public
+ sig { params(block: T.nilable(T.proc.returns(SoftwareSpec))).returns(T.untyped) }
def stable(&block)
- return @stable unless block
+ return T.must(@stable) unless block
- @stable.instance_eval(&block)
+ T.must(@stable).instance_eval(&block)
end
# @!attribute [w] head
@@ -3790,11 +3912,15 @@ class Formula
# ```ruby
# head "https://hg.is.awesome.but.git.has.won.example.com/", using: :hg
# ```
+ sig {
+ params(val: T.nilable(String), specs: T::Hash[Symbol, T.untyped], block: T.nilable(T.proc.void))
+ .returns(T.untyped)
+ }
def head(val = nil, specs = {}, &block)
if block
- @head.instance_eval(&block)
+ T.must(@head).instance_eval(&block)
elsif val
- @head.url(val, specs)
+ T.must(@head).url(val, specs)
else
@head
end
@@ -3824,6 +3950,7 @@ class Formula
# Specify a Go resource.
#
# @api public
+ sig { params(name: String, block: T.nilable(T.proc.void)).void }
def go_resource(name, &block)
odisabled "`Formula.go_resource`", "Go modules"
specs.each { |spec| spec.go_resource(name, &block) }
@@ -3892,6 +4019,7 @@ class Formula
# ```
#
# @api public
+ sig { params(dep: T.any(String, Symbol, T::Hash[String, T.untyped])).void }
def depends_on(dep)
specs.each { |spec| spec.depends_on(dep) }
end
@@ -3939,6 +4067,7 @@ class Formula
# ```
#
# @api public
+ sig { params(name: String, description: String).void }
def option(name, description = "")
specs.each { |spec| spec.option(name, description) }
end
@@ -3955,6 +4084,7 @@ class Formula
# ```
#
# @api public
+ sig { params(hash: T::Hash[String, String]).void }
def deprecated_option(hash)
specs.each { |spec| spec.deprecated_option(hash) }
end
@@ -4009,6 +4139,9 @@ class Formula
#
# @see https://docs.brew.sh/Formula-Cookbook#patches Patches
# @api public
+ sig {
+ params(strip: T.any(String, Symbol), src: T.any(NilClass, String, Symbol), block: T.nilable(T.proc.void)).void
+ }
def patch(strip = :p1, src = nil, &block)
specs.each { |spec| spec.patch(strip, src, &block) }
end
@@ -4022,9 +4155,10 @@ class Formula
# ```
#
# @api public
+ sig { params(names: T.untyped).void }
def conflicts_with(*names)
- opts = names.last.is_a?(Hash) ? names.pop : {}
- names.each { |name| conflicts << FormulaConflict.new(name, opts[:because]) }
+ opts = T.let(names.last.is_a?(Hash) ? names.pop : {}, T::Hash[Symbol, T.untyped])
+ names.each { |name| T.must(conflicts) << FormulaConflict.new(name, opts[:because]) }
end
# Skip cleaning paths in a formula.
@@ -4046,10 +4180,11 @@ class Formula
# ```
#
# @api public
+ sig { params(paths: T.any(String, Symbol)).returns(T::Set[T.any(String, Symbol)]) }
def skip_clean(*paths)
paths.flatten!
# Specifying :all is deprecated and will become an error
- skip_clean_paths.merge(paths)
+ T.must(skip_clean_paths).merge(paths)
end
# Software that will not be symlinked into the `brew --prefix` and will
@@ -4076,13 +4211,15 @@ class Formula
# ```
#
# @api public
+ sig { params(reason: T.any(String, Symbol), explanation: String).void }
def keg_only(reason, explanation = "")
- @keg_only_reason = KegOnlyReason.new(reason, explanation)
+ @keg_only_reason = T.let(KegOnlyReason.new(reason, explanation), T.nilable(KegOnlyReason))
end
# Pass `:skip` to this method to disable post-install stdlib checking.
#
# @api public
+ sig { params(check_type: Symbol).void }
def cxxstdlib_check(check_type)
define_method(:skip_cxxstdlib_check?) { true } if check_type == :skip
end
@@ -4118,6 +4255,7 @@ class Formula
# ```
#
# @api public
+ sig { params(compiler: T.any(Symbol, T::Hash[Symbol, String]), block: T.proc.void).void }
def fails_with(compiler, &block)
specs.each { |spec| spec.fails_with(compiler, &block) }
end
@@ -4133,6 +4271,7 @@ class Formula
# @see .fails_with
#
# @api public
+ sig { params(standards: String).void }
def needs(*standards)
specs.each { |spec| spec.needs(*standards) }
end
@@ -4173,6 +4312,7 @@ class Formula
# @see https://docs.brew.sh/Formula-Cookbook#add-a-test-to-the-formula Tests
# @return [Boolean]
# @api public
+ sig { params(block: T.proc.returns(T.untyped)).returns(T.untyped) }
def test(&block)
define_method(:test, &block)
end
@@ -4195,10 +4335,11 @@ class Formula
#
# @!attribute [w] livecheck
# @api public
+ sig { params(block: T.nilable(T.proc.bind(Livecheck).returns(T.untyped))).returns(T.untyped) }
def livecheck(&block)
return @livecheck unless block
- @livecheck_defined = true
+ @livecheck_defined = T.let(true, T.nilable(T::Boolean))
@livecheck.instance_eval(&block)
end
@@ -4217,10 +4358,14 @@ class Formula
#
# @!attribute [w] service
# @api public
+ sig {
+ params(block: T.nilable(T.proc.returns(T.untyped)))
+ .returns(T.nilable(T.proc.returns(T.untyped)))
+ }
def service(&block)
return @service_block unless block
- @service_block = block
+ @service_block = T.let(block, T.nilable(T.proc.returns(T.untyped)))
end
# Defines whether the {Formula}'s bottle can be used on the given Homebrew
@@ -4248,9 +4393,15 @@ class Formula
# ```
#
# @api public
+ sig {
+ params(
+ only_if: T.nilable(Symbol),
+ block: T.nilable(T.proc.params(arg0: T.untyped).returns(T.any(T::Boolean, Symbol))),
+ ).returns(T.any(T::Boolean, Symbol))
+ }
def pour_bottle?(only_if: nil, &block)
- @pour_bottle_check = PourBottleCheck.new(self)
- @pour_bottle_only_if = only_if
+ @pour_bottle_check = T.let(PourBottleCheck.new(self), T.nilable(PourBottleCheck))
+ @pour_bottle_only_if = T.let(only_if, T.nilable(Symbol))
if only_if.present? && block.present?
raise ArgumentError, "Do not pass both a preset condition and a block to `pour_bottle?`"
@@ -4283,7 +4434,7 @@ class Formula
raise ArgumentError, "Invalid preset `pour_bottle?` condition" if only_if.present?
end
- @pour_bottle_check.instance_eval(&block)
+ @pour_bottle_check.instance_eval(&T.unsafe(block))
end
# Deprecates a {Formula} (on the given date) so a warning is
@@ -4307,13 +4458,14 @@ class Formula
# @see https://docs.brew.sh/Deprecating-Disabling-and-Removing-Formulae
# @see DeprecateDisable::FORMULA_DEPRECATE_DISABLE_REASONS
# @api public
+ sig { params(date: String, because: T.any(NilClass, String, Symbol), replacement: T.nilable(String)).void }
def deprecate!(date:, because:, replacement: nil)
- @deprecation_date = Date.parse(date)
- return if @deprecation_date > Date.today
+ @deprecation_date = T.let(Date.parse(date), T.nilable(Date))
+ return if T.must(@deprecation_date) > Date.today
- @deprecation_reason = because
- @deprecation_replacement = replacement
- @deprecated = true
+ @deprecation_reason = T.let(because, T.any(NilClass, String, Symbol))
+ @deprecation_replacement = T.let(replacement, T.nilable(String))
+ T.must(@deprecated = T.let(true, T.nilable(T::Boolean)))
end
# Whether this {Formula} is deprecated (i.e. warns on installation).
@@ -4327,22 +4479,22 @@ class Formula
# The date that this {Formula} was or becomes deprecated.
# Returns `nil` if no date is specified.
#
- # @return Date
# @see .deprecate!
+ sig { returns(T.nilable(Date)) }
attr_reader :deprecation_date
# The reason for deprecation of a {Formula}.
#
# @return [nil] if no reason was provided or the formula is not deprecated.
- # @return [String, Symbol]
# @see .deprecate!
+ sig { returns(T.any(NilClass, String, Symbol)) }
attr_reader :deprecation_reason
# The replacement for a deprecated {Formula}.
#
# @return [nil] if no replacement was provided or the formula is not deprecated.
- # @return [String]
# @see .deprecate!
+ sig { returns(T.nilable(String)) }
attr_reader :deprecation_replacement
# Disables a {Formula} (on the given date) so it cannot be
@@ -4366,19 +4518,20 @@ class Formula
# @see https://docs.brew.sh/Deprecating-Disabling-and-Removing-Formulae
# @see DeprecateDisable::FORMULA_DEPRECATE_DISABLE_REASONS
# @api public
+ sig { params(date: String, because: T.any(NilClass, String, Symbol), replacement: T.nilable(String)).void }
def disable!(date:, because:, replacement: nil)
- @disable_date = Date.parse(date)
+ @disable_date = T.let(Date.parse(date), T.nilable(Date))
- if @disable_date > Date.today
- @deprecation_reason = because
- @deprecation_replacement = replacement
- @deprecated = true
+ if T.must(@disable_date) > Date.today
+ @deprecation_reason = T.let(because, T.any(NilClass, String, Symbol))
+ @deprecation_replacement = T.let(replacement, T.nilable(String))
+ @deprecated = T.let(true, T.nilable(T::Boolean))
return
end
- @disable_reason = because
- @disable_replacement = replacement
- @disabled = true
+ @disable_reason = T.let(because, T.nilable(T.any(String, Symbol)))
+ @disable_replacement = T.let(replacement, T.nilable(String))
+ @disabled = T.let(true, T.nilable(T::Boolean))
end
# Whether this {Formula} is disabled (i.e. cannot be installed).
@@ -4393,22 +4546,22 @@ class Formula
# The date that this {Formula} was or becomes disabled.
# Returns `nil` if no date is specified.
#
- # @return Date
# @see .disable!
+ sig { returns(T.nilable(Date)) }
attr_reader :disable_date
# The reason this {Formula} is disabled.
# Returns `nil` if no reason was provided or the formula is not disabled.
#
- # @return [String, Symbol]
# @see .disable!
+ sig { returns(T.any(NilClass, String, Symbol)) }
attr_reader :disable_reason
# The replacement for a disabled {Formula}.
# Returns `nil` if no reason was provided or the formula is not disabled.
#
- # @return [String]
# @see .disable!
+ sig { returns(T.nilable(String)) }
attr_reader :disable_replacement
# Permit overwriting certain files while linking.
@@ -4425,9 +4578,10 @@ class Formula
# ```ruby
# link_overwrite "share/man/man1/baz-*"
# ```
+ sig { params(paths: String).returns(T::Set[String]) }
def link_overwrite(*paths)
paths.flatten!
- link_overwrite_paths.merge(paths)
+ T.must(link_overwrite_paths).merge(paths)
end
end
end
diff --git a/Library/Homebrew/formula_cellar_checks.rb b/Library/Homebrew/formula_cellar_checks.rb
index 26e4f2f066..0e70e79cc3 100644
--- a/Library/Homebrew/formula_cellar_checks.rb
+++ b/Library/Homebrew/formula_cellar_checks.rb
@@ -307,7 +307,7 @@ module FormulaCellarChecks
return unless formula.service?
return unless formula.service.command?
- "Service command does not exist" unless File.exist?(formula.service.command.first)
+ "Service command does not exist" unless File.exist?(T.must(formula.service.command).first)
end
sig { params(formula: Formula).returns(T.nilable(String)) }
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index 430fd47db7..e87c14df85 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -1230,7 +1230,7 @@ on_request: installed_on_request?, options:)
return keg_formula_path if formula.loaded_from_api?
return keg_formula_path if formula.local_bottle_path.present?
- tap_formula_path = formula.specified_path
+ tap_formula_path = T.must(formula.specified_path)
return keg_formula_path unless tap_formula_path.exist?
begin
diff --git a/Library/Homebrew/language/java.rb b/Library/Homebrew/language/java.rb
index c89cbe7334..e0248c41cd 100644
--- a/Library/Homebrew/language/java.rb
+++ b/Library/Homebrew/language/java.rb
@@ -16,7 +16,7 @@ module Language
next false unless f.any_version_installed?
unless version.zero?
- major = f.any_installed_version.major
+ major = T.must(f.any_installed_version).major
next false if major < version
next false if major > version && !can_be_newer
end
diff --git a/Library/Homebrew/language/python.rb b/Library/Homebrew/language/python.rb
index 58ba404901..6428bce228 100644
--- a/Library/Homebrew/language/python.rb
+++ b/Library/Homebrew/language/python.rb
@@ -340,7 +340,10 @@ module Language
version = rp.match %r{^#{HOMEBREW_CELLAR}/python@(.*?)/}o
version = "@#{version.captures.first}" unless version.nil?
- new_target = rp.sub %r{#{HOMEBREW_CELLAR}/python#{version}/[^/]+}, Formula["python#{version}"].opt_prefix
+ new_target = rp.sub(
+ %r{#{HOMEBREW_CELLAR}/python#{version}/[^/]+},
+ Formula["python#{version}"].opt_prefix.to_s,
+ )
f.unlink
f.make_symlink new_target
end
@@ -351,7 +354,10 @@ module Language
version = prefix_path.match %r{^#{HOMEBREW_CELLAR}/python@(.*?)/}o
version = "@#{version.captures.first}" unless version.nil?
- prefix_path.sub! %r{^#{HOMEBREW_CELLAR}/python#{version}/[^/]+}, Formula["python#{version}"].opt_prefix
+ prefix_path.sub!(
+ %r{^#{HOMEBREW_CELLAR}/python#{version}/[^/]+},
+ Formula["python#{version}"].opt_prefix.to_s,
+ )
prefix_file.atomic_write prefix_path
end
@@ -362,7 +368,7 @@ module Language
cfg = cfg_file.read
framework = "Frameworks/Python.framework/Versions"
cfg.match(%r{= *(#{HOMEBREW_CELLAR}/(python@[\d.]+)/[^/]+(?:/#{framework}/[\d.]+)?/bin)}) do |match|
- cfg.sub! match[1].to_s, Formula[match[2]].opt_bin
+ cfg.sub! match[1].to_s, Formula[T.must(match[2])].opt_bin.to_s
cfg_file.atomic_write cfg
end
end