Merge branch 'master' into move-cask/cmd/uninstall

This commit is contained in:
hyuraku 2023-03-12 11:49:06 +09:00 committed by GitHub
commit da6f48dbd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
74 changed files with 808 additions and 786 deletions

View File

@ -189,14 +189,7 @@ Naming/MethodParameterName:
- AllowedNames - AllowedNames
AllowedNames: AllowedNames:
[ [
"a", "pr", # TODO: Remove if https://github.com/rubocop/rubocop/pull/11690 is merged or we change the variable names.
"b",
"c1",
"c2",
"e",
"f",
"o",
"pr",
] ]
# Both styles are used depending on context, # Both styles are used depending on context,
@ -324,7 +317,6 @@ Style/AutoResourceCleanup:
Style/BarePercentLiterals: Style/BarePercentLiterals:
EnforcedStyle: percent_q EnforcedStyle: percent_q
# make rspec formatting more flexible
Style/BlockDelimiters: Style/BlockDelimiters:
BracesRequiredMethods: BracesRequiredMethods:
- "sig" - "sig"

View File

@ -58,7 +58,8 @@ module Homebrew
skip_download = target.exist? && skip_download = target.exist? &&
!target.empty? && !target.empty? &&
(Homebrew::EnvConfig.no_auto_update? || (!Homebrew.auto_update_command? ||
Homebrew::EnvConfig.no_auto_update? ||
((Time.now - Homebrew::EnvConfig.api_auto_update_secs.to_i) < target.mtime)) ((Time.now - Homebrew::EnvConfig.api_auto_update_secs.to_i) < target.mtime))
skip_download ||= Homebrew.running_as_root_but_not_owned_by_root? skip_download ||= Homebrew.running_as_root_but_not_owned_by_root?

View File

@ -269,17 +269,7 @@ auto-update() {
# If we've checked for updates, we don't need to check again. # If we've checked for updates, we don't need to check again.
export HOMEBREW_AUTO_UPDATE_CHECKED="1" export HOMEBREW_AUTO_UPDATE_CHECKED="1"
AUTO_UPDATE_COMMANDS=( if [[ -n "${HOMEBREW_AUTO_UPDATE_COMMAND}" ]]
install
upgrade
bump-formula-pr
bump-cask-pr
bundle
release
)
if check-array-membership "${HOMEBREW_COMMAND}" "${AUTO_UPDATE_COMMANDS[@]}" ||
[[ "${HOMEBREW_COMMAND}" == "tap" && "${HOMEBREW_ARG_COUNT}" -gt 1 ]]
then then
export HOMEBREW_AUTO_UPDATING="1" export HOMEBREW_AUTO_UPDATING="1"
@ -816,6 +806,22 @@ then
unset HOMEBREW_RUBY_WARNINGS unset HOMEBREW_RUBY_WARNINGS
fi fi
# Check for commands that should call `brew update --auto-update` first.
AUTO_UPDATE_COMMANDS=(
install
outdated
upgrade
bump-formula-pr
bump-cask-pr
bundle
release
)
if check-array-membership "${HOMEBREW_COMMAND}" "${AUTO_UPDATE_COMMANDS[@]}" ||
[[ "${HOMEBREW_COMMAND}" == "tap" && "${HOMEBREW_ARG_COUNT}" -gt 1 ]]
then
export HOMEBREW_AUTO_UPDATE_COMMAND="1"
fi
# Disable Ruby options we don't need. # Disable Ruby options we don't need.
export HOMEBREW_RUBY_DISABLE_OPTIONS="--disable=gems,rubyopt" export HOMEBREW_RUBY_DISABLE_OPTIONS="--disable=gems,rubyopt"

View File

@ -198,19 +198,19 @@ class Build
keg.detect_cxx_stdlibs(skip_executables: true) keg.detect_cxx_stdlibs(skip_executables: true)
end end
def fixopt(f) def fixopt(formula)
path = if f.linked_keg.directory? && f.linked_keg.symlink? path = if formula.linked_keg.directory? && formula.linked_keg.symlink?
f.linked_keg.resolved_path formula.linked_keg.resolved_path
elsif f.prefix.directory? elsif formula.prefix.directory?
f.prefix formula.prefix
elsif (kids = f.rack.children).size == 1 && kids.first.directory? elsif (kids = formula.rack.children).size == 1 && kids.first.directory?
kids.first kids.first
else else
raise raise
end end
Keg.new(path).optlink(verbose: args.verbose?) Keg.new(path).optlink(verbose: args.verbose?)
rescue rescue
raise "#{f.opt_prefix} not present or broken\nPlease reinstall #{f.full_name}. Sorry :(" raise "#{formula.opt_prefix} not present or broken\nPlease reinstall #{formula.full_name}. Sorry :("
end end
end end

View File

@ -18,9 +18,9 @@ class BuildEnvironment
self self
end end
sig { params(o: Symbol).returns(T.self_type) } sig { params(option: Symbol).returns(T.self_type) }
def <<(o) def <<(option)
@settings << o @settings << option
self self
end end
@ -68,21 +68,21 @@ class BuildEnvironment
KEYS & env.keys KEYS & env.keys
end end
sig { params(env: T::Hash[String, T.nilable(T.any(String, Pathname))], f: IO).void } sig { params(env: T::Hash[String, T.nilable(T.any(String, Pathname))], out: IO).void }
def self.dump(env, f = $stdout) def self.dump(env, out = $stdout)
keys = self.keys(env) keys = self.keys(env)
keys -= %w[CC CXX OBJC OBJCXX] if env["CC"] == env["HOMEBREW_CC"] keys -= %w[CC CXX OBJC OBJCXX] if env["CC"] == env["HOMEBREW_CC"]
keys.each do |key| keys.each do |key|
value = env.fetch(key) value = env.fetch(key)
s = +"#{key}: #{value}" string = +"#{key}: #{value}"
case key case key
when "CC", "CXX", "LD" when "CC", "CXX", "LD"
s << " => #{Pathname.new(value).realpath}" if value.present? && File.symlink?(value) string << " => #{Pathname.new(value).realpath}" if value.present? && File.symlink?(value)
end end
s.freeze string.freeze
f.puts s out.puts string
end end
end end
end end

View File

@ -14,7 +14,6 @@ require "cask/cmd/audit"
require "cask/cmd/fetch" require "cask/cmd/fetch"
require "cask/cmd/install" require "cask/cmd/install"
require "cask/cmd/reinstall" require "cask/cmd/reinstall"
require "cask/cmd/upgrade"
module Cask module Cask
# Implementation of the `brew cask` command-line interface. # Implementation of the `brew cask` command-line interface.

View File

@ -1,257 +0,0 @@
# typed: false
# frozen_string_literal: true
require "env_config"
require "cask/config"
module Cask
class Cmd
# Cask implementation of the `brew upgrade` command.
#
# @api private
class Upgrade < AbstractCommand
extend T::Sig
OPTIONS = [
[:switch, "--skip-cask-deps", {
description: "Skip installing cask dependencies.",
}],
[:switch, "-g", "--greedy", {
description: "Also include casks with `auto_updates true` or `version :latest`.",
}],
[:switch, "--greedy-latest", {
description: "Also include casks with `version :latest`.",
}],
[:switch, "--greedy-auto-updates", {
description: "Also include casks with `auto_updates true`.",
}],
].freeze
sig { returns(Homebrew::CLI::Parser) }
def self.parser
super do
switch "--force",
description: "Force overwriting existing files."
switch "--dry-run",
description: "Show what would be upgraded, but do not actually upgrade anything."
OPTIONS.map(&:dup).each do |option|
kwargs = option.pop
send(*option, **kwargs)
end
end
end
sig { void }
def run
verbose = ($stdout.tty? || args.verbose?) && !args.quiet?
self.class.upgrade_casks(
*casks,
force: args.force?,
greedy: args.greedy?,
greedy_latest: args.greedy_latest?,
greedy_auto_updates: args.greedy_auto_updates?,
dry_run: args.dry_run?,
binaries: args.binaries?,
quarantine: args.quarantine?,
require_sha: args.require_sha?,
skip_cask_deps: args.skip_cask_deps?,
verbose: verbose,
args: args,
)
end
sig {
params(
casks: Cask,
args: Homebrew::CLI::Args,
force: T.nilable(T::Boolean),
greedy: T.nilable(T::Boolean),
greedy_latest: T.nilable(T::Boolean),
greedy_auto_updates: T.nilable(T::Boolean),
dry_run: T.nilable(T::Boolean),
skip_cask_deps: T.nilable(T::Boolean),
verbose: T.nilable(T::Boolean),
binaries: T.nilable(T::Boolean),
quarantine: T.nilable(T::Boolean),
require_sha: T.nilable(T::Boolean),
).returns(T::Boolean)
}
def self.upgrade_casks(
*casks,
args:,
force: false,
greedy: false,
greedy_latest: false,
greedy_auto_updates: false,
dry_run: false,
skip_cask_deps: false,
verbose: false,
binaries: nil,
quarantine: nil,
require_sha: nil
)
quarantine = true if quarantine.nil?
outdated_casks = if casks.empty?
Caskroom.casks(config: Config.from_args(args)).select do |cask|
cask.outdated?(greedy: greedy, greedy_latest: greedy_latest,
greedy_auto_updates: greedy_auto_updates)
end
else
casks.select do |cask|
raise CaskNotInstalledError, cask if !cask.installed? && !force
if cask.outdated?(greedy: true)
true
elsif cask.version.latest?
opoo "Not upgrading #{cask.token}, the downloaded artifact has not changed"
false
else
opoo "Not upgrading #{cask.token}, the latest version is already installed"
false
end
end
end
manual_installer_casks = outdated_casks.select do |cask|
cask.artifacts.any?(Artifact::Installer::ManualInstaller)
end
if manual_installer_casks.present?
count = manual_installer_casks.count
ofail "Not upgrading #{count} `installer manual` #{::Utils.pluralize("cask", count)}."
puts manual_installer_casks.map(&:to_s)
outdated_casks -= manual_installer_casks
end
return false if outdated_casks.empty?
if casks.empty? && !greedy
if !greedy_auto_updates && !greedy_latest
ohai "Casks with 'auto_updates true' or 'version :latest' " \
"will not be upgraded; pass `--greedy` to upgrade them."
end
if greedy_auto_updates && !greedy_latest
ohai "Casks with 'version :latest' will not be upgraded; pass `--greedy-latest` to upgrade them."
end
if !greedy_auto_updates && greedy_latest
ohai "Casks with 'auto_updates true' will not be upgraded; pass `--greedy-auto-updates` to upgrade them."
end
end
verb = dry_run ? "Would upgrade" : "Upgrading"
oh1 "#{verb} #{outdated_casks.count} outdated #{::Utils.pluralize("package", outdated_casks.count)}:"
caught_exceptions = []
upgradable_casks = outdated_casks.map do |c|
if !c.installed_caskfile.exist? && c.tap.to_s == "homebrew/cask" &&
Homebrew::API::Cask.all_casks.key?(c.token)
odie <<~EOS
The cask '#{c.token}' was affected by a bug and cannot be upgraded as-is. To fix this, run:
brew reinstall --cask --force #{c.token}
EOS
end
[CaskLoader.load(c.installed_caskfile), c]
end
puts upgradable_casks
.map { |(old_cask, new_cask)| "#{new_cask.full_name} #{old_cask.version} -> #{new_cask.version}" }
.join("\n")
return true if dry_run
upgradable_casks.each do |(old_cask, new_cask)|
upgrade_cask(
old_cask, new_cask,
binaries: binaries, force: force, skip_cask_deps: skip_cask_deps, verbose: verbose,
quarantine: quarantine, require_sha: require_sha
)
rescue => e
caught_exceptions << e.exception("#{new_cask.full_name}: #{e}")
next
end
return true if caught_exceptions.empty?
raise MultipleCaskErrors, caught_exceptions if caught_exceptions.count > 1
raise caught_exceptions.first if caught_exceptions.count == 1
end
def self.upgrade_cask(
old_cask, new_cask,
binaries:, force:, quarantine:, require_sha:, skip_cask_deps:, verbose:
)
require "cask/installer"
start_time = Time.now
odebug "Started upgrade process for Cask #{old_cask}"
old_config = old_cask.config
old_options = {
binaries: binaries,
verbose: verbose,
force: force,
upgrade: true,
}.compact
old_cask_installer =
Installer.new(old_cask, **old_options)
new_cask.config = new_cask.default_config.merge(old_config)
new_options = {
binaries: binaries,
verbose: verbose,
force: force,
skip_cask_deps: skip_cask_deps,
require_sha: require_sha,
upgrade: true,
quarantine: quarantine,
}.compact
new_cask_installer =
Installer.new(new_cask, **new_options)
started_upgrade = false
new_artifacts_installed = false
begin
oh1 "Upgrading #{Formatter.identifier(old_cask)}"
# Start new cask's installation steps
new_cask_installer.check_conflicts
if (caveats = new_cask_installer.caveats)
puts caveats
end
new_cask_installer.fetch
# Move the old cask's artifacts back to staging
old_cask_installer.start_upgrade
# And flag it so in case of error
started_upgrade = true
# Install the new cask
new_cask_installer.stage
new_cask_installer.install_artifacts
new_artifacts_installed = true
# If successful, wipe the old cask from staging
old_cask_installer.finalize_upgrade
rescue => e
new_cask_installer.uninstall_artifacts if new_artifacts_installed
new_cask_installer.purge_versioned_files
old_cask_installer.revert_upgrade if started_upgrade
raise e
end
end_time = Time.now
Homebrew.messages.package_installed(new_cask.token, end_time - start_time)
end
end
end
end

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
module Cask module Cask

View File

@ -0,0 +1,7 @@
# typed: strict
module Cask
module Metadata
requires_ancestor { Cask }
end
end

View File

@ -0,0 +1,204 @@
# typed: false
# frozen_string_literal: true
require "env_config"
require "cask/config"
module Cask
# @api private
class Upgrade
extend T::Sig
sig {
params(
casks: Cask,
args: Homebrew::CLI::Args,
force: T.nilable(T::Boolean),
greedy: T.nilable(T::Boolean),
greedy_latest: T.nilable(T::Boolean),
greedy_auto_updates: T.nilable(T::Boolean),
dry_run: T.nilable(T::Boolean),
skip_cask_deps: T.nilable(T::Boolean),
verbose: T.nilable(T::Boolean),
binaries: T.nilable(T::Boolean),
quarantine: T.nilable(T::Boolean),
require_sha: T.nilable(T::Boolean),
).returns(T::Boolean)
}
def self.upgrade_casks(
*casks,
args:,
force: false,
greedy: false,
greedy_latest: false,
greedy_auto_updates: false,
dry_run: false,
skip_cask_deps: false,
verbose: false,
binaries: nil,
quarantine: nil,
require_sha: nil
)
quarantine = true if quarantine.nil?
outdated_casks = if casks.empty?
Caskroom.casks(config: Config.from_args(args)).select do |cask|
cask.outdated?(greedy: greedy, greedy_latest: greedy_latest,
greedy_auto_updates: greedy_auto_updates)
end
else
casks.select do |cask|
raise CaskNotInstalledError, cask if !cask.installed? && !force
if cask.outdated?(greedy: true)
true
elsif cask.version.latest?
opoo "Not upgrading #{cask.token}, the downloaded artifact has not changed"
false
else
opoo "Not upgrading #{cask.token}, the latest version is already installed"
false
end
end
end
manual_installer_casks = outdated_casks.select do |cask|
cask.artifacts.any?(Artifact::Installer::ManualInstaller)
end
if manual_installer_casks.present?
count = manual_installer_casks.count
ofail "Not upgrading #{count} `installer manual` #{::Utils.pluralize("cask", count)}."
puts manual_installer_casks.map(&:to_s)
outdated_casks -= manual_installer_casks
end
return false if outdated_casks.empty?
if casks.empty? && !greedy
if !greedy_auto_updates && !greedy_latest
ohai "Casks with 'auto_updates true' or 'version :latest' " \
"will not be upgraded; pass `--greedy` to upgrade them."
end
if greedy_auto_updates && !greedy_latest
ohai "Casks with 'version :latest' will not be upgraded; pass `--greedy-latest` to upgrade them."
end
if !greedy_auto_updates && greedy_latest
ohai "Casks with 'auto_updates true' will not be upgraded; pass `--greedy-auto-updates` to upgrade them."
end
end
verb = dry_run ? "Would upgrade" : "Upgrading"
oh1 "#{verb} #{outdated_casks.count} outdated #{::Utils.pluralize("package", outdated_casks.count)}:"
caught_exceptions = []
upgradable_casks = outdated_casks.map do |c|
if !c.installed_caskfile.exist? && c.tap.to_s == "homebrew/cask" &&
Homebrew::API::Cask.all_casks.key?(c.token)
odie <<~EOS
The cask '#{c.token}' was affected by a bug and cannot be upgraded as-is. To fix this, run:
brew reinstall --cask --force #{c.token}
EOS
end
[CaskLoader.load(c.installed_caskfile), c]
end
puts upgradable_casks
.map { |(old_cask, new_cask)| "#{new_cask.full_name} #{old_cask.version} -> #{new_cask.version}" }
.join("\n")
return true if dry_run
upgradable_casks.each do |(old_cask, new_cask)|
upgrade_cask(
old_cask, new_cask,
binaries: binaries, force: force, skip_cask_deps: skip_cask_deps, verbose: verbose,
quarantine: quarantine, require_sha: require_sha
)
rescue => e
caught_exceptions << e.exception("#{new_cask.full_name}: #{e}")
next
end
return true if caught_exceptions.empty?
raise MultipleCaskErrors, caught_exceptions if caught_exceptions.count > 1
raise caught_exceptions.first if caught_exceptions.count == 1
end
def self.upgrade_cask(
old_cask, new_cask,
binaries:, force:, quarantine:, require_sha:, skip_cask_deps:, verbose:
)
require "cask/installer"
start_time = Time.now
odebug "Started upgrade process for Cask #{old_cask}"
old_config = old_cask.config
old_options = {
binaries: binaries,
verbose: verbose,
force: force,
upgrade: true,
}.compact
old_cask_installer =
Installer.new(old_cask, **old_options)
new_cask.config = new_cask.default_config.merge(old_config)
new_options = {
binaries: binaries,
verbose: verbose,
force: force,
skip_cask_deps: skip_cask_deps,
require_sha: require_sha,
upgrade: true,
quarantine: quarantine,
}.compact
new_cask_installer =
Installer.new(new_cask, **new_options)
started_upgrade = false
new_artifacts_installed = false
begin
oh1 "Upgrading #{Formatter.identifier(old_cask)}"
# Start new cask's installation steps
new_cask_installer.check_conflicts
if (caveats = new_cask_installer.caveats)
puts caveats
end
new_cask_installer.fetch
# Move the old cask's artifacts back to staging
old_cask_installer.start_upgrade
# And flag it so in case of error
started_upgrade = true
# Install the new cask
new_cask_installer.stage
new_cask_installer.install_artifacts
new_artifacts_installed = true
# If successful, wipe the old cask from staging
old_cask_installer.finalize_upgrade
rescue => e
new_cask_installer.uninstall_artifacts if new_artifacts_installed
new_cask_installer.purge_versioned_files
old_cask_installer.revert_upgrade if started_upgrade
raise e
end
end_time = Time.now
Homebrew.messages.package_installed(new_cask.token, end_time - start_time)
end
end
end

View File

@ -1,5 +1,4 @@
# typed: strict # typed: strict
# typed: false
class URL class URL
include Kernel include Kernel

View File

@ -9,21 +9,21 @@ require "language/python"
class Caveats class Caveats
extend Forwardable extend Forwardable
attr_reader :f attr_reader :formula
def initialize(f) def initialize(formula)
@f = f @formula = formula
end end
def caveats def caveats
caveats = [] caveats = []
begin begin
build = f.build build = formula.build
f.build = Tab.for_formula(f) formula.build = Tab.for_formula(formula)
s = f.caveats.to_s string = formula.caveats.to_s
caveats << "#{s.chomp}\n" unless s.empty? caveats << "#{string.chomp}\n" unless string.empty?
ensure ensure
f.build = build formula.build = build
end end
caveats << keg_only_text caveats << keg_only_text
@ -48,49 +48,49 @@ class Caveats
delegate [:empty?, :to_s] => :caveats delegate [:empty?, :to_s] => :caveats
def keg_only_text(skip_reason: false) def keg_only_text(skip_reason: false)
return unless f.keg_only? return unless formula.keg_only?
s = if skip_reason s = if skip_reason
"" ""
else else
<<~EOS <<~EOS
#{f.name} is keg-only, which means it was not symlinked into #{HOMEBREW_PREFIX}, #{formula.name} is keg-only, which means it was not symlinked into #{HOMEBREW_PREFIX},
because #{f.keg_only_reason.to_s.chomp}. because #{formula.keg_only_reason.to_s.chomp}.
EOS EOS
end.dup end.dup
if f.bin.directory? || f.sbin.directory? if formula.bin.directory? || formula.sbin.directory?
s << <<~EOS s << <<~EOS
If you need to have #{f.name} first in your PATH, run: If you need to have #{formula.name} first in your PATH, run:
EOS EOS
s << " #{Utils::Shell.prepend_path_in_profile(f.opt_bin.to_s)}\n" if f.bin.directory? s << " #{Utils::Shell.prepend_path_in_profile(formula.opt_bin.to_s)}\n" if formula.bin.directory?
s << " #{Utils::Shell.prepend_path_in_profile(f.opt_sbin.to_s)}\n" if f.sbin.directory? s << " #{Utils::Shell.prepend_path_in_profile(formula.opt_sbin.to_s)}\n" if formula.sbin.directory?
end end
if f.lib.directory? || f.include.directory? if formula.lib.directory? || formula.include.directory?
s << <<~EOS s << <<~EOS
For compilers to find #{f.name} you may need to set: For compilers to find #{formula.name} you may need to set:
EOS EOS
s << " #{Utils::Shell.export_value("LDFLAGS", "-L#{f.opt_lib}")}\n" if f.lib.directory? s << " #{Utils::Shell.export_value("LDFLAGS", "-L#{formula.opt_lib}")}\n" if formula.lib.directory?
s << " #{Utils::Shell.export_value("CPPFLAGS", "-I#{f.opt_include}")}\n" if f.include.directory? s << " #{Utils::Shell.export_value("CPPFLAGS", "-I#{formula.opt_include}")}\n" if formula.include.directory?
if which("pkg-config", ORIGINAL_PATHS) && if which("pkg-config", ORIGINAL_PATHS) &&
((f.lib/"pkgconfig").directory? || (f.share/"pkgconfig").directory?) ((formula.lib/"pkgconfig").directory? || (formula.share/"pkgconfig").directory?)
s << <<~EOS s << <<~EOS
For pkg-config to find #{f.name} you may need to set: For pkg-config to find #{formula.name} you may need to set:
EOS EOS
if (f.lib/"pkgconfig").directory? if (formula.lib/"pkgconfig").directory?
s << " #{Utils::Shell.export_value("PKG_CONFIG_PATH", "#{f.opt_lib}/pkgconfig")}\n" s << " #{Utils::Shell.export_value("PKG_CONFIG_PATH", "#{formula.opt_lib}/pkgconfig")}\n"
end end
if (f.share/"pkgconfig").directory? if (formula.share/"pkgconfig").directory?
s << " #{Utils::Shell.export_value("PKG_CONFIG_PATH", "#{f.opt_share}/pkgconfig")}\n" s << " #{Utils::Shell.export_value("PKG_CONFIG_PATH", "#{formula.opt_share}/pkgconfig")}\n"
end end
end end
end end
@ -100,7 +100,7 @@ class Caveats
private private
def keg def keg
@keg ||= [f.prefix, f.opt_prefix, f.linked_keg].map do |d| @keg ||= [formula.prefix, formula.opt_prefix, formula.linked_keg].map do |d|
Keg.new(d.resolved_path) Keg.new(d.resolved_path)
rescue rescue
nil nil
@ -119,7 +119,7 @@ class Caveats
installed << "completions" if completion_installed installed << "completions" if completion_installed
installed << "functions" if functions_installed installed << "functions" if functions_installed
root_dir = f.keg_only? ? f.opt_prefix : HOMEBREW_PREFIX root_dir = formula.keg_only? ? formula.opt_prefix : HOMEBREW_PREFIX
case shell case shell
when :bash when :bash
@ -141,55 +141,55 @@ class Caveats
end end
def elisp_caveats def elisp_caveats
return if f.keg_only? return if formula.keg_only?
return unless keg return unless keg
return unless keg.elisp_installed? return unless keg.elisp_installed?
<<~EOS <<~EOS
Emacs Lisp files have been installed to: Emacs Lisp files have been installed to:
#{HOMEBREW_PREFIX}/share/emacs/site-lisp/#{f.name} #{HOMEBREW_PREFIX}/share/emacs/site-lisp/#{formula.name}
EOS EOS
end end
def service_caveats def service_caveats
return if !f.plist && !f.service? && !keg&.plist_installed? return if !formula.plist && !formula.service? && !keg&.plist_installed?
return if f.service? && f.service.command.blank? return if formula.service? && formula.service.command.blank?
s = [] s = []
command = if f.service? command = if formula.service?
f.service.manual_command formula.service.manual_command
else else
f.plist_manual formula.plist_manual
end end
return <<~EOS if !which("launchctl") && f.plist return <<~EOS if !which("launchctl") && formula.plist
#{Formatter.warning("Warning:")} #{f.name} provides a launchd plist which can only be used on macOS! #{Formatter.warning("Warning:")} #{formula.name} provides a launchd plist which can only be used on macOS!
You can manually execute the service instead with: You can manually execute the service instead with:
#{command} #{command}
EOS EOS
# Brew services only works with these two tools # Brew services only works with these two tools
return <<~EOS if !which("systemctl") && !which("launchctl") && f.service? return <<~EOS if !which("systemctl") && !which("launchctl") && formula.service?
#{Formatter.warning("Warning:")} #{f.name} provides a service which can only be used on macOS or systemd! #{Formatter.warning("Warning:")} #{formula.name} provides a service which can only be used on macOS or systemd!
You can manually execute the service instead with: You can manually execute the service instead with:
#{command} #{command}
EOS EOS
is_running_service = f.service? && quiet_system("ps aux | grep #{f.service.command&.first}") is_running_service = formula.service? && quiet_system("ps aux | grep #{formula.service.command&.first}")
startup = f.service&.requires_root? || f.plist_startup startup = formula.service&.requires_root? || formula.plist_startup
if is_running_service || (f.plist && quiet_system("/bin/launchctl list #{f.plist_name} &>/dev/null")) if is_running_service || (formula.plist && quiet_system("/bin/launchctl list #{formula.plist_name} &>/dev/null"))
s << "To restart #{f.full_name} after an upgrade:" s << "To restart #{formula.full_name} after an upgrade:"
s << " #{startup ? "sudo " : ""}brew services restart #{f.full_name}" s << " #{startup ? "sudo " : ""}brew services restart #{formula.full_name}"
elsif startup elsif startup
s << "To start #{f.full_name} now and restart at startup:" s << "To start #{formula.full_name} now and restart at startup:"
s << " sudo brew services start #{f.full_name}" s << " sudo brew services start #{formula.full_name}"
else else
s << "To start #{f.full_name} now and restart at login:" s << "To start #{formula.full_name} now and restart at login:"
s << " brew services start #{f.full_name}" s << " brew services start #{formula.full_name}"
end end
if f.plist_manual || f.service? if formula.plist_manual || formula.service?
s << "Or, if you don't want/need a background service you can just run:" s << "Or, if you don't want/need a background service you can just run:"
s << " #{command}" s << " #{command}"
end end

View File

@ -14,8 +14,8 @@ class Cleaner
include Context include Context
# Create a cleaner for the given formula. # Create a cleaner for the given formula.
def initialize(f) def initialize(formula)
@f = f @formula = formula
end end
# Clean the keg of the formula. # Clean the keg of the formula.
@ -24,9 +24,9 @@ class Cleaner
# Many formulae include 'lib/charset.alias', but it is not strictly needed # Many formulae include 'lib/charset.alias', but it is not strictly needed
# and will conflict if more than one formula provides it # and will conflict if more than one formula provides it
observe_file_removal @f.lib/"charset.alias" observe_file_removal @formula.lib/"charset.alias"
[@f.bin, @f.sbin, @f.lib].each { |d| clean_dir(d) if d.exist? } [@formula.bin, @formula.sbin, @formula.lib].each { |dir| clean_dir(dir) if dir.exist? }
# Get rid of any info 'dir' files, so they don't conflict at the link stage # Get rid of any info 'dir' files, so they don't conflict at the link stage
# #
@ -47,11 +47,11 @@ class Cleaner
# [1]: https://github.com/Homebrew/brew/pull/11597 # [1]: https://github.com/Homebrew/brew/pull/11597
# [2]: https://github.com/Homebrew/homebrew-core/issues/100190 # [2]: https://github.com/Homebrew/homebrew-core/issues/100190
# [3]: https://github.com/Homebrew/brew/pull/13215 # [3]: https://github.com/Homebrew/brew/pull/13215
Dir.glob(@f.info/"**/dir").each do |f| Dir.glob(@formula.info/"**/dir").each do |file|
info_dir_file = Pathname(f) info_dir_file = Pathname(file)
next unless info_dir_file.file? next unless info_dir_file.file?
next if info_dir_file == @f.info/@f.name/"dir" next if info_dir_file == @formula.info/@formula.name/"dir"
next if @f.skip_clean?(info_dir_file) next if @formula.skip_clean?(info_dir_file)
observe_file_removal info_dir_file observe_file_removal info_dir_file
end end
@ -73,8 +73,8 @@ class Cleaner
def prune def prune
dirs = [] dirs = []
symlinks = [] symlinks = []
@f.prefix.find do |path| @formula.prefix.find do |path|
if path == @f.libexec || @f.skip_clean?(path) if path == @formula.libexec || @formula.skip_clean?(path)
Find.prune Find.prune
elsif path.symlink? elsif path.symlink?
symlinks << path symlinks << path
@ -121,7 +121,7 @@ class Cleaner
directory.find do |path| directory.find do |path|
path.extend(ObserverPathnameExtension) path.extend(ObserverPathnameExtension)
Find.prune if @f.skip_clean? path Find.prune if @formula.skip_clean? path
next if path.directory? next if path.directory?
@ -149,14 +149,14 @@ class Cleaner
require "language/perl" require "language/perl"
require "utils/shebang" require "utils/shebang"
basepath = @f.prefix.realpath basepath = @formula.prefix.realpath
basepath.find do |path| basepath.find do |path|
Find.prune if @f.skip_clean? path Find.prune if @formula.skip_clean? path
next if path.directory? || path.symlink? next if path.directory? || path.symlink?
begin begin
Utils::Shebang.rewrite_shebang Language::Perl::Shebang.detected_perl_shebang(@f), path Utils::Shebang.rewrite_shebang Language::Perl::Shebang.detected_perl_shebang(@formula), path
rescue ShebangDetectionError rescue ShebangDetectionError
break break
end end

View File

@ -155,21 +155,21 @@ module Homebrew
@cleaned_up_paths = Set.new @cleaned_up_paths = Set.new
end end
def self.install_formula_clean!(f, dry_run: false) def self.install_formula_clean!(formula, dry_run: false)
return if Homebrew::EnvConfig.no_install_cleanup? return if Homebrew::EnvConfig.no_install_cleanup?
return unless f.latest_version_installed? return unless formula.latest_version_installed?
return if skip_clean_formula?(f) return if skip_clean_formula?(formula)
if dry_run if dry_run
ohai "Would run `brew cleanup #{f}`" ohai "Would run `brew cleanup #{formula}`"
else else
ohai "Running `brew cleanup #{f}`..." ohai "Running `brew cleanup #{formula}`..."
end end
puts_no_install_cleanup_disable_message_if_not_already! puts_no_install_cleanup_disable_message_if_not_already!
return if dry_run return if dry_run
Cleanup.new.cleanup_formula(f) Cleanup.new.cleanup_formula(formula)
end end
def self.puts_no_install_cleanup_disable_message def self.puts_no_install_cleanup_disable_message
@ -187,11 +187,11 @@ module Homebrew
@puts_no_install_cleanup_disable_message_if_not_already = true @puts_no_install_cleanup_disable_message_if_not_already = true
end end
def self.skip_clean_formula?(f) def self.skip_clean_formula?(formula)
return false if Homebrew::EnvConfig.no_cleanup_formulae.blank? return false if Homebrew::EnvConfig.no_cleanup_formulae.blank?
@skip_clean_formulae ||= Homebrew::EnvConfig.no_cleanup_formulae.split(",") @skip_clean_formulae ||= Homebrew::EnvConfig.no_cleanup_formulae.split(",")
@skip_clean_formulae.include?(f.name) || (@skip_clean_formulae & f.aliases).present? @skip_clean_formulae.include?(formula.name) || (@skip_clean_formulae & formula.aliases).present?
end end
def self.periodic_clean_due? def self.periodic_clean_due?

View File

@ -249,11 +249,11 @@ module Homebrew
"digraph {\n#{dot_code}\n}" "digraph {\n#{dot_code}\n}"
end end
def self.graph_deps(f, dep_graph:, recursive:, args:) def self.graph_deps(formula, dep_graph:, recursive:, args:)
return if dep_graph.key?(f) return if dep_graph.key?(formula)
dependables = dependables(f, args: args) dependables = dependables(formula, args: args)
dep_graph[f] = dependables dep_graph[formula] = dependables
return unless recursive return unless recursive
dependables.each do |dep| dependables.each do |dep|
@ -274,19 +274,19 @@ module Homebrew
end end
end end
def self.dependables(f, args:) def self.dependables(formula, args:)
includes, ignores = args_includes_ignores(args) includes, ignores = args_includes_ignores(args)
deps = @use_runtime_dependencies ? f.runtime_dependencies : f.deps deps = @use_runtime_dependencies ? formula.runtime_dependencies : formula.deps
deps = reject_ignores(deps, ignores, includes) deps = reject_ignores(deps, ignores, includes)
reqs = reject_ignores(f.requirements, ignores, includes) if args.include_requirements? reqs = reject_ignores(formula.requirements, ignores, includes) if args.include_requirements?
reqs ||= [] reqs ||= []
reqs + deps reqs + deps
end end
def self.recursive_deps_tree(f, dep_stack:, prefix:, recursive:, args:) def self.recursive_deps_tree(formula, dep_stack:, prefix:, recursive:, args:)
dependables = dependables(f, args: args) dependables = dependables(formula, args: args)
max = dependables.length - 1 max = dependables.length - 1
dep_stack.push f.name dep_stack.push formula.name
dependables.each_with_index do |dep, i| dependables.each_with_index do |dep, i|
tree_lines = if i == max tree_lines = if i == max
"└──" "└──"

View File

@ -138,10 +138,10 @@ module Homebrew
opoo "Resource #{resource.name} reports different sha256: #{e.expected}" opoo "Resource #{resource.name} reports different sha256: #{e.expected}"
end end
def self.fetch_formula(f, args:) def self.fetch_formula(formula, args:)
fetch_fetchable f, args: args fetch_fetchable formula, args: args
rescue ChecksumMismatchError => e rescue ChecksumMismatchError => e
retry if retry_fetch?(f, args: args) retry if retry_fetch?(formula, args: args)
opoo "Formula reports different sha256: #{e.expected}" opoo "Formula reports different sha256: #{e.expected}"
end end
@ -159,18 +159,18 @@ module Homebrew
Homebrew.failed = true Homebrew.failed = true
end end
def self.retry_fetch?(f, args:) def self.retry_fetch?(formula, args:)
@fetch_tries ||= Hash.new { |h, k| h[k] = 1 } @fetch_tries ||= Hash.new { |h, k| h[k] = 1 }
if args.retry? && (@fetch_tries[f] < FETCH_MAX_TRIES) if args.retry? && (@fetch_tries[formula] < FETCH_MAX_TRIES)
wait = 2 ** @fetch_tries[f] wait = 2 ** @fetch_tries[formula]
remaining = FETCH_MAX_TRIES - @fetch_tries[f] remaining = FETCH_MAX_TRIES - @fetch_tries[formula]
what = Utils.pluralize("tr", remaining, plural: "ies", singular: "y") what = Utils.pluralize("tr", remaining, plural: "ies", singular: "y")
ohai "Retrying download in #{wait}s... (#{remaining} #{what} left)" ohai "Retrying download in #{wait}s... (#{remaining} #{what} left)"
sleep wait sleep wait
f.clear_cache formula.clear_cache
@fetch_tries[f] += 1 @fetch_tries[formula] += 1
true true
else else
Homebrew.failed = true Homebrew.failed = true
@ -178,15 +178,15 @@ module Homebrew
end end
end end
def self.fetch_fetchable(f, args:) def self.fetch_fetchable(formula, args:)
f.clear_cache if args.force? formula.clear_cache if args.force?
already_fetched = f.cached_download.exist? already_fetched = formula.cached_download.exist?
begin begin
download = f.fetch(verify_download_integrity: false) download = formula.fetch(verify_download_integrity: false)
rescue DownloadError rescue DownloadError
retry if retry_fetch?(f, args: args) retry if retry_fetch?(formula, args: args)
raise raise
end end
@ -195,6 +195,6 @@ module Homebrew
puts "Downloaded to: #{download}" unless already_fetched puts "Downloaded to: #{download}" unless already_fetched
puts "SHA256: #{download.sha256}" puts "SHA256: #{download.sha256}"
f.verify_download_integrity(download) formula.verify_download_integrity(download)
end end
end end

View File

@ -35,22 +35,24 @@ module Homebrew
end end
end end
def gistify_logs(f, args:) def gistify_logs(formula, args:)
files = load_logs(f.logs) files = load_logs(formula.logs)
build_time = f.logs.ctime build_time = formula.logs.ctime
timestamp = build_time.strftime("%Y-%m-%d_%H-%M-%S") timestamp = build_time.strftime("%Y-%m-%d_%H-%M-%S")
s = StringIO.new s = StringIO.new
SystemConfig.dump_verbose_config s SystemConfig.dump_verbose_config s
# Dummy summary file, asciibetically first, to control display title of gist # Dummy summary file, asciibetically first, to control display title of gist
files["# #{f.name} - #{timestamp}.txt"] = { content: brief_build_info(f, with_hostname: args.with_hostname?) } files["# #{formula.name} - #{timestamp}.txt"] = {
content: brief_build_info(formula, with_hostname: args.with_hostname?),
}
files["00.config.out"] = { content: s.string } files["00.config.out"] = { content: s.string }
files["00.doctor.out"] = { content: Utils.popen_read("#{HOMEBREW_PREFIX}/bin/brew", "doctor", err: :out) } files["00.doctor.out"] = { content: Utils.popen_read("#{HOMEBREW_PREFIX}/bin/brew", "doctor", err: :out) }
unless f.core_formula? unless formula.core_formula?
tap = <<~EOS tap = <<~EOS
Formula: #{f.name} Formula: #{formula.name}
Tap: #{f.tap} Tap: #{formula.tap}
Path: #{f.path} Path: #{formula.path}
EOS EOS
files["00.tap.out"] = { content: tap } files["00.tap.out"] = { content: tap }
end end
@ -58,10 +60,10 @@ module Homebrew
odie "`brew gist-logs` requires HOMEBREW_GITHUB_API_TOKEN to be set!" if GitHub::API.credentials_type == :none odie "`brew gist-logs` requires HOMEBREW_GITHUB_API_TOKEN to be set!" if GitHub::API.credentials_type == :none
# Description formatted to work well as page title when viewing gist # Description formatted to work well as page title when viewing gist
descr = if f.core_formula? descr = if formula.core_formula?
"#{f.name} on #{OS_VERSION} - Homebrew build logs" "#{formula.name} on #{OS_VERSION} - Homebrew build logs"
else else
"#{f.name} (#{f.full_name}) on #{OS_VERSION} - Homebrew build logs" "#{formula.name} (#{formula.full_name}) on #{OS_VERSION} - Homebrew build logs"
end end
begin begin
@ -73,22 +75,24 @@ module Homebrew
EOS EOS
end end
url = GitHub.create_issue(f.tap, "#{f.name} failed to build on #{MacOS.full_version}", url) if args.new_issue? if args.new_issue?
url = GitHub.create_issue(formula.tap, "#{formula.name} failed to build on #{MacOS.full_version}", url)
end
puts url if url puts url if url
end end
def brief_build_info(f, with_hostname:) def brief_build_info(formula, with_hostname:)
build_time_str = f.logs.ctime.strftime("%Y-%m-%d %H:%M:%S") build_time_string = formula.logs.ctime.strftime("%Y-%m-%d %H:%M:%S")
s = +<<~EOS string = +<<~EOS
Homebrew build logs for #{f.full_name} on #{OS_VERSION} Homebrew build logs for #{formula.full_name} on #{OS_VERSION}
EOS EOS
if with_hostname if with_hostname
hostname = Socket.gethostname hostname = Socket.gethostname
s << "Host: #{hostname}\n" string << "Host: #{hostname}\n"
end end
s << "Build date: #{build_time_str}\n" string << "Build date: #{build_time_string}\n"
s.freeze string.freeze
end end
# Causes some terminals to display secure password entry indicators. # Causes some terminals to display secure password entry indicators.

View File

@ -247,40 +247,40 @@ module Homebrew
end end
end end
def github_info(f) def github_info(formula)
return f.path if f.tap.blank? || f.tap.remote.blank? return formula.path if formula.tap.blank? || formula.tap.remote.blank?
path = case f path = case formula
when Formula when Formula
f.path.relative_path_from(f.tap.path) formula.path.relative_path_from(formula.tap.path)
when Cask::Cask when Cask::Cask
return "#{f.tap.default_remote}/blob/HEAD/Casks/#{f.token}.rb" if f.sourcefile_path.blank? return "#{formula.tap.default_remote}/blob/HEAD/Casks/#{formula.token}.rb" if formula.sourcefile_path.blank?
f.sourcefile_path.relative_path_from(f.tap.path) formula.sourcefile_path.relative_path_from(formula.tap.path)
end end
github_remote_path(f.tap.remote, path) github_remote_path(formula.tap.remote, path)
end end
def info_formula(f, args:) def info_formula(formula, args:)
specs = [] specs = []
if (stable = f.stable) if (stable = formula.stable)
s = "stable #{stable.version}" string = "stable #{stable.version}"
s += " (bottled)" if stable.bottled? && f.pour_bottle? string += " (bottled)" if stable.bottled? && formula.pour_bottle?
specs << s specs << string
end end
specs << "HEAD" if f.head specs << "HEAD" if formula.head
attrs = [] attrs = []
attrs << "pinned at #{f.pinned_version}" if f.pinned? attrs << "pinned at #{formula.pinned_version}" if formula.pinned?
attrs << "keg-only" if f.keg_only? attrs << "keg-only" if formula.keg_only?
puts "#{oh1_title(f.full_name)}: #{specs * ", "}#{" [#{attrs * ", "}]" unless attrs.empty?}" puts "#{oh1_title(formula.full_name)}: #{specs * ", "}#{" [#{attrs * ", "}]" unless attrs.empty?}"
puts f.desc if f.desc puts formula.desc if formula.desc
puts Formatter.url(f.homepage) if f.homepage puts Formatter.url(formula.homepage) if formula.homepage
deprecate_disable_type, deprecate_disable_reason = DeprecateDisable.deprecate_disable_info f deprecate_disable_type, deprecate_disable_reason = DeprecateDisable.deprecate_disable_info formula
if deprecate_disable_type.present? if deprecate_disable_type.present?
if deprecate_disable_reason.present? if deprecate_disable_reason.present?
puts "#{deprecate_disable_type.capitalize} because it #{deprecate_disable_reason}!" puts "#{deprecate_disable_type.capitalize} because it #{deprecate_disable_reason}!"
@ -289,9 +289,9 @@ module Homebrew
end end
end end
conflicts = f.conflicts.map do |c| conflicts = formula.conflicts.map do |conflict|
reason = " (because #{c.reason})" if c.reason reason = " (because #{conflict.reason})" if conflict.reason
"#{c.name}#{reason}" "#{conflict.name}#{reason}"
end.sort! end.sort!
unless conflicts.empty? unless conflicts.empty?
puts <<~EOS puts <<~EOS
@ -300,7 +300,7 @@ module Homebrew
EOS EOS
end end
kegs = f.installed_kegs kegs = formula.installed_kegs
heads, versioned = kegs.partition { |k| k.version.head? } heads, versioned = kegs.partition { |k| k.version.head? }
kegs = [ kegs = [
*heads.sort_by { |k| -Tab.for_keg(k).time.to_i }, *heads.sort_by { |k| -Tab.for_keg(k).time.to_i },
@ -316,37 +316,37 @@ module Homebrew
end end
end end
puts "From: #{Formatter.url(github_info(f))}" puts "From: #{Formatter.url(github_info(formula))}"
puts "License: #{SPDX.license_expression_to_string f.license}" if f.license.present? puts "License: #{SPDX.license_expression_to_string formula.license}" if formula.license.present?
unless f.deps.empty? unless formula.deps.empty?
ohai "Dependencies" ohai "Dependencies"
%w[build required recommended optional].map do |type| %w[build required recommended optional].map do |type|
deps = f.deps.send(type).uniq deps = formula.deps.send(type).uniq
puts "#{type.capitalize}: #{decorate_dependencies deps}" unless deps.empty? puts "#{type.capitalize}: #{decorate_dependencies deps}" unless deps.empty?
end end
end end
unless f.requirements.to_a.empty? unless formula.requirements.to_a.empty?
ohai "Requirements" ohai "Requirements"
%w[build required recommended optional].map do |type| %w[build required recommended optional].map do |type|
reqs = f.requirements.select(&:"#{type}?") reqs = formula.requirements.select(&:"#{type}?")
next if reqs.to_a.empty? next if reqs.to_a.empty?
puts "#{type.capitalize}: #{decorate_requirements(reqs)}" puts "#{type.capitalize}: #{decorate_requirements(reqs)}"
end end
end end
if !f.options.empty? || f.head if !formula.options.empty? || formula.head
ohai "Options" ohai "Options"
Options.dump_for_formula f Options.dump_for_formula formula
end end
caveats = Caveats.new(f) caveats = Caveats.new(formula)
ohai "Caveats", caveats.to_s unless caveats.empty? ohai "Caveats", caveats.to_s unless caveats.empty?
Utils::Analytics.formula_output(f, args: args) Utils::Analytics.formula_output(formula, args: args)
end end
def decorate_dependencies(dependencies) def decorate_dependencies(dependencies)

View File

@ -7,6 +7,7 @@ require "install"
require "upgrade" require "upgrade"
require "cask/cmd" require "cask/cmd"
require "cask/utils" require "cask/utils"
require "cask/upgrade"
require "cask/macos" require "cask/macos"
require "api" require "api"
@ -87,8 +88,19 @@ module Homebrew
description: "Treat all named arguments as casks. If no named arguments " \ description: "Treat all named arguments as casks. If no named arguments " \
"are specified, upgrade only outdated casks.", "are specified, upgrade only outdated casks.",
}], }],
[:switch, "--skip-cask-deps", {
description: "Skip installing cask dependencies.",
}],
[:switch, "-g", "--greedy", {
description: "Also include casks with `auto_updates true` or `version :latest`.",
}],
[:switch, "--greedy-latest", {
description: "Also include casks with `version :latest`.",
}],
[:switch, "--greedy-auto-updates", {
description: "Also include casks with `auto_updates true`.",
}],
*Cask::Cmd::AbstractCommand::OPTIONS.map(&:dup), *Cask::Cmd::AbstractCommand::OPTIONS.map(&:dup),
*Cask::Cmd::Upgrade::OPTIONS.map(&:dup),
].each do |args| ].each do |args|
options = args.pop options = args.pop
send(*args, **options) send(*args, **options)
@ -230,7 +242,7 @@ module Homebrew
def upgrade_outdated_casks(casks, args:) def upgrade_outdated_casks(casks, args:)
return false if args.formula? return false if args.formula?
Cask::Cmd::Upgrade.upgrade_casks( Cask::Upgrade.upgrade_casks(
*casks, *casks,
force: args.force?, force: args.force?,
greedy: args.greedy?, greedy: args.greedy?,

View File

@ -98,22 +98,22 @@ module Debrew
end end
end end
def self.debug(e) def self.debug(exception)
raise(e) if !active? || !debugged_exceptions.add?(e) || !try_lock raise(exception) if !active? || !debugged_exceptions.add?(exception) || !try_lock
begin begin
puts e.backtrace.first.to_s puts exception.backtrace.first.to_s
puts Formatter.error(e, label: e.class.name) puts Formatter.error(exception, label: exception.class.name)
loop do loop do
Menu.choose do |menu| Menu.choose do |menu|
menu.prompt = "Choose an action: " menu.prompt = "Choose an action: "
menu.choice(:raise) { raise(e) } menu.choice(:raise) { raise(e) }
menu.choice(:ignore) { return :ignore } if e.is_a?(Ignorable::ExceptionMixin) menu.choice(:ignore) { return :ignore } if exception.is_a?(Ignorable::ExceptionMixin)
menu.choice(:backtrace) { puts e.backtrace } menu.choice(:backtrace) { puts exception.backtrace }
if e.is_a?(Ignorable::ExceptionMixin) if exception.is_a?(Ignorable::ExceptionMixin)
menu.choice(:irb) do menu.choice(:irb) do
puts "When you exit this IRB session, execution will continue." puts "When you exit this IRB session, execution will continue."
set_trace_func proc { |event, _, _, id, binding, klass| set_trace_func proc { |event, _, _, id, binding, klass|

View File

@ -82,8 +82,6 @@ class DescriptionCacheStore < CacheStore
end end
alias delete_from_cask_tokens! delete_from_formula_names! alias delete_from_cask_tokens! delete_from_formula_names!
private
# `select` from the underlying database. # `select` from the underlying database.
def select(&block) def select(&block)
database.select(&block) database.select(&block)

View File

@ -102,8 +102,8 @@ module Homebrew
return merge(args: args) return merge(args: args)
end end
args.named.to_resolved_formulae(uniq: false).each do |f| args.named.to_resolved_formulae(uniq: false).each do |formula|
bottle_formula f, args: args bottle_formula formula, args: args
end end
end end
@ -261,13 +261,13 @@ module Homebrew
["#{gnu_tar.opt_bin}/gtar", gnutar_args].freeze ["#{gnu_tar.opt_bin}/gtar", gnutar_args].freeze
end end
def formula_ignores(f) def formula_ignores(formula)
ignores = [] ignores = []
cellar_regex = Regexp.escape(HOMEBREW_CELLAR) cellar_regex = Regexp.escape(HOMEBREW_CELLAR)
prefix_regex = Regexp.escape(HOMEBREW_PREFIX) prefix_regex = Regexp.escape(HOMEBREW_PREFIX)
# Ignore matches to go keg, because all go binaries are statically linked. # Ignore matches to go keg, because all go binaries are statically linked.
any_go_deps = f.deps.any? do |dep| any_go_deps = formula.deps.any? do |dep|
dep.name =~ Version.formula_optionally_versioned_regex(:go) dep.name =~ Version.formula_optionally_versioned_regex(:go)
end end
if any_go_deps if any_go_deps
@ -277,7 +277,7 @@ module Homebrew
# TODO: Refactor and move to extend/os # TODO: Refactor and move to extend/os
# rubocop:disable Homebrew/MoveToExtendOS # rubocop:disable Homebrew/MoveToExtendOS
ignores << case f.name ignores << case formula.name
# On Linux, GCC installation can be moved so long as the whole directory tree is moved together: # On Linux, GCC installation can be moved so long as the whole directory tree is moved together:
# https://gcc-help.gcc.gnu.narkive.com/GnwuCA7l/moving-gcc-from-the-installation-path-is-it-allowed. # https://gcc-help.gcc.gnu.narkive.com/GnwuCA7l/moving-gcc-from-the-installation-path-is-it-allowed.
when Version.formula_optionally_versioned_regex(:gcc) when Version.formula_optionally_versioned_regex(:gcc)
@ -291,25 +291,29 @@ module Homebrew
ignores.compact ignores.compact
end end
def bottle_formula(f, args:) def bottle_formula(formula, args:)
local_bottle_json = args.json? && f.local_bottle_path.present? local_bottle_json = args.json? && formula.local_bottle_path.present?
unless local_bottle_json unless local_bottle_json
return ofail "Formula not installed or up-to-date: #{f.full_name}" unless f.latest_version_installed? unless formula.latest_version_installed?
return ofail "Formula was not installed with --build-bottle: #{f.full_name}" unless Utils::Bottles.built_as? f return ofail "Formula not installed or up-to-date: #{formula.full_name}"
end
unless Utils::Bottles.built_as? formula
return ofail "Formula was not installed with --build-bottle: #{formula.full_name}"
end
end end
tap = f.tap tap = formula.tap
if tap.nil? if tap.nil?
return ofail "Formula not from core or any installed taps: #{f.full_name}" unless args.force_core_tap? return ofail "Formula not from core or any installed taps: #{formula.full_name}" unless args.force_core_tap?
tap = CoreTap.instance tap = CoreTap.instance
end end
return ofail "Formula has no stable version: #{f.full_name}" unless f.stable return ofail "Formula has no stable version: #{formula.full_name}" unless formula.stable
bottle_tag, rebuild = if local_bottle_json bottle_tag, rebuild = if local_bottle_json
_, tag_string, rebuild_string = Utils::Bottles.extname_tag_rebuild(f.local_bottle_path.to_s) _, tag_string, rebuild_string = Utils::Bottles.extname_tag_rebuild(formula.local_bottle_path.to_s)
[tag_string.to_sym, rebuild_string.to_i] [tag_string.to_sym, rebuild_string.to_i]
end end
@ -322,19 +326,19 @@ module Homebrew
rebuild ||= if args.no_rebuild? || !tap rebuild ||= if args.no_rebuild? || !tap
0 0
elsif args.keep_old? elsif args.keep_old?
f.bottle_specification.rebuild formula.bottle_specification.rebuild
else else
ohai "Determining #{f.full_name} bottle rebuild..." ohai "Determining #{formula.full_name} bottle rebuild..."
FormulaVersions.new(f).formula_at_revision("origin/HEAD") do |upstream_f| FormulaVersions.new(formula).formula_at_revision("origin/HEAD") do |upstream_formula|
if f.pkg_version == upstream_f.pkg_version if formula.pkg_version == upstream_formula.pkg_version
upstream_f.bottle_specification.rebuild + 1 upstream_formula.bottle_specification.rebuild + 1
else else
0 0
end end
end || 0 end || 0
end end
filename = Bottle::Filename.create(f, bottle_tag.to_sym, rebuild) filename = Bottle::Filename.create(formula, bottle_tag.to_sym, rebuild)
local_filename = filename.to_s local_filename = filename.to_s
bottle_path = Pathname.pwd/filename bottle_path = Pathname.pwd/filename
@ -354,7 +358,7 @@ module Homebrew
cellar = HOMEBREW_CELLAR.to_s cellar = HOMEBREW_CELLAR.to_s
if local_bottle_json if local_bottle_json
bottle_path = f.local_bottle_path bottle_path = formula.local_bottle_path
local_filename = bottle_path.basename.to_s local_filename = bottle_path.basename.to_s
tab_path = Utils::Bottles.receipt_path(bottle_path) tab_path = Utils::Bottles.receipt_path(bottle_path)
@ -363,7 +367,7 @@ module Homebrew
tab_json = Utils::Bottles.file_from_bottle(bottle_path, tab_path) tab_json = Utils::Bottles.file_from_bottle(bottle_path, tab_path)
tab = Tab.from_file_content(tab_json, tab_path) tab = Tab.from_file_content(tab_json, tab_path)
tag_spec = Formula[f.name].bottle_specification.tag_specification_for(bottle_tag, no_older_versions: true) tag_spec = Formula[formula.name].bottle_specification.tag_specification_for(bottle_tag, no_older_versions: true)
relocatable = [:any, :any_skip_relocation].include?(tag_spec.cellar) relocatable = [:any, :any_skip_relocation].include?(tag_spec.cellar)
skip_relocation = tag_spec.cellar == :any_skip_relocation skip_relocation = tag_spec.cellar == :any_skip_relocation
@ -373,12 +377,12 @@ module Homebrew
tar_filename = filename.to_s.sub(/.gz$/, "") tar_filename = filename.to_s.sub(/.gz$/, "")
tar_path = Pathname.pwd/tar_filename tar_path = Pathname.pwd/tar_filename
keg = Keg.new(f.prefix) keg = Keg.new(formula.prefix)
end end
ohai "Bottling #{local_filename}..." ohai "Bottling #{local_filename}..."
formula_and_runtime_deps_names = [f.name] + f.runtime_dependencies.map(&:name) formula_and_runtime_deps_names = [formula.name] + formula.runtime_dependencies.map(&:name)
# this will be nil when using a local bottle # this will be nil when using a local bottle
keg&.lock do keg&.lock do
@ -417,10 +421,10 @@ module Homebrew
tar, tar_args = setup_tar_and_args!(args, tar_mtime) tar, tar_args = setup_tar_and_args!(args, tar_mtime)
safe_system tar, "--create", "--numeric-owner", safe_system tar, "--create", "--numeric-owner",
*tar_args, *tar_args,
"--file", tar_path, "#{f.name}/#{f.pkg_version}" "--file", tar_path, "#{formula.name}/#{formula.pkg_version}"
sudo_purge sudo_purge
# Set filename as it affects the tarball checksum. # Set filename as it affects the tarball checksum.
relocatable_tar_path = "#{f}-bottle.tar" relocatable_tar_path = "#{formula}-bottle.tar"
mv tar_path, relocatable_tar_path mv tar_path, relocatable_tar_path
# Use gzip, faster to compress than bzip2, faster to uncompress than bzip2 # Use gzip, faster to compress than bzip2, faster to uncompress than bzip2
# or an uncompressed tarball (and more bandwidth friendly). # or an uncompressed tarball (and more bandwidth friendly).
@ -444,7 +448,7 @@ module Homebrew
ignores = [%r{/include/|\.(c|cc|cpp|h|hpp)$}] ignores = [%r{/include/|\.(c|cc|cpp|h|hpp)$}]
# Add additional workarounds to ignore # Add additional workarounds to ignore
ignores += formula_ignores(f) ignores += formula_ignores(formula)
repository_reference = if HOMEBREW_PREFIX == HOMEBREW_REPOSITORY repository_reference = if HOMEBREW_PREFIX == HOMEBREW_REPOSITORY
HOMEBREW_LIBRARY HOMEBREW_LIBRARY
@ -500,7 +504,7 @@ module Homebrew
sha256 = bottle_path.sha256 sha256 = bottle_path.sha256
bottle.sha256 cellar: bottle_cellar, bottle_tag.to_sym => sha256 bottle.sha256 cellar: bottle_cellar, bottle_tag.to_sym => sha256
old_spec = f.bottle_specification old_spec = formula.bottle_specification
if args.keep_old? && !old_spec.checksums.empty? if args.keep_old? && !old_spec.checksums.empty?
mismatches = [:root_url, :rebuild].reject do |key| mismatches = [:root_url, :rebuild].reject do |key|
old_spec.send(key) == bottle.send(key) old_spec.send(key) == bottle.send(key)
@ -529,21 +533,21 @@ module Homebrew
return unless args.json? return unless args.json?
json = { json = {
f.full_name => { formula.full_name => {
"formula" => { "formula" => {
"name" => f.name, "name" => formula.name,
"pkg_version" => f.pkg_version.to_s, "pkg_version" => formula.pkg_version.to_s,
"path" => f.path.to_s.delete_prefix("#{HOMEBREW_REPOSITORY}/"), "path" => formula.path.to_s.delete_prefix("#{HOMEBREW_REPOSITORY}/"),
"tap_git_path" => f.path.to_s.delete_prefix("#{tap_path}/"), "tap_git_path" => formula.path.to_s.delete_prefix("#{tap_path}/"),
"tap_git_revision" => tap_git_revision, "tap_git_revision" => tap_git_revision,
"tap_git_remote" => tap_git_remote, "tap_git_remote" => tap_git_remote,
# descriptions can contain emoji. sigh. # descriptions can contain emoji. sigh.
"desc" => f.desc.to_s.encode( "desc" => formula.desc.to_s.encode(
Encoding.find("ASCII"), Encoding.find("ASCII"),
invalid: :replace, undef: :replace, replace: "", invalid: :replace, undef: :replace, replace: "",
).strip, ).strip,
"license" => SPDX.license_expression_to_string(f.license), "license" => SPDX.license_expression_to_string(formula.license),
"homepage" => f.homepage, "homepage" => formula.homepage,
}, },
"bottle" => { "bottle" => {
"root_url" => bottle.root_url, "root_url" => bottle.root_url,
@ -603,8 +607,8 @@ module Homebrew
old_bottle_spec = formula.bottle_specification old_bottle_spec = formula.bottle_specification
old_pkg_version = formula.pkg_version old_pkg_version = formula.pkg_version
FormulaVersions.new(formula).formula_at_revision("origin/HEAD") do |upstream_f| FormulaVersions.new(formula).formula_at_revision("origin/HEAD") do |upstream_formula|
old_pkg_version = upstream_f.pkg_version old_pkg_version = upstream_formula.pkg_version
end end
old_bottle_spec_matches = old_bottle_spec && old_bottle_spec_matches = old_bottle_spec &&

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "formula" require "formula"

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "timeout" require "timeout"

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "formulary" require "formulary"

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "cli/parser"

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "cli/parser"

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "cli/parser"

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "cli/parser"

View File

@ -114,11 +114,11 @@ module Homebrew
end end
end end
def retry_test?(f, args:) def retry_test?(formula, args:)
@test_failed ||= Set.new @test_failed ||= Set.new
if args.retry? && @test_failed.add?(f) if args.retry? && @test_failed.add?(formula)
oh1 "Testing #{f.full_name} (again)" oh1 "Testing #{formula.full_name} (again)"
f.clear_cache formula.clear_cache
ENV["RUST_BACKTRACE"] = "full" ENV["RUST_BACKTRACE"] = "full"
true true
else else

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "cli/parser"

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "keg" require "keg"
@ -31,7 +31,7 @@ module Homebrew
def self.checks(type, fatal: true) def self.checks(type, fatal: true)
@checks ||= Checks.new @checks ||= Checks.new
failed = false failed = T.let(false, T::Boolean)
@checks.public_send(type).each do |check| @checks.public_send(type).each do |check|
out = @checks.public_send(check) out = @checks.public_send(check)
next if out.nil? next if out.nil?
@ -64,6 +64,7 @@ module Homebrew
end end
end end
sig { params(list: T::Array[String], string: String).returns(String) }
def inject_file_list(list, string) def inject_file_list(list, string)
list.reduce(string.dup) { |acc, elem| acc << " #{elem}\n" } list.reduce(string.dup) { |acc, elem| acc << " #{elem}\n" }
.freeze .freeze
@ -569,8 +570,8 @@ module Homebrew
EOS EOS
end end
def __check_linked_brew(f) def __check_linked_brew(formula)
f.installed_prefixes.each do |prefix| formula.installed_prefixes.each do |prefix|
prefix.find do |src| prefix.find do |src|
next if src == prefix next if src == prefix
@ -642,10 +643,11 @@ module Homebrew
EOS EOS
end end
sig { returns(T.nilable(String)) }
def check_git_status def check_git_status
return unless Utils::Git.available? return unless Utils::Git.available?
message = nil message = T.let(nil, T.nilable(String))
repos = { repos = {
"Homebrew/brew" => HOMEBREW_REPOSITORY, "Homebrew/brew" => HOMEBREW_REPOSITORY,

View File

@ -162,33 +162,33 @@ module Kernel
odeprecated(method, replacement, options) odeprecated(method, replacement, options)
end end
def pretty_installed(f) def pretty_installed(formula)
if !$stdout.tty? if !$stdout.tty?
f.to_s formula.to_s
elsif Homebrew::EnvConfig.no_emoji? elsif Homebrew::EnvConfig.no_emoji?
Formatter.success("#{Tty.bold}#{f} (installed)#{Tty.reset}") Formatter.success("#{Tty.bold}#{formula} (installed)#{Tty.reset}")
else else
"#{Tty.bold}#{f} #{Formatter.success("")}#{Tty.reset}" "#{Tty.bold}#{formula} #{Formatter.success("")}#{Tty.reset}"
end end
end end
def pretty_outdated(f) def pretty_outdated(formula)
if !$stdout.tty? if !$stdout.tty?
f.to_s formula.to_s
elsif Homebrew::EnvConfig.no_emoji? elsif Homebrew::EnvConfig.no_emoji?
Formatter.error("#{Tty.bold}#{f} (outdated)#{Tty.reset}") Formatter.error("#{Tty.bold}#{formula} (outdated)#{Tty.reset}")
else else
"#{Tty.bold}#{f} #{Formatter.warning("")}#{Tty.reset}" "#{Tty.bold}#{formula} #{Formatter.warning("")}#{Tty.reset}"
end end
end end
def pretty_uninstalled(f) def pretty_uninstalled(formula)
if !$stdout.tty? if !$stdout.tty?
f.to_s formula.to_s
elsif Homebrew::EnvConfig.no_emoji? elsif Homebrew::EnvConfig.no_emoji?
Formatter.error("#{Tty.bold}#{f} (uninstalled)#{Tty.reset}") Formatter.error("#{Tty.bold}#{formula} (uninstalled)#{Tty.reset}")
else else
"#{Tty.bold}#{f} #{Formatter.error("")}#{Tty.reset}" "#{Tty.bold}#{formula} #{Formatter.error("")}#{Tty.reset}"
end end
end end
@ -209,10 +209,10 @@ module Kernel
res.freeze res.freeze
end end
def interactive_shell(f = nil) def interactive_shell(formula = nil)
unless f.nil? unless formula.nil?
ENV["HOMEBREW_DEBUG_PREFIX"] = f.prefix ENV["HOMEBREW_DEBUG_PREFIX"] = formula.prefix
ENV["HOMEBREW_DEBUG_INSTALL"] = f.full_name ENV["HOMEBREW_DEBUG_INSTALL"] = formula.full_name
end end
if Utils::Shell.preferred == :zsh && (home = Dir.home).start_with?(HOMEBREW_TEMP.resolved_path.to_s) if Utils::Shell.preferred == :zsh && (home = Dir.home).start_with?(HOMEBREW_TEMP.resolved_path.to_s)

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
module Stdenv module Stdenv
@ -7,7 +7,7 @@ module Stdenv
undef homebrew_extra_pkg_config_paths undef homebrew_extra_pkg_config_paths
def homebrew_extra_pkg_config_paths def homebrew_extra_pkg_config_paths
["#{HOMEBREW_LIBRARY}/Homebrew/os/mac/pkgconfig/#{MacOS.version}"] [Pathname("#{HOMEBREW_LIBRARY}/Homebrew/os/mac/pkgconfig/#{MacOS.version}")]
end end
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false, def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
module Superenv module Superenv
@ -29,7 +29,7 @@ module Superenv
# @private # @private
def homebrew_extra_pkg_config_paths def homebrew_extra_pkg_config_paths
["/usr/lib/pkgconfig", "#{HOMEBREW_LIBRARY}/Homebrew/os/mac/pkgconfig/#{MacOS.version}"] [Pathname("/usr/lib/pkgconfig"), Pathname("#{HOMEBREW_LIBRARY}/Homebrew/os/mac/pkgconfig/#{MacOS.version}")]
end end
# @private # @private
@ -68,7 +68,7 @@ module Superenv
end end
def homebrew_extra_cmake_library_paths def homebrew_extra_cmake_library_paths
["#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries"] [Pathname("#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries")]
end end
def homebrew_extra_cmake_frameworks_paths def homebrew_extra_cmake_frameworks_paths
@ -96,7 +96,7 @@ module Superenv
end end
self["HOMEBREW_DEVELOPER_DIR"] = if is_xcode_sdk self["HOMEBREW_DEVELOPER_DIR"] = if is_xcode_sdk
MacOS::Xcode.prefix MacOS::Xcode.prefix.to_s
else else
MacOS::CLT::PKG_PATH MacOS::CLT::PKG_PATH
end end

View File

@ -38,12 +38,12 @@ module SystemConfig
@clt ||= MacOS::CLT.version if MacOS::CLT.installed? @clt ||= MacOS::CLT.version if MacOS::CLT.installed?
end end
def dump_verbose_config(f = $stdout) def dump_verbose_config(out = $stdout)
dump_generic_verbose_config(f) dump_generic_verbose_config(out)
f.puts "macOS: #{MacOS.full_version}-#{kernel}" out.puts "macOS: #{MacOS.full_version}-#{kernel}"
f.puts "CLT: #{clt || "N/A"}" out.puts "CLT: #{clt || "N/A"}"
f.puts "Xcode: #{xcode || "N/A"}" out.puts "Xcode: #{xcode || "N/A"}"
f.puts "Rosetta 2: #{Hardware::CPU.in_rosetta2?}" if Hardware::CPU.physical_cpu_arm64? out.puts "Rosetta 2: #{Hardware::CPU.in_rosetta2?}" if Hardware::CPU.physical_cpu_arm64?
end end
end end
end end

View File

@ -6,16 +6,16 @@ module Homebrew
module Fetch module Fetch
extend T::Sig extend T::Sig
sig { params(f: Formula, args: CLI::Args).returns(T::Boolean) } sig { params(formula: Formula, args: CLI::Args).returns(T::Boolean) }
def fetch_bottle?(f, args:) def fetch_bottle?(formula, args:)
bottle = f.bottle bottle = formula.bottle
return true if args.force_bottle? && bottle.present? return true if args.force_bottle? && bottle.present?
return true if args.bottle_tag.present? && f.bottled?(args.bottle_tag) return true if args.bottle_tag.present? && formula.bottled?(args.bottle_tag)
bottle.present? && bottle.present? &&
f.pour_bottle? && formula.pour_bottle? &&
args.build_from_source_formulae.exclude?(f.full_name) && args.build_from_source_formulae.exclude?(formula.full_name) &&
bottle.compatible_locations? bottle.compatible_locations?
end end
end end

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
module Homebrew module Homebrew

View File

@ -0,0 +1,5 @@
# typed: strict
module Homebrew::Assertions
include Kernel
end

View File

@ -7,22 +7,22 @@ require "keg"
# #
# @api private # @api private
class FormulaPin class FormulaPin
def initialize(f) def initialize(formula)
@f = f @formula = formula
end end
def path def path
HOMEBREW_PINNED_KEGS/@f.name HOMEBREW_PINNED_KEGS/@formula.name
end end
def pin_at(version) def pin_at(version)
HOMEBREW_PINNED_KEGS.mkpath HOMEBREW_PINNED_KEGS.mkpath
version_path = @f.rack/version version_path = @formula.rack/version
path.make_relative_symlink(version_path) if !pinned? && version_path.exist? path.make_relative_symlink(version_path) if !pinned? && version_path.exist?
end end
def pin def pin
pin_at(@f.installed_kegs.map(&:version).max) pin_at(@formula.installed_kegs.map(&:version).max)
end end
def unpin def unpin
@ -35,7 +35,7 @@ class FormulaPin
end end
def pinnable? def pinnable?
!@f.installed_prefixes.empty? !@formula.installed_prefixes.empty?
end end
def pinned_version def pinned_version

View File

@ -124,6 +124,10 @@ module Homebrew
def running_as_root_but_not_owned_by_root? def running_as_root_but_not_owned_by_root?
running_as_root? && !owner_uid.zero? running_as_root? && !owner_uid.zero?
end end
def auto_update_command?
ENV.fetch("HOMEBREW_AUTO_UPDATE_COMMAND", false).present?
end
end end
end end

View File

@ -97,7 +97,7 @@ module Homebrew
private_class_method :check_cc_argv private_class_method :check_cc_argv
def install_formula?( def install_formula?(
f, formula,
head: false, head: false,
fetch_head: false, fetch_head: false,
only_dependencies: false, only_dependencies: false,
@ -105,49 +105,51 @@ module Homebrew
quiet: false quiet: false
) )
# head-only without --HEAD is an error # head-only without --HEAD is an error
if !head && f.stable.nil? if !head && formula.stable.nil?
odie <<~EOS odie <<~EOS
#{f.full_name} is a head-only formula. #{formula.full_name} is a head-only formula.
To install it, run: To install it, run:
brew install --HEAD #{f.full_name} brew install --HEAD #{formula.full_name}
EOS EOS
end end
# --HEAD, fail with no head defined # --HEAD, fail with no head defined
odie "No head is defined for #{f.full_name}" if head && f.head.nil? odie "No head is defined for #{formula.full_name}" if head && formula.head.nil?
installed_head_version = f.latest_head_version installed_head_version = formula.latest_head_version
if installed_head_version && if installed_head_version &&
!f.head_version_outdated?(installed_head_version, fetch_head: fetch_head) !formula.head_version_outdated?(installed_head_version, fetch_head: fetch_head)
new_head_installed = true new_head_installed = true
end end
prefix_installed = f.prefix.exist? && !f.prefix.children.empty? prefix_installed = formula.prefix.exist? && !formula.prefix.children.empty?
if f.keg_only? && f.any_version_installed? && f.optlinked? && !force if formula.keg_only? && formula.any_version_installed? && formula.optlinked? && !force
# keg-only install is only possible when no other version is # keg-only install is only possible when no other version is
# linked to opt, because installing without any warnings can break # linked to opt, because installing without any warnings can break
# dependencies. Therefore before performing other checks we need to be # dependencies. Therefore before performing other checks we need to be
# sure --force flag is passed. # sure --force flag is passed.
if f.outdated? if formula.outdated?
if !Homebrew::EnvConfig.no_install_upgrade? && !f.pinned? if !Homebrew::EnvConfig.no_install_upgrade? && !formula.pinned?
puts "#{f.name} #{f.linked_version} is already installed but outdated (so it will be upgraded)." name = formula.name
version = formula.linked_version
puts "#{name} #{version} is already installed but outdated (so it will be upgraded)."
return true return true
end end
unpin_cmd_if_needed = ("brew unpin #{f.full_name} && " if f.pinned?) unpin_cmd_if_needed = ("brew unpin #{formula.full_name} && " if formula.pinned?)
optlinked_version = Keg.for(f.opt_prefix).version optlinked_version = Keg.for(formula.opt_prefix).version
onoe <<~EOS onoe <<~EOS
#{f.full_name} #{optlinked_version} is already installed. #{formula.full_name} #{optlinked_version} is already installed.
To upgrade to #{f.version}, run: To upgrade to #{formula.version}, run:
#{unpin_cmd_if_needed}brew upgrade #{f.full_name} #{unpin_cmd_if_needed}brew upgrade #{formula.full_name}
EOS EOS
elsif only_dependencies elsif only_dependencies
return true return true
elsif !quiet elsif !quiet
opoo <<~EOS opoo <<~EOS
#{f.full_name} #{f.pkg_version} is already installed and up-to-date. #{formula.full_name} #{formula.pkg_version} is already installed and up-to-date.
To reinstall #{f.pkg_version}, run: To reinstall #{formula.pkg_version}, run:
brew reinstall #{f.name} brew reinstall #{formula.name}
EOS EOS
end end
elsif (head && new_head_installed) || prefix_installed elsif (head && new_head_installed) || prefix_installed
@ -156,27 +158,27 @@ module Homebrew
# install is not already installed. # install is not already installed.
installed_version = if head installed_version = if head
f.latest_head_version formula.latest_head_version
else else
f.pkg_version formula.pkg_version
end end
msg = "#{f.full_name} #{installed_version} is already installed" msg = "#{formula.full_name} #{installed_version} is already installed"
linked_not_equals_installed = f.linked_version != installed_version linked_not_equals_installed = formula.linked_version != installed_version
if f.linked? && linked_not_equals_installed if formula.linked? && linked_not_equals_installed
msg = if quiet msg = if quiet
nil nil
else else
<<~EOS <<~EOS
#{msg}. #{msg}.
The currently linked version is: #{f.linked_version} The currently linked version is: #{formula.linked_version}
EOS EOS
end end
elsif !f.linked? || f.keg_only? elsif !formula.linked? || formula.keg_only?
msg = <<~EOS msg = <<~EOS
#{msg}, it's just not linked. #{msg}, it's just not linked.
To link this version, run: To link this version, run:
brew link #{f} brew link #{formula}
EOS EOS
elsif only_dependencies elsif only_dependencies
msg = nil msg = nil
@ -187,13 +189,13 @@ module Homebrew
else else
<<~EOS <<~EOS
#{msg} and up-to-date. #{msg} and up-to-date.
To reinstall #{f.pkg_version}, run: To reinstall #{formula.pkg_version}, run:
brew reinstall #{f.name} brew reinstall #{formula.name}
EOS EOS
end end
end end
opoo msg if msg opoo msg if msg
elsif !f.any_version_installed? && (old_formula = f.old_installed_formulae.first) elsif !formula.any_version_installed? && (old_formula = formula.old_installed_formulae.first)
msg = "#{old_formula.full_name} #{old_formula.any_installed_version} already installed" msg = "#{old_formula.full_name} #{old_formula.any_installed_version} already installed"
msg = if !old_formula.linked? && !old_formula.keg_only? msg = if !old_formula.linked? && !old_formula.keg_only?
<<~EOS <<~EOS
@ -207,37 +209,37 @@ module Homebrew
"#{msg}." "#{msg}."
end end
opoo msg if msg opoo msg if msg
elsif f.migration_needed? && !force elsif formula.migration_needed? && !force
# Check if the formula we try to install is the same as installed # Check if the formula we try to install is the same as installed
# but not migrated one. If --force is passed then install anyway. # but not migrated one. If --force is passed then install anyway.
opoo <<~EOS opoo <<~EOS
#{f.oldname} is already installed, it's just not migrated. #{formula.oldname} is already installed, it's just not migrated.
To migrate this formula, run: To migrate this formula, run:
brew migrate #{f} brew migrate #{formula}
Or to force-install it, run: Or to force-install it, run:
brew install #{f} --force brew install #{formula} --force
EOS EOS
elsif f.linked? elsif formula.linked?
message = "#{f.name} #{f.linked_version} is already installed" message = "#{formula.name} #{formula.linked_version} is already installed"
if f.outdated? && !head if formula.outdated? && !head
if !Homebrew::EnvConfig.no_install_upgrade? && !f.pinned? if !Homebrew::EnvConfig.no_install_upgrade? && !formula.pinned?
puts "#{message} but outdated (so it will be upgraded)." puts "#{message} but outdated (so it will be upgraded)."
return true return true
end end
unpin_cmd_if_needed = ("brew unpin #{f.full_name} && " if f.pinned?) unpin_cmd_if_needed = ("brew unpin #{formula.full_name} && " if formula.pinned?)
onoe <<~EOS onoe <<~EOS
#{message} #{message}
To upgrade to #{f.pkg_version}, run: To upgrade to #{formula.pkg_version}, run:
#{unpin_cmd_if_needed}brew upgrade #{f.full_name} #{unpin_cmd_if_needed}brew upgrade #{formula.full_name}
EOS EOS
elsif only_dependencies elsif only_dependencies
return true return true
else else
onoe <<~EOS onoe <<~EOS
#{message} #{message}
To install #{f.pkg_version}, first run: To install #{formula.pkg_version}, first run:
brew unlink #{f.name} brew unlink #{formula.name}
EOS EOS
end end
else else
@ -248,9 +250,9 @@ module Homebrew
# Even if we don't install this formula mark it as no longer just # Even if we don't install this formula mark it as no longer just
# installed as a dependency. # installed as a dependency.
return false unless f.opt_prefix.directory? return false unless formula.opt_prefix.directory?
keg = Keg.new(f.opt_prefix.resolved_path) keg = Keg.new(formula.opt_prefix.resolved_path)
tab = Tab.for_keg(keg) tab = Tab.for_keg(keg)
unless tab.installed_on_request unless tab.installed_on_request
tab.installed_on_request = true tab.installed_on_request = true
@ -281,12 +283,12 @@ module Homebrew
verbose: false, verbose: false,
dry_run: false dry_run: false
) )
formula_installers = formulae_to_install.map do |f| formula_installers = formulae_to_install.map do |formula|
Migrator.migrate_if_needed(f, force: force, dry_run: dry_run) Migrator.migrate_if_needed(formula, force: force, dry_run: dry_run)
build_options = f.build build_options = formula.build
fi = FormulaInstaller.new( formula_installer = FormulaInstaller.new(
f, formula,
options: build_options.used_options, options: build_options.used_options,
build_bottle: build_bottle, build_bottle: build_bottle,
force_bottle: force_bottle, force_bottle: force_bottle,
@ -309,15 +311,15 @@ module Homebrew
begin begin
unless dry_run unless dry_run
fi.prelude formula_installer.prelude
fi.fetch formula_installer.fetch
end end
fi formula_installer
rescue CannotInstallFormulaError => e rescue CannotInstallFormulaError => e
ofail e.message ofail e.message
nil nil
rescue UnsatisfiedRequirements, DownloadError, ChecksumMismatchError => e rescue UnsatisfiedRequirements, DownloadError, ChecksumMismatchError => e
ofail "#{f}: #{e}" ofail "#{formula}: #{e}"
nil nil
end end
end.compact end.compact
@ -329,8 +331,7 @@ module Homebrew
puts formulae_name_to_install.join(" ") puts formulae_name_to_install.join(" ")
formula_installers.each do |fi| formula_installers.each do |fi|
f = fi.formula print_dry_run_dependencies(fi.formula, fi.compute_dependencies, &:name)
print_dry_run_dependencies(f, fi.compute_dependencies, &:name)
end end
end end
return return
@ -343,9 +344,9 @@ module Homebrew
end end
def install_formula(formula_installer) def install_formula(formula_installer)
f = formula_installer.formula formula = formula_installer.formula
upgrade = f.linked? && f.outdated? && !f.head? && !Homebrew::EnvConfig.no_install_upgrade? upgrade = formula.linked? && formula.outdated? && !formula.head? && !Homebrew::EnvConfig.no_install_upgrade?
Upgrade.install_formula(formula_installer, upgrade: upgrade) Upgrade.install_formula(formula_installer, upgrade: upgrade)
end end

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
class Keg class Keg
@ -44,7 +44,7 @@ class Keg
key.is_a?(String) ? key.length : 999 key.is_a?(String) ? key.length : 999
end.reverse end.reverse
any_changed = false any_changed = T.let(nil, T.nilable(String))
sorted_keys.each do |key| sorted_keys.each do |key|
changed = text.gsub!(key, replacements[key]) changed = text.gsub!(key, replacements[key])
any_changed ||= changed any_changed ||= changed
@ -144,7 +144,7 @@ class Keg
def replace_text_in_files(relocation, files: nil) def replace_text_in_files(relocation, files: nil)
files ||= text_files | libtool_files files ||= text_files | libtool_files
changed_files = [] changed_files = T.let([], Array)
files.map(&path.method(:join)).group_by { |f| f.stat.ino }.each_value do |first, *rest| files.map(&path.method(:join)).group_by { |f| f.stat.ino }.each_value do |first, *rest|
s = first.open("rb", &:read) s = first.open("rb", &:read)
@ -179,11 +179,11 @@ class Keg
binary = File.binread file binary = File.binread file
odebug "Replacing build prefix in: #{file}" odebug "Replacing build prefix in: #{file}"
binary_strings = binary.split(/#{NULL_BYTE}/o, -1) binary_strings = binary.split(/#{NULL_BYTE}/o, -1)
match_indices = binary_strings.each_index.select { |i| binary_strings[i].include?(old_prefix) } match_indices = binary_strings.each_index.select { |i| binary_strings.fetch(i).include?(old_prefix) }
# Only perform substitution on strings which match prefix regex. # Only perform substitution on strings which match prefix regex.
match_indices.each do |i| match_indices.each do |i|
s = binary_strings[i] s = binary_strings.fetch(i)
binary_strings[i] = s.gsub(old_prefix, new_prefix) binary_strings[i] = s.gsub(old_prefix, new_prefix)
.ljust(s.size, NULL_BYTE) .ljust(s.size, NULL_BYTE)
end end

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
module Language module Language

View File

@ -0,0 +1,11 @@
# typed: strict
module Language::Python
module Shebang
include Kernel
end
module Virtualenv
requires_ancestor { Formula }
end
end

View File

@ -139,8 +139,8 @@ class Options
map(&:flag) map(&:flag)
end end
def include?(o) def include?(option)
any? { |opt| opt == o || opt.name == o || opt.flag == o } any? { |opt| opt == option || opt.name == option || opt.flag == option }
end end
alias to_ary to_a alias to_ary to_a
@ -155,10 +155,10 @@ class Options
"#<#{self.class.name}: #{to_a.inspect}>" "#<#{self.class.name}: #{to_a.inspect}>"
end end
def self.dump_for_formula(f) def self.dump_for_formula(formula)
f.options.sort_by(&:flag).each do |opt| formula.options.sort_by(&:flag).each do |opt|
puts "#{opt.flag}\n\t#{opt.description}" puts "#{opt.flag}\n\t#{opt.description}"
end end
puts "--HEAD\n\tInstall HEAD version" if f.head puts "--HEAD\n\tInstall HEAD version" if formula.head
end end
end end

View File

@ -117,11 +117,11 @@ module OS
sdk_locator.sdk_if_applicable(version) sdk_locator.sdk_if_applicable(version)
end end
def sdk_for_formula(f, version = nil, check_only_runtime_requirements: false) def sdk_for_formula(formula, version = nil, check_only_runtime_requirements: false)
# If the formula requires Xcode, don't return the CLT SDK # If the formula requires Xcode, don't return the CLT SDK
# If check_only_runtime_requirements is true, don't necessarily return the # If check_only_runtime_requirements is true, don't necessarily return the
# Xcode SDK if the XcodeRequirement is only a build or test requirement. # Xcode SDK if the XcodeRequirement is only a build or test requirement.
return Xcode.sdk if f.requirements.any? do |req| return Xcode.sdk if formula.requirements.any? do |req|
next false unless req.is_a? XcodeRequirement next false unless req.is_a? XcodeRequirement
next false if check_only_runtime_requirements && req.build? && !req.test? next false if check_only_runtime_requirements && req.build? && !req.test?

View File

@ -214,13 +214,13 @@ module RuboCop
end end
# Method to report and correct component precedence violations. # Method to report and correct component precedence violations.
def component_problem(c1, c2) def component_problem(component1, component2)
return if tap_style_exception? :components_order_exceptions return if tap_style_exception? :components_order_exceptions
problem "`#{format_component(c1)}` (line #{line_number(c1)}) " \ problem "`#{format_component(component1)}` (line #{line_number(component1)}) " \
"should be put before `#{format_component(c2)}` " \ "should be put before `#{format_component(component2)}` " \
"(line #{line_number(c2)})" do |corrector| "(line #{line_number(component2)})" do |corrector|
reorder_components(corrector, c1, c2) reorder_components(corrector, component1, component2)
end end
end end

View File

@ -170,12 +170,12 @@ module Homebrew
[all_formulae, all_casks] [all_formulae, all_casks]
end end
def search(array, string_or_regex, &block) def search(selectable, string_or_regex, &block)
case string_or_regex case string_or_regex
when Regexp when Regexp
search_regex(array, string_or_regex, &block) search_regex(selectable, string_or_regex, &block)
else else
search_string(array, string_or_regex.to_str, &block) search_string(selectable, string_or_regex.to_str, &block)
end end
end end
@ -183,17 +183,17 @@ module Homebrew
string.downcase.gsub(/[^a-z\d]/i, "") string.downcase.gsub(/[^a-z\d]/i, "")
end end
def search_regex(array, regex) def search_regex(selectable, regex)
array.select do |*args| selectable.select do |*args|
args = yield(*args) if block_given? args = yield(*args) if block_given?
args = Array(args).flatten.compact args = Array(args).flatten.compact
args.any? { |arg| arg.match?(regex) } args.any? { |arg| arg.match?(regex) }
end end
end end
def search_string(array, string) def search_string(selectable, string)
simplified_string = simplify_string(string) simplified_string = simplify_string(string)
array.select do |*args| selectable.select do |*args|
args = yield(*args) if block_given? args = yield(*args) if block_given?
args = Array(args).flatten.compact args = Array(args).flatten.compact
args.any? { |arg| simplify_string(arg).include?(simplified_string) } args.any? { |arg| simplify_string(arg).include?(simplified_string) }

View File

@ -139,43 +139,43 @@ module SystemConfig
end end
end end
def core_tap_config(f = $stdout) def core_tap_config(out = $stdout)
if CoreTap.instance.installed? if CoreTap.instance.installed?
f.puts "Core tap origin: #{core_tap_origin}" out.puts "Core tap origin: #{core_tap_origin}"
f.puts "Core tap HEAD: #{core_tap_head}" out.puts "Core tap HEAD: #{core_tap_head}"
f.puts "Core tap last commit: #{core_tap_last_commit}" out.puts "Core tap last commit: #{core_tap_last_commit}"
f.puts "Core tap branch: #{core_tap_branch}" out.puts "Core tap branch: #{core_tap_branch}"
end end
if (formula_json = Homebrew::API::HOMEBREW_CACHE_API/"formula.jws.json") && formula_json.exist? if (formula_json = Homebrew::API::HOMEBREW_CACHE_API/"formula.jws.json") && formula_json.exist?
f.puts "Core tap JSON: #{formula_json.mtime.utc.strftime("%d %b %H:%M UTC")}" out.puts "Core tap JSON: #{formula_json.mtime.utc.strftime("%d %b %H:%M UTC")}"
elsif !CoreTap.instance.installed? elsif !CoreTap.instance.installed?
f.puts "Core tap: N/A" out.puts "Core tap: N/A"
end end
end end
def homebrew_config(f = $stdout) def homebrew_config(out = $stdout)
f.puts "HOMEBREW_VERSION: #{HOMEBREW_VERSION}" out.puts "HOMEBREW_VERSION: #{HOMEBREW_VERSION}"
f.puts "ORIGIN: #{origin}" out.puts "ORIGIN: #{origin}"
f.puts "HEAD: #{head}" out.puts "HEAD: #{head}"
f.puts "Last commit: #{last_commit}" out.puts "Last commit: #{last_commit}"
end end
def homebrew_env_config(f = $stdout) def homebrew_env_config(out = $stdout)
f.puts "HOMEBREW_PREFIX: #{HOMEBREW_PREFIX}" out.puts "HOMEBREW_PREFIX: #{HOMEBREW_PREFIX}"
{ {
HOMEBREW_REPOSITORY: Homebrew::DEFAULT_REPOSITORY, HOMEBREW_REPOSITORY: Homebrew::DEFAULT_REPOSITORY,
HOMEBREW_CELLAR: Homebrew::DEFAULT_CELLAR, HOMEBREW_CELLAR: Homebrew::DEFAULT_CELLAR,
}.freeze.each do |key, default| }.freeze.each do |key, default|
value = Object.const_get(key) value = Object.const_get(key)
f.puts "#{key}: #{value}" if value.to_s != default.to_s out.puts "#{key}: #{value}" if value.to_s != default.to_s
end end
Homebrew::EnvConfig::ENVS.each do |env, hash| Homebrew::EnvConfig::ENVS.each do |env, hash|
method_name = Homebrew::EnvConfig.env_method_name(env, hash) method_name = Homebrew::EnvConfig.env_method_name(env, hash)
if hash[:boolean] if hash[:boolean]
f.puts "#{env}: set" if Homebrew::EnvConfig.send(method_name) out.puts "#{env}: set" if Homebrew::EnvConfig.send(method_name)
next next
end end
@ -184,26 +184,26 @@ module SystemConfig
next if (default = hash[:default].presence) && value.to_s == default.to_s next if (default = hash[:default].presence) && value.to_s == default.to_s
if ENV.sensitive?(env) if ENV.sensitive?(env)
f.puts "#{env}: set" out.puts "#{env}: set"
else else
f.puts "#{env}: #{value}" out.puts "#{env}: #{value}"
end end
end end
f.puts "Homebrew Ruby: #{describe_homebrew_ruby}" out.puts "Homebrew Ruby: #{describe_homebrew_ruby}"
end end
def host_software_config(f = $stdout) def host_software_config(out = $stdout)
f.puts "Clang: #{describe_clang}" out.puts "Clang: #{describe_clang}"
f.puts "Git: #{describe_git}" out.puts "Git: #{describe_git}"
f.puts "Curl: #{describe_curl}" out.puts "Curl: #{describe_curl}"
end end
def dump_verbose_config(f = $stdout) def dump_verbose_config(out = $stdout)
homebrew_config(f) homebrew_config(out)
core_tap_config(f) core_tap_config(out)
homebrew_env_config(f) homebrew_env_config(out)
f.puts hardware if hardware out.puts hardware if hardware
host_software_config(f) host_software_config(out)
end end
alias dump_generic_verbose_config dump_verbose_config alias dump_generic_verbose_config dump_verbose_config
end end

View File

@ -143,37 +143,37 @@ class Tab < OpenStruct
# Returns a {Tab} for an already installed formula, # Returns a {Tab} for an already installed formula,
# or a fake one if the formula is not installed. # or a fake one if the formula is not installed.
def self.for_formula(f) def self.for_formula(formula)
paths = [] paths = []
paths << f.opt_prefix.resolved_path if f.opt_prefix.symlink? && f.opt_prefix.directory? paths << formula.opt_prefix.resolved_path if formula.opt_prefix.symlink? && formula.opt_prefix.directory?
paths << f.linked_keg.resolved_path if f.linked_keg.symlink? && f.linked_keg.directory? paths << formula.linked_keg.resolved_path if formula.linked_keg.symlink? && formula.linked_keg.directory?
if (dirs = f.installed_prefixes).length == 1 if (dirs = formula.installed_prefixes).length == 1
paths << dirs.first paths << dirs.first
end end
paths << f.latest_installed_prefix paths << formula.latest_installed_prefix
path = paths.map { |pn| pn/FILENAME }.find(&:file?) path = paths.map { |pathname| pathname/FILENAME }.find(&:file?)
if path if path
tab = from_file(path) tab = from_file(path)
used_options = remap_deprecated_options(f.deprecated_options, tab.used_options) used_options = remap_deprecated_options(formula.deprecated_options, tab.used_options)
tab.used_options = used_options.as_flags tab.used_options = used_options.as_flags
else else
# Formula is not installed. Return a fake tab. # Formula is not installed. Return a fake tab.
tab = empty tab = empty
tab.unused_options = f.options.as_flags tab.unused_options = formula.options.as_flags
tab.source = { tab.source = {
"path" => f.specified_path.to_s, "path" => formula.specified_path.to_s,
"tap" => f.tap&.name, "tap" => formula.tap&.name,
"spec" => f.active_spec_sym.to_s, "spec" => formula.active_spec_sym.to_s,
"versions" => { "versions" => {
"stable" => f.stable&.version.to_s, "stable" => formula.stable&.version.to_s,
"head" => f.head&.version.to_s, "head" => formula.head&.version.to_s,
"version_scheme" => f.version_scheme, "version_scheme" => formula.version_scheme,
}, },
} }
end end

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
raise "#{__FILE__} must not be loaded via `require`." if $PROGRAM_NAME != __FILE__ raise "#{__FILE__} must not be loaded via `require`." if $PROGRAM_NAME != __FILE__
@ -38,12 +38,10 @@ begin
formula.extend(Debrew::Formula) if args.debug? formula.extend(Debrew::Formula) if args.debug?
ENV.extend(Stdenv) ENV.extend(Stdenv)
T.cast(ENV, Stdenv).setup_build_environment(formula: formula, testing_formula: true) ENV.setup_build_environment(formula: formula, testing_formula: true)
# tests can also return false to indicate failure # tests can also return false to indicate failure
run_test = proc do run_test = proc { |_ = nil| raise "test returned false" if formula.run_test(keep_tmp: args.keep_tmp?) == false }
raise "test returned false" if formula.run_test(keep_tmp: args.keep_tmp?) == false
end
if args.debug? # --debug is interactive if args.debug? # --debug is interactive
run_test.call run_test.call
else else

View File

@ -1,7 +1,9 @@
# typed: false # typed: false
# frozen_string_literal: true # frozen_string_literal: true
describe Cask::Cmd::Upgrade, :cask do require "cask/upgrade"
describe Cask::Upgrade, :cask do
let(:version_latest_path_2) { version_latest.config.appdir.join("Caffeine Pro.app") } let(:version_latest_path_2) { version_latest.config.appdir.join("Caffeine Pro.app") }
let(:version_latest_path_1) { version_latest.config.appdir.join("Caffeine Mini.app") } let(:version_latest_path_1) { version_latest.config.appdir.join("Caffeine Mini.app") }
let(:version_latest) { Cask::CaskLoader.load("version-latest") } let(:version_latest) { Cask::CaskLoader.load("version-latest") }
@ -11,6 +13,7 @@ describe Cask::Cmd::Upgrade, :cask do
let(:local_transmission) { Cask::CaskLoader.load("local-transmission") } let(:local_transmission) { Cask::CaskLoader.load("local-transmission") }
let(:local_caffeine_path) { local_caffeine.config.appdir.join("Caffeine.app") } let(:local_caffeine_path) { local_caffeine.config.appdir.join("Caffeine.app") }
let(:local_caffeine) { Cask::CaskLoader.load("local-caffeine") } let(:local_caffeine) { Cask::CaskLoader.load("local-caffeine") }
let(:args) { Homebrew::CLI::Args.new }
context "when the upgrade is successful" do context "when the upgrade is successful" do
let(:installed) do let(:installed) do
@ -38,7 +41,7 @@ describe Cask::Cmd::Upgrade, :cask do
expect(local_transmission_path).to be_a_directory expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60") expect(local_transmission.versions).to include("2.60")
described_class.run described_class.upgrade_casks(args: args)
expect(local_caffeine).to be_installed expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory expect(local_caffeine_path).to be_a_directory
@ -58,7 +61,7 @@ describe Cask::Cmd::Upgrade, :cask do
expect(local_transmission_path).to be_a_directory expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60") expect(local_transmission.versions).to include("2.60")
described_class.run("local-caffeine") described_class.upgrade_casks(local_caffeine, args: args)
expect(local_caffeine).to be_installed expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory expect(local_caffeine_path).to be_a_directory
@ -78,7 +81,7 @@ describe Cask::Cmd::Upgrade, :cask do
expect(auto_updates_path).to be_a_directory expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57") expect(auto_updates.versions).to include("2.57")
described_class.run("local-caffeine", "auto-updates") described_class.upgrade_casks(local_caffeine, auto_updates, args: args)
expect(local_caffeine).to be_installed expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory expect(local_caffeine_path).to be_a_directory
@ -111,7 +114,7 @@ describe Cask::Cmd::Upgrade, :cask do
version_latest.download_sha_path.write("fake download sha") version_latest.download_sha_path.write("fake download sha")
expect(version_latest.outdated_download_sha?).to be(true) expect(version_latest.outdated_download_sha?).to be(true)
described_class.run("--greedy") described_class.upgrade_casks(greedy: true, args: args)
expect(local_caffeine).to be_installed expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory expect(local_caffeine_path).to be_a_directory
@ -136,13 +139,13 @@ describe Cask::Cmd::Upgrade, :cask do
expect(auto_updates_path).to be_a_directory expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57") expect(auto_updates.versions).to include("2.57")
described_class.run("auto-updates", "--greedy") described_class.upgrade_casks(auto_updates, greedy: true, args: args)
expect(auto_updates).to be_installed expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.61") expect(auto_updates.versions).to include("2.61")
described_class.run("auto-updates", "--greedy") described_class.upgrade_casks(auto_updates, greedy: true, args: args)
expect(auto_updates).to be_installed expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory expect(auto_updates_path).to be_a_directory
@ -158,7 +161,7 @@ describe Cask::Cmd::Upgrade, :cask do
version_latest.download_sha_path.write("fake download sha") version_latest.download_sha_path.write("fake download sha")
expect(version_latest.outdated_download_sha?).to be(true) expect(version_latest.outdated_download_sha?).to be(true)
described_class.run("version-latest", "--greedy") described_class.upgrade_casks(version_latest, greedy: true, args: args)
expect(version_latest).to be_installed expect(version_latest).to be_installed
expect(version_latest_path_1).to be_a_directory expect(version_latest_path_1).to be_a_directory
@ -166,7 +169,7 @@ describe Cask::Cmd::Upgrade, :cask do
expect(version_latest.versions).to include("latest") expect(version_latest.versions).to include("latest")
expect(version_latest.outdated_download_sha?).to be(false) expect(version_latest.outdated_download_sha?).to be(false)
described_class.run("version-latest", "--greedy") described_class.upgrade_casks(version_latest, greedy: true, args: args)
expect(version_latest).to be_installed expect(version_latest).to be_installed
expect(version_latest_path_1).to be_a_directory expect(version_latest_path_1).to be_a_directory
@ -205,7 +208,7 @@ describe Cask::Cmd::Upgrade, :cask do
expect(local_transmission_path).to be_a_directory expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60") expect(local_transmission.versions).to include("2.60")
described_class.run("--dry-run") described_class.upgrade_casks(dry_run: true, args: args)
expect(local_caffeine).to be_installed expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory expect(local_caffeine_path).to be_a_directory
@ -229,7 +232,7 @@ describe Cask::Cmd::Upgrade, :cask do
expect(local_transmission_path).to be_a_directory expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60") expect(local_transmission.versions).to include("2.60")
described_class.run("--dry-run", "local-caffeine") described_class.upgrade_casks(local_caffeine, dry_run: true, args: args)
expect(local_caffeine).to be_installed expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory expect(local_caffeine_path).to be_a_directory
@ -253,7 +256,7 @@ describe Cask::Cmd::Upgrade, :cask do
expect(auto_updates_path).to be_a_directory expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57") expect(auto_updates.versions).to include("2.57")
described_class.run("--dry-run", "local-caffeine", "auto-updates") described_class.upgrade_casks(local_caffeine, auto_updates, dry_run: true, args: args)
expect(local_caffeine).to be_installed expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory expect(local_caffeine_path).to be_a_directory
@ -288,7 +291,7 @@ describe Cask::Cmd::Upgrade, :cask do
version_latest.download_sha_path.write("fake download sha") version_latest.download_sha_path.write("fake download sha")
expect(version_latest.outdated_download_sha?).to be(true) expect(version_latest.outdated_download_sha?).to be(true)
described_class.run("--greedy", "--dry-run") described_class.upgrade_casks(greedy: true, dry_run: true, args: args)
expect(local_caffeine).to be_installed expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory expect(local_caffeine_path).to be_a_directory
@ -316,7 +319,7 @@ describe Cask::Cmd::Upgrade, :cask do
expect(auto_updates_path).to be_a_directory expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57") expect(auto_updates.versions).to include("2.57")
described_class.run("--dry-run", "auto-updates", "--greedy") described_class.upgrade_casks(auto_updates, dry_run: true, greedy: true, args: args)
expect(auto_updates).to be_installed expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory expect(auto_updates_path).to be_a_directory
@ -335,7 +338,7 @@ describe Cask::Cmd::Upgrade, :cask do
version_latest.download_sha_path.write("fake download sha") version_latest.download_sha_path.write("fake download sha")
expect(version_latest.outdated_download_sha?).to be(true) expect(version_latest.outdated_download_sha?).to be(true)
described_class.run("--dry-run", "version-latest", "--greedy") described_class.upgrade_casks(version_latest, dry_run: true, greedy: true, args: args)
expect(version_latest).to be_installed expect(version_latest).to be_installed
expect(version_latest_path_1).to be_a_directory expect(version_latest_path_1).to be_a_directory
@ -373,7 +376,7 @@ describe Cask::Cmd::Upgrade, :cask do
expect(will_fail_if_upgraded.versions).to include("1.2.2") expect(will_fail_if_upgraded.versions).to include("1.2.2")
expect do expect do
described_class.run("will-fail-if-upgraded") described_class.upgrade_casks(will_fail_if_upgraded, args: args)
end.to raise_error(Cask::CaskError).and output(output_reverted).to_stderr end.to raise_error(Cask::CaskError).and output(output_reverted).to_stderr
expect(will_fail_if_upgraded).to be_installed expect(will_fail_if_upgraded).to be_installed
@ -391,7 +394,7 @@ describe Cask::Cmd::Upgrade, :cask do
expect(bad_checksum.versions).to include("1.2.2") expect(bad_checksum.versions).to include("1.2.2")
expect do expect do
described_class.run("bad-checksum") described_class.upgrade_casks(bad_checksum, args: args)
end.to raise_error(ChecksumMismatchError).and(not_to_output(output_reverted).to_stderr) end.to raise_error(ChecksumMismatchError).and(not_to_output(output_reverted).to_stderr)
expect(bad_checksum).to be_installed expect(bad_checksum).to be_installed
@ -436,7 +439,7 @@ describe Cask::Cmd::Upgrade, :cask do
expect(bad_checksum_2.versions).to include("1.2.2") expect(bad_checksum_2.versions).to include("1.2.2")
expect do expect do
described_class.run described_class.upgrade_casks(args: args)
end.to raise_error(Cask::MultipleCaskErrors) end.to raise_error(Cask::MultipleCaskErrors)
expect(bad_checksum).to be_installed expect(bad_checksum).to be_installed

View File

@ -10,7 +10,7 @@ describe Caveats do
let(:f) { formula { url "foo-1.0" } } let(:f) { formula { url "foo-1.0" } }
specify "#f" do specify "#f" do
expect(caveats.f).to eq(f) expect(caveats.formula).to eq(f)
end end
describe "#empty?" do describe "#empty?" do

View File

@ -6,19 +6,29 @@ require "cmd/shared_examples/args_parse"
describe "brew irb" do describe "brew irb" do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
it "starts an interactive Homebrew shell session", :integration_test do describe "integration test" do
setup_test_formula "testball" let(:history_file) { Pathname("#{Dir.home}/.brew_irb_history") }
irb_test = HOMEBREW_TEMP/"irb-test.rb" after do
irb_test.write <<~RUBY history_file.delete if history_file.exist?
"testball".f end
:testball.f
exit
RUBY
expect { brew "irb", irb_test } it "starts an interactive Homebrew shell session", :integration_test do
.to output(/Interactive Homebrew Shell/).to_stdout setup_test_formula "testball"
.and not_to_output.to_stderr
.and be_a_success irb_test = HOMEBREW_TEMP/"irb-test.rb"
irb_test.write <<~RUBY
"testball".f
:testball.f
exit
RUBY
expect { brew "irb", irb_test }
.to output(/Interactive Homebrew Shell/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect(history_file).to exist
end
end end
end end

View File

@ -49,22 +49,22 @@ describe FormulaInstaller do
expect(formula).not_to be_latest_version_installed expect(formula).not_to be_latest_version_installed
end end
def test_basic_formula_setup(f) def test_basic_formula_setup(formula)
# Test that things made it into the Keg # Test that things made it into the Keg
expect(f.bin).to be_a_directory expect(formula.bin).to be_a_directory
expect(f.libexec).to be_a_directory expect(formula.libexec).to be_a_directory
expect(f.prefix/"main.c").not_to exist expect(formula.prefix/"main.c").not_to exist
# Test that things made it into the Cellar # Test that things made it into the Cellar
keg = Keg.new f.prefix keg = Keg.new formula.prefix
keg.link keg.link
bin = HOMEBREW_PREFIX/"bin" bin = HOMEBREW_PREFIX/"bin"
expect(bin).to be_a_directory expect(bin).to be_a_directory
expect(f.libexec).to be_a_directory expect(formula.libexec).to be_a_directory
end end
# This test wraps expect() calls in `test_basic_formula_setup` # This test wraps expect() calls in `test_basic_formula_setup`

View File

@ -1,12 +1,10 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
module Homebrew module Homebrew
# Provides helper methods for unlinking formulae and kegs with consistent output. # Provides helper methods for unlinking formulae and kegs with consistent output.
module Unlink module Unlink
module_function def self.unlink_versioned_formulae(formula, verbose: false)
def unlink_versioned_formulae(formula, verbose: false)
formula.versioned_formulae formula.versioned_formulae
.select(&:keg_only?) .select(&:keg_only?)
.select(&:linked?) .select(&:linked?)
@ -18,7 +16,7 @@ module Homebrew
end end
end end
def unlink(keg, dry_run: false, verbose: false) def self.unlink(keg, dry_run: false, verbose: false)
options = { dry_run: dry_run, verbose: verbose } options = { dry_run: dry_run, verbose: verbose }
keg.lock do keg.lock do

View File

@ -423,13 +423,13 @@ module Homebrew
end end
end end
def depends_on(a, b) def depends_on(one, two)
if a.any_installed_keg if one.any_installed_keg
&.runtime_dependencies &.runtime_dependencies
&.any? { |d| d["full_name"] == b.full_name } &.any? { |dependency| dependency["full_name"] == two.full_name }
1 1
else else
a <=> b one <=> two
end end
end end
private_class_method :depends_on private_class_method :depends_on

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "context" require "context"
@ -42,7 +42,6 @@ module Utils
--data av=#{HOMEBREW_VERSION} --data av=#{HOMEBREW_VERSION}
] ]
metadata.each do |key, value| metadata.each do |key, value|
next unless key
next unless value next unless value
key = ERB::Util.url_encode key key = ERB::Util.url_encode key
@ -146,13 +145,13 @@ module Utils
report_influx(measurement, package_and_options, on_request, additional_tags_influx) report_influx(measurement, package_and_options, on_request, additional_tags_influx)
end end
sig { params(exception: Exception).void } sig { params(exception: BuildError).void }
def report_build_error(exception) def report_build_error(exception)
report_google_build_error(exception) report_google_build_error(exception)
report_influx_error(exception) report_influx_error(exception)
end end
sig { params(exception: Exception).void } sig { params(exception: BuildError).void }
def report_google_build_error(exception) def report_google_build_error(exception)
return if not_this_run? || disabled? return if not_this_run? || disabled?
@ -165,10 +164,10 @@ module Utils
else else
formula_full_name formula_full_name
end end
report_google_event("BuildError", package_and_options) report_google_event(:BuildError, package_and_options)
end end
sig { params(exception: Exception).void } sig { params(exception: BuildError).void }
def report_influx_error(exception) def report_influx_error(exception)
return if not_this_run? || disabled? return if not_this_run? || disabled?
@ -283,10 +282,10 @@ module Utils
end end
end end
def formula_output(f, args:) def formula_output(formula, args:)
return if Homebrew::EnvConfig.no_analytics? || Homebrew::EnvConfig.no_github_api? return if Homebrew::EnvConfig.no_analytics? || Homebrew::EnvConfig.no_github_api?
json = Homebrew::API::Formula.fetch f.name json = Homebrew::API::Formula.fetch formula.name
return if json.blank? || json["analytics"].blank? return if json.blank? || json["analytics"].blank?
get_analytics(json, args: args) get_analytics(json, args: args)

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
module Utils module Utils
@ -25,7 +25,7 @@ module Utils
def formulae_with_no_formula_dependents(formulae) def formulae_with_no_formula_dependents(formulae)
return [] if formulae.blank? return [] if formulae.blank?
dependents = [] dependents = T.let([], T::Array[Formula])
formulae.each do |formula| formulae.each do |formula|
dependents += formula.runtime_formula_dependencies dependents += formula.runtime_formula_dependencies
@ -33,7 +33,7 @@ module Utils
next if Tab.for_keg(formula.any_installed_keg).poured_from_bottle next if Tab.for_keg(formula.any_installed_keg).poured_from_bottle
formula.deps.select(&:build?).each do |dep| formula.deps.select(&:build?).each do |dep|
suppress(FormulaUnavailableError) { dependents << dep.to_formula } Kernel.suppress(FormulaUnavailableError) { dependents << dep.to_formula }
end end
end end
formulae - dependents formulae - dependents

View File

@ -19,22 +19,22 @@ module Utils
arch: HOMEBREW_PROCESSOR.downcase.to_sym) arch: HOMEBREW_PROCESSOR.downcase.to_sym)
end end
def built_as?(f) def built_as?(formula)
return false unless f.latest_version_installed? return false unless formula.latest_version_installed?
tab = Tab.for_keg(f.latest_installed_prefix) tab = Tab.for_keg(formula.latest_installed_prefix)
tab.built_as_bottle tab.built_as_bottle
end end
def file_outdated?(f, file) def file_outdated?(formula, file)
filename = file.basename.to_s filename = file.basename.to_s
return false if f.bottle.blank? return false if formula.bottle.blank?
bottle_ext, bottle_tag, = extname_tag_rebuild(filename) bottle_ext, bottle_tag, = extname_tag_rebuild(filename)
return false if bottle_ext.blank? return false if bottle_ext.blank?
return false if bottle_tag != tag.to_s return false if bottle_tag != tag.to_s
bottle_url_ext, = extname_tag_rebuild(f.bottle.url) bottle_url_ext, = extname_tag_rebuild(formula.bottle.url)
bottle_ext && bottle_url_ext && bottle_ext != bottle_url_ext bottle_ext && bottle_url_ext && bottle_ext != bottle_url_ext
end end

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "open3" require "open3"
@ -243,8 +243,8 @@ module Utils
return unless url.start_with? "http" return unless url.start_with? "http"
secure_url = url.sub(/\Ahttp:/, "https:") secure_url = url.sub(/\Ahttp:/, "https:")
secure_details = nil secure_details = T.let(nil, T.nilable(T::Hash[Symbol, T.untyped]))
hash_needed = false hash_needed = T.let(false, T::Boolean)
if url != secure_url if url != secure_url
user_agents.each do |user_agent| user_agents.each do |user_agent|
secure_details = begin secure_details = begin
@ -267,7 +267,7 @@ module Utils
end end
end end
details = nil details = T.let(nil, T.nilable(T::Hash[Symbol, T.untyped]))
user_agents.each do |user_agent| user_agents.each do |user_agent|
details = details =
curl_http_content_headers_and_checksum( curl_http_content_headers_and_checksum(
@ -414,7 +414,7 @@ module Utils
# Unknown charset in Content-Type header # Unknown charset in Content-Type header
end end
end end
file_contents = File.read(file.path, **open_args) file_contents = File.read(T.must(file.path), **open_args)
file_hash = Digest::SHA2.hexdigest(file_contents) if hash_needed file_hash = Digest::SHA2.hexdigest(file_contents) if hash_needed
end end
@ -430,7 +430,7 @@ module Utils
responses: responses, responses: responses,
} }
ensure ensure
file.unlink T.must(file).unlink
end end
def curl_supports_tls13? def curl_supports_tls13?
@ -547,7 +547,7 @@ module Utils
return response unless response_text.match?(HTTP_STATUS_LINE_REGEX) return response unless response_text.match?(HTTP_STATUS_LINE_REGEX)
# Parse the status line and remove it # Parse the status line and remove it
match = response_text.match(HTTP_STATUS_LINE_REGEX) match = T.must(response_text.match(HTTP_STATUS_LINE_REGEX))
response[:status_code] = match["code"] if match["code"].present? response[:status_code] = match["code"] if match["code"].present?
response[:status_text] = match["text"] if match["text"].present? response[:status_text] = match["text"] if match["text"].present?
response_text = response_text.sub(%r{^HTTP/.* (\d+).*$\s*}, "") response_text = response_text.sub(%r{^HTTP/.* (\d+).*$\s*}, "")

View File

@ -0,0 +1,6 @@
# typed: strict
module Utils::Curl
include Kernel
requires_ancestor { SystemCommand::Mixin }
end

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "utils/tty" require "utils/tty"
@ -91,11 +91,11 @@ module Formatter
end end
fallback.call if objects.empty? fallback.call if objects.empty?
fallback.call if respond_to?(:tty?) ? !tty? : !$stdout.tty? fallback.call if respond_to?(:tty?) ? !T.unsafe(self).tty? : !$stdout.tty?
console_width = Tty.width console_width = Tty.width
object_lengths = objects.map { |obj| Tty.strip_ansi(obj).length } object_lengths = objects.map { |obj| Tty.strip_ansi(obj).length }
cols = (console_width + gap_size) / (object_lengths.max + gap_size) cols = (console_width + gap_size) / (T.must(object_lengths.max) + gap_size)
fallback.call if cols < 2 fallback.call if cols < 2
@ -109,14 +109,14 @@ module Formatter
output = +"" output = +""
rows.times do |row_index| rows.times do |row_index|
item_indices_for_row = row_index.step(objects.size - 1, rows).to_a item_indices_for_row = T.cast(row_index.step(objects.size - 1, rows).to_a, T::Array[Integer])
first_n = item_indices_for_row[0...-1].map do |index| first_n = T.must(item_indices_for_row[0...-1]).map do |index|
objects[index] + "".rjust(col_width - object_lengths[index]) objects[index] + "".rjust(col_width - object_lengths.fetch(index))
end end
# don't add trailing whitespace to last column # don't add trailing whitespace to last column
last = objects.values_at(item_indices_for_row.last) last = objects.values_at(item_indices_for_row.fetch(-1))
output.concat((first_n + last) output.concat((first_n + last)
.join(gap_string)) .join(gap_string))

View File

@ -0,0 +1,5 @@
# typed: strict
module Formatter
include Kernel
end

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "tempfile" require "tempfile"
@ -214,7 +214,7 @@ module GitHub
headers_tmpfile = Tempfile.new("github_api_headers", HOMEBREW_TEMP) headers_tmpfile = Tempfile.new("github_api_headers", HOMEBREW_TEMP)
begin begin
if data if data_tmpfile
data_tmpfile.write data data_tmpfile.write data
data_tmpfile.close data_tmpfile.close
args += ["--data", "@#{data_tmpfile.path}"] args += ["--data", "@#{data_tmpfile.path}"]
@ -222,7 +222,7 @@ module GitHub
args += ["--request", request_method.to_s] if request_method args += ["--request", request_method.to_s] if request_method
end end
args += ["--dump-header", headers_tmpfile.path] args += ["--dump-header", T.must(headers_tmpfile.path)]
output, errors, status = curl_output("--location", url.to_s, *args, secrets: [token]) output, errors, status = curl_output("--location", url.to_s, *args, secrets: [token])
output, _, http_code = output.rpartition("\n") output, _, http_code = output.rpartition("\n")

View File

@ -0,0 +1,5 @@
# typed: strict
module GitHub::API
include Kernel
end

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "utils/curl" require "utils/curl"

View File

@ -0,0 +1,6 @@
# typed: strict
module Repology
include Kernel
requires_ancestor { Utils::Curl }
end

View File

@ -653,9 +653,9 @@ class Version
private private
sig { params(a: Integer, b: Integer).returns(Integer) } sig { params(first: Integer, second: Integer).returns(Integer) }
def max(a, b) def max(first, second)
(a > b) ? a : b (first > second) ? first : second
end end
sig { returns(T::Array[Token]) } sig { returns(T::Array[Token]) }

View File

@ -85,4 +85,4 @@ Flaky test detection and tracking is provided by [BuildPulse](https://buildpulse
[![DNSimple](https://cdn.dnsimple.com/assets/resolving-with-us/logo-light.png)](https://dnsimple.com/resolving/homebrew#gh-light-mode-only) [![DNSimple](https://cdn.dnsimple.com/assets/resolving-with-us/logo-light.png)](https://dnsimple.com/resolving/homebrew#gh-light-mode-only)
[![DNSimple](https://cdn.dnsimple.com/assets/resolving-with-us/logo-dark.png)](https://dnsimple.com/resolving/homebrew#gh-dark-mode-only) [![DNSimple](https://cdn.dnsimple.com/assets/resolving-with-us/logo-dark.png)](https://dnsimple.com/resolving/homebrew#gh-dark-mode-only)
Homebrew is generously supported by [Custom Ink](https://github.com/customink), [Randy Reddig](https://github.com/ydnar), [Sentry](https://github.com/getsentry), [Codecademy](https://github.com/Codecademy), [Appwrite](https://github.com/appwrite), [embark-studios](https://github.com/embark-studios), [Agilend](https://github.com/Agilend), and many other users and organisations via [GitHub Sponsors](https://github.com/sponsors/Homebrew). Homebrew is generously supported by [Custom Ink](https://github.com/customink), [Randy Reddig](https://github.com/ydnar), [Sentry](https://github.com/getsentry), [Codecademy](https://github.com/Codecademy), [Appwrite](https://github.com/appwrite), [Mercedes-Benz Group](https://github.com/mercedes-benz), [embark-studios](https://github.com/embark-studios), [Agilend](https://github.com/Agilend), and many other users and organisations via [GitHub Sponsors](https://github.com/sponsors/Homebrew).

View File

@ -1988,7 +1988,7 @@ _brew_upgrade() {
'(--formula)--vst-plugindir[Target location for VST Plugins (default: `~/Library/Audio/Plug-Ins/VST`)]' \ '(--formula)--vst-plugindir[Target location for VST Plugins (default: `~/Library/Audio/Plug-Ins/VST`)]' \
'(--formula)--vst3-plugindir[Target location for VST3 Plugins (default: `~/Library/Audio/Plug-Ins/VST3`)]' \ '(--formula)--vst3-plugindir[Target location for VST3 Plugins (default: `~/Library/Audio/Plug-Ins/VST3`)]' \
- outdated_formula \ - outdated_formula \
'(--casks --binaries --require-sha --quarantine --skip-cask-deps --greedy --greedy-latest --greedy-auto-updates --appdir --colorpickerdir --prefpanedir --qlplugindir --mdimporterdir --dictionarydir --fontdir --servicedir --input-methoddir --internet-plugindir --audio-unit-plugindir --vst-plugindir --vst3-plugindir --screen-saverdir --language)--formula[Treat all named arguments as formulae. If no named arguments are specified, upgrade only outdated formulae]' \ '(--casks --skip-cask-deps --greedy --greedy-latest --greedy-auto-updates --binaries --require-sha --quarantine --appdir --colorpickerdir --prefpanedir --qlplugindir --mdimporterdir --dictionarydir --fontdir --servicedir --input-methoddir --internet-plugindir --audio-unit-plugindir --vst-plugindir --vst3-plugindir --screen-saverdir --language)--formula[Treat all named arguments as formulae. If no named arguments are specified, upgrade only outdated formulae]' \
'*::outdated_formula:__brew_outdated_formulae' \ '*::outdated_formula:__brew_outdated_formulae' \
- outdated_cask \ - outdated_cask \
'(--formulae --build-from-source --interactive --force-bottle --fetch-HEAD --ignore-pinned --keep-tmp --debug-symbols --display-times)--cask[Treat all named arguments as casks. If no named arguments are specified, upgrade only outdated casks]' \ '(--formulae --build-from-source --interactive --force-bottle --fetch-HEAD --ignore-pinned --keep-tmp --debug-symbols --display-times)--cask[Treat all named arguments as casks. If no named arguments are specified, upgrade only outdated casks]' \

View File

@ -755,12 +755,6 @@ upgraded formulae or, every 30 days, for all formulae.
Print install times for each package at the end of the run. Print install times for each package at the end of the run.
* `--cask`: * `--cask`:
Treat all named arguments as casks. If no named arguments are specified, upgrade only outdated casks. Treat all named arguments as casks. If no named arguments are specified, upgrade only outdated casks.
* `--[no-]binaries`:
Disable/enable linking of helper executables (default: enabled).
* `--require-sha`:
Require all casks to have a checksum.
* `--[no-]quarantine`:
Disable/enable quarantining of downloads (default: enabled).
* `--skip-cask-deps`: * `--skip-cask-deps`:
Skip installing cask dependencies. Skip installing cask dependencies.
* `-g`, `--greedy`: * `-g`, `--greedy`:
@ -769,6 +763,12 @@ upgraded formulae or, every 30 days, for all formulae.
Also include casks with `version :latest`. Also include casks with `version :latest`.
* `--greedy-auto-updates`: * `--greedy-auto-updates`:
Also include casks with `auto_updates true`. Also include casks with `auto_updates true`.
* `--[no-]binaries`:
Disable/enable linking of helper executables (default: enabled).
* `--require-sha`:
Require all casks to have a checksum.
* `--[no-]quarantine`:
Disable/enable quarantining of downloads (default: enabled).
### `uses` [*`options`*] *`formula`* [...] ### `uses` [*`options`*] *`formula`* [...]

View File

@ -1058,18 +1058,6 @@ Print install times for each package at the end of the run\.
Treat all named arguments as casks\. If no named arguments are specified, upgrade only outdated casks\. Treat all named arguments as casks\. If no named arguments are specified, upgrade only outdated casks\.
. .
.TP .TP
\fB\-\-[no\-]binaries\fR
Disable/enable linking of helper executables (default: enabled)\.
.
.TP
\fB\-\-require\-sha\fR
Require all casks to have a checksum\.
.
.TP
\fB\-\-[no\-]quarantine\fR
Disable/enable quarantining of downloads (default: enabled)\.
.
.TP
\fB\-\-skip\-cask\-deps\fR \fB\-\-skip\-cask\-deps\fR
Skip installing cask dependencies\. Skip installing cask dependencies\.
. .
@ -1085,6 +1073,18 @@ Also include casks with \fBversion :latest\fR\.
\fB\-\-greedy\-auto\-updates\fR \fB\-\-greedy\-auto\-updates\fR
Also include casks with \fBauto_updates true\fR\. Also include casks with \fBauto_updates true\fR\.
. .
.TP
\fB\-\-[no\-]binaries\fR
Disable/enable linking of helper executables (default: enabled)\.
.
.TP
\fB\-\-require\-sha\fR
Require all casks to have a checksum\.
.
.TP
\fB\-\-[no\-]quarantine\fR
Disable/enable quarantining of downloads (default: enabled)\.
.
.SS "\fBuses\fR [\fIoptions\fR] \fIformula\fR [\.\.\.]" .SS "\fBuses\fR [\fIoptions\fR] \fIformula\fR [\.\.\.]"
Show formulae and casks that specify \fIformula\fR as a dependency; that is, show dependents of \fIformula\fR\. When given multiple formula arguments, show the intersection of formulae that use \fIformula\fR\. By default, \fBuses\fR shows all formulae and casks that specify \fIformula\fR as a required or recommended dependency for their stable builds\. Show formulae and casks that specify \fIformula\fR as a dependency; that is, show dependents of \fIformula\fR\. When given multiple formula arguments, show the intersection of formulae that use \fIformula\fR\. By default, \fBuses\fR shows all formulae and casks that specify \fIformula\fR as a required or recommended dependency for their stable builds\.
. .