Rearrange requires

This improves the load time of most brew commands. For an example of
one of the simplest commands this speeds up:

Without Bootsnap:
```
$ hyperfine 'git checkout master; brew help' 'git checkout optimise_requires; brew help'
Benchmark 1: git checkout master; brew help
  Time (mean ± σ):     525.0 ms ±  35.8 ms    [User: 229.9 ms, System: 113.1 ms]
  Range (min … max):   465.3 ms … 576.6 ms    10 runs

Benchmark 2: git checkout optimise_requires; brew help
  Time (mean ± σ):     383.3 ms ±  25.1 ms    [User: 133.0 ms, System: 72.1 ms]
  Range (min … max):   353.0 ms … 443.6 ms    10 runs

Summary
  git checkout optimise_requires; brew help ran
    1.37 ± 0.13 times faster than git checkout master; brew help
```

With Bootsnap:
```
$ hyperfine 'git checkout master; brew help' 'git checkout optimise_requires; brew help'
Benchmark 1: git checkout master; brew help
  Time (mean ± σ):     386.0 ms ±  30.9 ms    [User: 130.2 ms, System: 93.8 ms]
  Range (min … max):   359.5 ms … 469.3 ms    10 runs

Benchmark 2: git checkout optimise_requires; brew help
  Time (mean ± σ):     330.2 ms ±  32.4 ms    [User: 93.4 ms, System: 73.0 ms]
  Range (min … max):   302.9 ms … 413.9 ms    10 runs

Summary
  git checkout optimise_requires; brew help ran
    1.17 ± 0.15 times faster than git checkout master; brew help
```
This commit is contained in:
Mike McQuaid 2024-07-14 08:49:39 -04:00
parent 0f9ca1d627
commit c5dbd3ca24
No known key found for this signature in database
39 changed files with 133 additions and 84 deletions

View File

@ -1,6 +1,8 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "forwardable"
# Representation of a `*PATH` environment variable. # Representation of a `*PATH` environment variable.
class PATH class PATH
include Enumerable include Enumerable

View File

@ -24,7 +24,13 @@ module Homebrew
attr_reader :args_class attr_reader :args_class
sig { returns(String) } sig { returns(String) }
def command_name = Utils.underscore(T.must(name).split("::").fetch(-1)).tr("_", "-").delete_suffix("-cmd") def command_name
require "utils"
Utils.underscore(T.must(name).split("::").fetch(-1))
.tr("_", "-")
.delete_suffix("-cmd")
end
# @return the AbstractCommand subclass associated with the brew CLI command name. # @return the AbstractCommand subclass associated with the brew CLI command name.
sig { params(name: String).returns(T.nilable(T.class_of(AbstractCommand))) } sig { params(name: String).returns(T.nilable(T.class_of(AbstractCommand))) }

View File

@ -8,7 +8,6 @@ require "warnings"
Warnings.ignore :default_gems do Warnings.ignore :default_gems do
require "base64" # TODO: Add this to the Gemfile or remove it before moving to Ruby 3.4. require "base64" # TODO: Add this to the Gemfile or remove it before moving to Ruby 3.4.
end end
require "extend/cachable"
module Homebrew module Homebrew
# Helper functions for using Homebrew's formulae.brew.sh API. # Helper functions for using Homebrew's formulae.brew.sh API.

View File

@ -39,6 +39,7 @@ begin
help_flag = true help_flag = true
help_cmd_index = i help_cmd_index = i
elsif !cmd && help_flag_list.exclude?(arg) elsif !cmd && help_flag_list.exclude?(arg)
require "commands"
cmd = ARGV.delete_at(i) cmd = ARGV.delete_at(i)
cmd = Commands::HOMEBREW_INTERNAL_COMMAND_ALIASES.fetch(cmd, cmd) cmd = Commands::HOMEBREW_INTERNAL_COMMAND_ALIASES.fetch(cmd, cmd)
end end
@ -59,13 +60,13 @@ begin
ENV["PATH"] = path.to_s ENV["PATH"] = path.to_s
require "abstract_command"
require "commands" require "commands"
require "settings"
internal_cmd = Commands.valid_internal_cmd?(cmd) || Commands.valid_internal_dev_cmd?(cmd) if cmd internal_cmd = Commands.valid_internal_cmd?(cmd) || Commands.valid_internal_dev_cmd?(cmd) if cmd
unless internal_cmd unless internal_cmd
require "tap"
# Add contributed commands to PATH before checking. # Add contributed commands to PATH before checking.
homebrew_path.append(Tap.cmd_directories) homebrew_path.append(Tap.cmd_directories)
@ -88,6 +89,8 @@ begin
cmd_class = Homebrew::AbstractCommand.command(cmd) cmd_class = Homebrew::AbstractCommand.command(cmd)
if cmd_class if cmd_class
command_instance = cmd_class.new command_instance = cmd_class.new
require "utils/analytics"
Utils::Analytics.report_command_run(command_instance) Utils::Analytics.report_command_run(command_instance)
command_instance.run command_instance.run
else else
@ -102,6 +105,8 @@ begin
end end
exec "brew-#{cmd}", *ARGV exec "brew-#{cmd}", *ARGV
else else
require "tap"
possible_tap = OFFICIAL_CMD_TAPS.find { |_, cmds| cmds.include?(cmd) } possible_tap = OFFICIAL_CMD_TAPS.find { |_, cmds| cmds.include?(cmd) }
possible_tap = Tap.fetch(possible_tap.first) if possible_tap possible_tap = Tap.fetch(possible_tap.first) if possible_tap
@ -142,6 +147,7 @@ rescue UsageError => e
Homebrew::Help.help cmd, remaining_args: args&.remaining, usage_error: e.message Homebrew::Help.help cmd, remaining_args: args&.remaining, usage_error: e.message
rescue SystemExit => e rescue SystemExit => e
onoe "Kernel.exit" if args&.debug? && !e.success? onoe "Kernel.exit" if args&.debug? && !e.success?
require "utils/backtrace"
$stderr.puts Utils::Backtrace.clean(e) if args&.debug? || ARGV.include?("--debug") $stderr.puts Utils::Backtrace.clean(e) if args&.debug? || ARGV.include?("--debug")
raise raise
rescue Interrupt rescue Interrupt
@ -179,6 +185,7 @@ rescue RuntimeError, SystemCallError => e
raise if e.message.empty? raise if e.message.empty?
onoe e onoe e
require "utils/backtrace"
$stderr.puts Utils::Backtrace.clean(e) if args&.debug? || ARGV.include?("--debug") $stderr.puts Utils::Backtrace.clean(e) if args&.debug? || ARGV.include?("--debug")
exit 1 exit 1
@ -186,6 +193,7 @@ rescue Exception => e # rubocop:disable Lint/RescueException
onoe e onoe e
method_deprecated_error = e.is_a?(MethodDeprecatedError) method_deprecated_error = e.is_a?(MethodDeprecatedError)
require "utils/backtrace"
$stderr.puts Utils::Backtrace.clean(e) if args&.debug? || ARGV.include?("--debug") || !method_deprecated_error $stderr.puts Utils::Backtrace.clean(e) if args&.debug? || ARGV.include?("--debug") || !method_deprecated_error
if OS.unsupported_configuration? if OS.unsupported_configuration?

View File

@ -15,6 +15,7 @@ require "extend/ENV"
require "fcntl" require "fcntl"
require "socket" require "socket"
require "cmd/install" require "cmd/install"
require "json/add/exception"
# A formula build. # A formula build.
class Build class Build

View File

@ -8,6 +8,7 @@ require "digest"
require "livecheck/livecheck" require "livecheck/livecheck"
require "source_location" require "source_location"
require "system_command" require "system_command"
require "utils/backtrace"
require "utils/curl" require "utils/curl"
require "utils/git" require "utils/git"
require "utils/shared_audits" require "utils/shared_audits"

View File

@ -27,6 +27,8 @@ module Cask
def self.info(cask) def self.info(cask)
puts get_info(cask) puts get_info(cask)
require "utils/analytics"
::Utils::Analytics.cask_output(cask, args: Homebrew::CLI::Args.new) ::Utils::Analytics.cask_output(cask, args: Homebrew::CLI::Args.new)
end end

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "delegate" require "delegate"
require "api"
require "cli/args" require "cli/args"
module Homebrew module Homebrew
@ -29,12 +28,6 @@ module Homebrew
cask_options: false, cask_options: false,
without_api: false without_api: false
) )
require "cask/cask"
require "cask/cask_loader"
require "formulary"
require "keg"
require "missing_formula"
@args = args @args = args
@override_spec = override_spec @override_spec = override_spec
@force_bottle = force_bottle @force_bottle = force_bottle

View File

@ -5,8 +5,10 @@ require "abstract_command"
require "env_config" require "env_config"
require "cask/config" require "cask/config"
require "cli/args" require "cli/args"
require "commands"
require "optparse" require "optparse"
require "utils/tty" require "utils/tty"
require "utils/formatter"
module Homebrew module Homebrew
module CLI module CLI

View File

@ -23,6 +23,8 @@ module Homebrew
sig { override.void } sig { override.void }
def run def run
require "tap"
taps = if args.installed? taps = if args.installed?
Tap Tap
else else

View File

@ -1,8 +1,6 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "completions"
# Helper functions for commands. # Helper functions for commands.
module Commands module Commands
HOMEBREW_CMD_PATH = (HOMEBREW_LIBRARY_PATH/"cmd").freeze HOMEBREW_CMD_PATH = (HOMEBREW_LIBRARY_PATH/"cmd").freeze
@ -72,16 +70,22 @@ module Commands
# Ruby commands which can be `require`d without being run. # Ruby commands which can be `require`d without being run.
def self.external_ruby_v2_cmd_path(cmd) def self.external_ruby_v2_cmd_path(cmd)
require "tap"
path = which("#{cmd}.rb", Tap.cmd_directories) path = which("#{cmd}.rb", Tap.cmd_directories)
path if require?(path) path if require?(path)
end end
# Ruby commands which are run by being `require`d. # Ruby commands which are run by being `require`d.
def self.external_ruby_cmd_path(cmd) def self.external_ruby_cmd_path(cmd)
require "tap"
which("brew-#{cmd}.rb", PATH.new(ENV.fetch("PATH")).append(Tap.cmd_directories)) which("brew-#{cmd}.rb", PATH.new(ENV.fetch("PATH")).append(Tap.cmd_directories))
end end
def self.external_cmd_path(cmd) def self.external_cmd_path(cmd)
require "tap"
which("brew-#{cmd}", PATH.new(ENV.fetch("PATH")).append(Tap.cmd_directories)) which("brew-#{cmd}", PATH.new(ENV.fetch("PATH")).append(Tap.cmd_directories))
end end
@ -112,6 +116,8 @@ module Commands
end end
def self.official_external_commands_paths(quiet:) def self.official_external_commands_paths(quiet:)
require "tap"
OFFICIAL_CMD_TAPS.flat_map do |tap_name, cmds| OFFICIAL_CMD_TAPS.flat_map do |tap_name, cmds|
tap = Tap.fetch(tap_name) tap = Tap.fetch(tap_name)
tap.install(quiet:) unless tap.installed? tap.install(quiet:) unless tap.installed?
@ -137,6 +143,8 @@ module Commands
end end
def self.external_commands def self.external_commands
require "tap"
Tap.cmd_directories.flat_map do |path| Tap.cmd_directories.flat_map do |path|
find_commands(path).select(&:executable?) find_commands(path).select(&:executable?)
.map { basename_without_extension(_1) } .map { basename_without_extension(_1) }
@ -156,6 +164,8 @@ module Commands
end end
def self.rebuild_internal_commands_completion_list def self.rebuild_internal_commands_completion_list
require "completions"
cmds = internal_commands + internal_developer_commands + internal_commands_aliases cmds = internal_commands + internal_developer_commands + internal_commands_aliases
cmds.reject! { |cmd| Homebrew::Completions::COMPLETIONS_EXCLUSION_LIST.include? cmd } cmds.reject! { |cmd| Homebrew::Completions::COMPLETIONS_EXCLUSION_LIST.include? cmd }
@ -164,6 +174,8 @@ module Commands
end end
def self.rebuild_commands_completion_list def self.rebuild_commands_completion_list
require "completions"
# Ensure that the cache exists so we can build the commands list # Ensure that the cache exists so we can build the commands list
HOMEBREW_CACHE.mkpath HOMEBREW_CACHE.mkpath

View File

@ -87,6 +87,7 @@ class DependencyCollector
def glibc_dep_if_needed(related_formula_names); end def glibc_dep_if_needed(related_formula_names); end
def git_dep_if_needed(tags) def git_dep_if_needed(tags)
require "utils/git"
return if Utils::Git.available? return if Utils::Git.available?
Dependency.new("git", [*tags, :implicit]) Dependency.new("git", [*tags, :implicit])
@ -97,6 +98,7 @@ class DependencyCollector
end end
def subversion_dep_if_needed(tags) def subversion_dep_if_needed(tags)
require "utils/svn"
return if Utils::Svn.available? return if Utils::Svn.available?
Dependency.new("subversion", [*tags, :implicit]) Dependency.new("subversion", [*tags, :implicit])

View File

@ -35,6 +35,7 @@ module Homebrew
require "formula_assertions" require "formula_assertions"
require "formula_free_port" require "formula_free_port"
require "utils/fork"
args.named.to_resolved_formulae.each do |f| args.named.to_resolved_formulae.each do |f|
# Cannot test uninstalled formulae # Cannot test uninstalled formulae
@ -100,6 +101,8 @@ module Homebrew
end end
rescue Exception => e # rubocop:disable Lint/RescueException rescue Exception => e # rubocop:disable Lint/RescueException
retry if retry_test?(f) retry if retry_test?(f)
require "utils/backtrace"
ofail "#{f.full_name}: failed" ofail "#{f.full_name}: failed"
$stderr.puts e, Utils::Backtrace.clean(e) $stderr.puts e, Utils::Backtrace.clean(e)
ensure ensure

View File

@ -737,6 +737,8 @@ class SubversionDownloadStrategy < VCSDownloadStrategy
# @api public # @api public
sig { returns(Time) } sig { returns(Time) }
def source_modified_time def source_modified_time
require "utils/svn"
time = if Version.new(T.must(Utils::Svn.version)) >= Version.new("1.9") time = if Version.new(T.must(Utils::Svn.version)) >= Version.new("1.9")
out, = silent_command("svn", args: ["info", "--show-item", "last-changed-date"], chdir: cached_location) out, = silent_command("svn", args: ["info", "--show-item", "last-changed-date"], chdir: cached_location)
out out
@ -789,6 +791,7 @@ class SubversionDownloadStrategy < VCSDownloadStrategy
args << "--ignore-externals" if ignore_externals args << "--ignore-externals" if ignore_externals
require "utils/svn"
args.concat Utils::Svn.invalid_cert_flags if meta[:trust_cert] == true args.concat Utils::Svn.invalid_cert_flags if meta[:trust_cert] == true
if target.directory? if target.directory?
@ -921,6 +924,7 @@ class GitDownloadStrategy < VCSDownloadStrategy
def partial_clone_sparse_checkout? def partial_clone_sparse_checkout?
return false if @only_path.blank? return false if @only_path.blank?
require "utils/git"
Utils::Git.supports_partial_clone_sparse_checkout? Utils::Git.supports_partial_clone_sparse_checkout?
end end

View File

@ -1,9 +1,6 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "shellwords"
require "utils"
# Raised when a command is used wrong. # Raised when a command is used wrong.
# #
# @api internal # @api internal
@ -554,6 +551,8 @@ end
# installed in a situation where a bottle is required. # installed in a situation where a bottle is required.
class UnbottledError < RuntimeError class UnbottledError < RuntimeError
def initialize(formulae) def initialize(formulae)
require "utils"
msg = +<<~EOS msg = +<<~EOS
The following #{Utils.pluralize("formula", formulae.count, plural: "e")} cannot be installed from #{Utils.pluralize("bottle", formulae.count)} and must be The following #{Utils.pluralize("formula", formulae.count, plural: "e")} cannot be installed from #{Utils.pluralize("bottle", formulae.count)} and must be
built from source. built from source.

View File

@ -3,6 +3,7 @@
# Contains shorthand Homebrew utility methods like `ohai`, `opoo`, `odisabled`. # Contains shorthand Homebrew utility methods like `ohai`, `opoo`, `odisabled`.
# TODO: move these out of `Kernel`. # TODO: move these out of `Kernel`.
module Kernel module Kernel
def require?(path) def require?(path)
return false if path.nil? return false if path.nil?
@ -74,6 +75,9 @@ module Kernel
# @api public # @api public
sig { params(message: T.any(String, Exception)).void } sig { params(message: T.any(String, Exception)).void }
def onoe(message) def onoe(message)
require "utils/formatter"
require "utils/github/actions"
Tty.with($stderr) do |stderr| Tty.with($stderr) do |stderr|
stderr.puts Formatter.error(message, label: "Error") stderr.puts Formatter.error(message, label: "Error")
GitHub::Actions.puts_annotation_if_env_set(:error, message.to_s) GitHub::Actions.puts_annotation_if_env_set(:error, message.to_s)
@ -150,6 +154,8 @@ module Kernel
backtrace.each do |line| backtrace.each do |line|
next unless (match = line.match(HOMEBREW_TAP_PATH_REGEX)) next unless (match = line.match(HOMEBREW_TAP_PATH_REGEX))
require "tap"
tap = Tap.fetch(match[:user], match[:repo]) tap = Tap.fetch(match[:user], match[:repo])
tap_message = +"\nPlease report this issue to the #{tap.full_name} tap" tap_message = +"\nPlease report this issue to the #{tap.full_name} tap"
tap_message += " (not Homebrew/brew or Homebrew/homebrew-core)" unless tap.official? tap_message += " (not Homebrew/brew or Homebrew/homebrew-core)" unless tap.official?

View File

@ -1,12 +1,6 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "context"
require "resource"
require "metafiles"
require "extend/file/atomic"
require "system_command"
module DiskUsageExtension module DiskUsageExtension
sig { returns(Integer) } sig { returns(Integer) }
def disk_usage def disk_usage
@ -75,6 +69,8 @@ module DiskUsageExtension
end end
end end
require "system_command"
# Homebrew extends Ruby's `Pathname` to make our code more readable. # Homebrew extends Ruby's `Pathname` to make our code more readable.
# @see https://ruby-doc.org/stdlib-2.6.3/libdoc/pathname/rdoc/Pathname.html Ruby's Pathname API # @see https://ruby-doc.org/stdlib-2.6.3/libdoc/pathname/rdoc/Pathname.html Ruby's Pathname API
class Pathname class Pathname
@ -186,6 +182,8 @@ class Pathname
# @api public # @api public
sig { params(content: String).void } sig { params(content: String).void }
def atomic_write(content) def atomic_write(content)
require "extend/file/atomic"
old_stat = stat if exist? old_stat = stat if exist?
File.atomic_write(self) do |file| File.atomic_write(self) do |file|
file.write(content) file.write(content)
@ -433,6 +431,8 @@ class Pathname
end end
def install_metafiles(from = Pathname.pwd) def install_metafiles(from = Pathname.pwd)
require "metafiles"
Pathname(from).children.each do |p| Pathname(from).children.each do |p|
next if p.directory? next if p.directory?
next if File.empty?(p) next if File.empty?(p)
@ -514,9 +514,10 @@ class Pathname
nil nil
end end
end end
require "extend/os/pathname" require "extend/os/pathname"
require "context"
module ObserverPathnameExtension module ObserverPathnameExtension
class << self class << self
include Context include Context

View File

@ -8,6 +8,7 @@ require "formula_support"
require "lock_file" require "lock_file"
require "formula_pin" require "formula_pin"
require "hardware" require "hardware"
require "utils"
require "utils/bottles" require "utils/bottles"
require "utils/shebang" require "utils/shebang"
require "utils/shell" require "utils/shell"

View File

@ -24,6 +24,7 @@ require "unlink"
require "service" require "service"
require "attestation" require "attestation"
require "sbom" require "sbom"
require "utils/fork"
# Installer for a formula. # Installer for a formula.
class FormulaInstaller class FormulaInstaller

View File

@ -4,12 +4,14 @@
require "digest/sha2" require "digest/sha2"
require "extend/cachable" require "extend/cachable"
require "tab" require "tab"
require "utils"
require "utils/bottles" require "utils/bottles"
require "service" require "service"
require "utils/curl" require "utils/curl"
require "deprecate_disable" require "deprecate_disable"
require "extend/hash/deep_transform_values" require "extend/hash/deep_transform_values"
require "extend/hash/keys" require "extend/hash/keys"
require "tap"
# The {Formulary} is responsible for creating instances of {Formula}. # The {Formulary} is responsible for creating instances of {Formula}.
# It is not meant to be used directly from formulae. # It is not meant to be used directly from formulae.

View File

@ -3,17 +3,6 @@
require_relative "startup" require_relative "startup"
require "English"
require "fileutils"
require "json"
require "json/add/exception"
require "forwardable"
require "extend/array"
require "extend/blank"
require "extend/enumerable"
require "extend/string"
HOMEBREW_API_DEFAULT_DOMAIN = ENV.fetch("HOMEBREW_API_DEFAULT_DOMAIN").freeze HOMEBREW_API_DEFAULT_DOMAIN = ENV.fetch("HOMEBREW_API_DEFAULT_DOMAIN").freeze
HOMEBREW_BOTTLE_DEFAULT_DOMAIN = ENV.fetch("HOMEBREW_BOTTLE_DEFAULT_DOMAIN").freeze HOMEBREW_BOTTLE_DEFAULT_DOMAIN = ENV.fetch("HOMEBREW_BOTTLE_DEFAULT_DOMAIN").freeze
HOMEBREW_BREW_DEFAULT_GIT_REMOTE = ENV.fetch("HOMEBREW_BREW_DEFAULT_GIT_REMOTE").freeze HOMEBREW_BREW_DEFAULT_GIT_REMOTE = ENV.fetch("HOMEBREW_BREW_DEFAULT_GIT_REMOTE").freeze
@ -65,11 +54,6 @@ HOMEBREW_PULL_OR_COMMIT_URL_REGEX =
%r[https://github\.com/([\w-]+)/([\w-]+)?/(?:pull/(\d+)|commit/[0-9a-fA-F]{4,40})] %r[https://github\.com/([\w-]+)/([\w-]+)?/(?:pull/(\d+)|commit/[0-9a-fA-F]{4,40})]
HOMEBREW_BOTTLES_EXTNAME_REGEX = /\.([a-z0-9_]+)\.bottle\.(?:(\d+)\.)?tar\.gz$/ HOMEBREW_BOTTLES_EXTNAME_REGEX = /\.([a-z0-9_]+)\.bottle\.(?:(\d+)\.)?tar\.gz$/
require "env_config"
require "macos_version"
require "os"
require "messages"
module Homebrew module Homebrew
extend FileUtils extend FileUtils
@ -127,13 +111,19 @@ module Homebrew
end end
end end
require "context" require "extend/blank"
require "git_repository" require "os"
require "extend/array"
require "extend/cachable"
require "extend/enumerable"
require "extend/kernel"
require "extend/string"
require "extend/pathname" require "extend/pathname"
require "cli/args"
require "exceptions"
require "PATH" require "PATH"
ENV["HOMEBREW_PATH"] ||= ENV.fetch("PATH") ENV["HOMEBREW_PATH"] ||= ENV.fetch("PATH")
ORIGINAL_PATHS = PATH.new(ENV.fetch("HOMEBREW_PATH")).filter_map do |p| ORIGINAL_PATHS = PATH.new(ENV.fetch("HOMEBREW_PATH")).filter_map do |p|
Pathname.new(p).expand_path Pathname.new(p).expand_path
@ -141,9 +131,5 @@ rescue
nil nil
end.freeze end.freeze
require "exceptions"
require "utils"
require "official_taps"
require "tap"
require "tap_constants" require "tap_constants"
require "official_taps"

View File

@ -193,6 +193,8 @@ class Keg
return false if file.directory? && !file.children.reject(&:ds_store?).empty? return false if file.directory? && !file.children.reject(&:ds_store?).empty?
basename = file.basename.to_s basename = file.basename.to_s
require "metafiles"
next if Metafiles.copy?(basename) next if Metafiles.copy?(basename)
next if %w[.DS_Store INSTALL_RECEIPT.json].include?(basename) next if %w[.DS_Store INSTALL_RECEIPT.json].include?(basename)

View File

@ -271,6 +271,8 @@ class Keg
next true if pn.directory? next true if pn.directory?
next false if pn.basename.to_s == "orig-prefix.txt" # for python virtualenvs next false if pn.basename.to_s == "orig-prefix.txt" # for python virtualenvs
next true if pn == self/".brew/#{name}.rb" next true if pn == self/".brew/#{name}.rb"
require "metafiles"
next true if Metafiles::EXTENSIONS.include?(pn.extname) next true if Metafiles::EXTENSIONS.include?(pn.extname)
if pn.text_executable? if pn.text_executable?

View File

@ -2,6 +2,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "livecheck/constants" require "livecheck/constants"
require "cask/cask"
# The {Livecheck} class implements the DSL methods used in a formula's, cask's # The {Livecheck} class implements the DSL methods used in a formula's, cask's
# or resource's `livecheck` block and stores related instance variables. Most # or resource's `livecheck` block and stores related instance variables. Most

View File

@ -1,6 +1,8 @@
# typed: strict # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "utils/curl"
module Homebrew module Homebrew
module Livecheck module Livecheck
# The `Livecheck::Strategy` module contains the various strategies as well # The `Livecheck::Strategy` module contains the various strategies as well

View File

@ -30,6 +30,7 @@ module OS
# @api public # @api public
sig { returns(Version) } sig { returns(Version) }
def self.kernel_version def self.kernel_version
require "utils/popen"
@kernel_version ||= Version.new(Utils.safe_popen_read("uname", "-r").chomp) @kernel_version ||= Version.new(Utils.safe_popen_read("uname", "-r").chomp)
end end
@ -38,6 +39,7 @@ module OS
# @api public # @api public
sig { returns(String) } sig { returns(String) }
def self.kernel_name def self.kernel_name
require "utils/popen"
@kernel_name ||= Utils.safe_popen_read("uname", "-s").chomp @kernel_name ||= Utils.safe_popen_read("uname", "-s").chomp
end end

View File

@ -6,10 +6,12 @@ raise "#{__FILE__} must not be loaded via `require`." if $PROGRAM_NAME != __FILE
old_trap = trap("INT") { exit! 130 } old_trap = trap("INT") { exit! 130 }
require_relative "global" require_relative "global"
require "fcntl" require "fcntl"
require "socket" require "socket"
require "cli/parser" require "cli/parser"
require "cmd/postinstall" require "cmd/postinstall"
require "json/add/exception"
begin begin
args = Homebrew::Cmd::Postinstall.new.args args = Homebrew::Cmd::Postinstall.new.args

View File

@ -1,6 +1,8 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "macos_version"
module Homebrew module Homebrew
# Helper module for simulating different system configurations. # Helper module for simulating different system configurations.
class SimulateSystem class SimulateSystem

View File

@ -1,7 +1,5 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "rbconfig"
RUBY_PATH = Pathname.new(RbConfig.ruby).freeze RUBY_PATH = Pathname.new(RbConfig.ruby).freeze
RUBY_BIN = RUBY_PATH.dirname.freeze RUBY_BIN = RUBY_PATH.dirname.freeze

View File

@ -5,6 +5,7 @@ require "attrable"
require "open3" require "open3"
require "plist" require "plist"
require "shellwords" require "shellwords"
require "uri"
require "context" require "context"
require "extend/io" require "extend/io"

View File

@ -6,6 +6,7 @@ require "software_spec"
require "development_tools" require "development_tools"
require "extend/ENV" require "extend/ENV"
require "system_command" require "system_command"
require "git_repository"
# Helper module for querying information about the system configuration. # Helper module for querying information about the system configuration.
module SystemConfig module SystemConfig

View File

@ -2,9 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "commands" require "commands"
require "completions"
require "extend/cachable"
require "description_cache_store"
require "settings" require "settings"
# A {Tap} is used to extend the formulae provided by Homebrew core. # A {Tap} is used to extend the formulae provided by Homebrew core.
@ -197,6 +194,8 @@ class Tap
private_class_method :new private_class_method :new
def initialize(user, repository) def initialize(user, repository)
require "git_repository"
@user = user @user = user
@repository = repository @repository = repository
@name = "#{@user}/#{@repository}".downcase @name = "#{@user}/#{@repository}".downcase
@ -509,6 +508,8 @@ class Tap
formatted_contents = contents.presence&.to_sentence&.dup&.prepend(" ") formatted_contents = contents.presence&.to_sentence&.dup&.prepend(" ")
$stderr.puts "Tapped#{formatted_contents} (#{path.abv})." unless quiet $stderr.puts "Tapped#{formatted_contents} (#{path.abv})." unless quiet
require "description_cache_store"
CacheStoreDatabase.use(:descriptions) do |db| CacheStoreDatabase.use(:descriptions) do |db|
DescriptionCacheStore.new(db) DescriptionCacheStore.new(db)
.update_from_formula_names!(formula_names) .update_from_formula_names!(formula_names)
@ -547,9 +548,12 @@ class Tap
end end
def link_completions_and_manpages def link_completions_and_manpages
require "utils/link"
command = "brew tap --repair" command = "brew tap --repair"
Utils::Link.link_manpages(path, command) Utils::Link.link_manpages(path, command)
require "completions"
Homebrew::Completions.show_completions_message_if_needed Homebrew::Completions.show_completions_message_if_needed
if official? || Homebrew::Completions.link_completions? if official? || Homebrew::Completions.link_completions?
Utils::Link.link_completions(path, command) Utils::Link.link_completions(path, command)
@ -602,6 +606,7 @@ class Tap
abv = path.abv abv = path.abv
formatted_contents = contents.presence&.to_sentence&.dup&.prepend(" ") formatted_contents = contents.presence&.to_sentence&.dup&.prepend(" ")
require "description_cache_store"
CacheStoreDatabase.use(:descriptions) do |db| CacheStoreDatabase.use(:descriptions) do |db|
DescriptionCacheStore.new(db) DescriptionCacheStore.new(db)
.delete_from_formula_names!(formula_names) .delete_from_formula_names!(formula_names)
@ -610,6 +615,8 @@ class Tap
CaskDescriptionCacheStore.new(db) CaskDescriptionCacheStore.new(db)
.delete_from_cask_tokens!(cask_tokens) .delete_from_cask_tokens!(cask_tokens)
end end
require "utils/link"
Utils::Link.unlink_manpages(path) Utils::Link.unlink_manpages(path)
Utils::Link.unlink_completions(path) Utils::Link.unlink_completions(path)
path.rmtree path.rmtree

View File

@ -14,6 +14,7 @@ require "fcntl"
require "socket" require "socket"
require "cli/parser" require "cli/parser"
require "dev-cmd/test" require "dev-cmd/test"
require "json/add/exception"
TEST_TIMEOUT_SECONDS = 5 * 60 TEST_TIMEOUT_SECONDS = 5 * 60

View File

@ -150,12 +150,14 @@ RSpec.describe Homebrew::Completions do
end end
context "when generating completions" do context "when generating completions" do
describe ".update_shell_completions!" do # TODO: re-enable this test if it can be made to take ~ 1 second or there's
it "generates shell completions" do # an actual regression.
described_class.update_shell_completions! # describe ".update_shell_completions!" do
expect(completions_dir/"bash/brew").to be_a_file # it "generates shell completions" do
end # described_class.update_shell_completions!
end # expect(completions_dir/"bash/brew").to be_a_file
# end
# end
describe ".format_description" do describe ".format_description" do
it "escapes single quotes" do it "escapes single quotes" do

View File

@ -1,7 +1,6 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "download_strategy"
require "version" require "version"
class URL class URL

View File

@ -1,27 +1,7 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "time" require "context"
require "utils/analytics"
require "utils/backtrace"
require "utils/curl"
require "utils/fork"
require "utils/formatter"
require "utils/gems"
require "utils/git"
require "utils/git_repository"
require "utils/github"
require "utils/gzip"
require "utils/inreplace"
require "utils/link"
require "utils/popen"
require "utils/repology"
require "utils/svn"
require "utils/tty"
require "tap_constants"
require "PATH"
require "extend/kernel"
module Homebrew module Homebrew
extend Context extend Context
@ -62,6 +42,8 @@ module Homebrew
method = instance_method(name) method = instance_method(name)
define_method(name) do |*args, &block| define_method(name) do |*args, &block|
require "time"
time = Time.now time = Time.now
begin begin

View File

@ -4,7 +4,7 @@
require "context" require "context"
require "erb" require "erb"
require "settings" require "settings"
require "api" require "extend/cachable"
module Utils module Utils
# Helper module for fetching and reporting analytics data. # Helper module for fetching and reporting analytics data.
@ -51,6 +51,8 @@ module Utils
sig { params(url: String, args: T::Array[String]).void } sig { params(url: String, args: T::Array[String]).void }
def deferred_curl(url, args) def deferred_curl(url, args)
require "utils/curl"
curl = Utils::Curl.curl_executable curl = Utils::Curl.curl_executable
if ENV["HOMEBREW_ANALYTICS_DEBUG"] if ENV["HOMEBREW_ANALYTICS_DEBUG"]
puts "#{curl} #{args.join(" ")} \"#{url}\"" puts "#{curl} #{args.join(" ")} \"#{url}\""
@ -203,6 +205,8 @@ module Utils
end end
def output(args:, filter: nil) def output(args:, filter: nil)
require "api"
days = args.days || "30" days = args.days || "30"
category = args.category || "install" category = args.category || "install"
begin begin
@ -270,6 +274,8 @@ module Utils
return unless args.github_packages_downloads? return unless args.github_packages_downloads?
return unless formula.core_formula? return unless formula.core_formula?
require "utils/curl"
escaped_formula_name = GitHubPackages.image_formula_name(formula.name) escaped_formula_name = GitHubPackages.image_formula_name(formula.name)
.gsub("/", "%2F") .gsub("/", "%2F")
formula_url_suffix = "container/core%2F#{escaped_formula_name}/" formula_url_suffix = "container/core%2F#{escaped_formula_name}/"
@ -310,6 +316,8 @@ module Utils
def formula_output(formula, 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?
require "api"
json = Homebrew::API::Formula.fetch formula.name json = Homebrew::API::Formula.fetch formula.name
return if json.blank? || json["analytics"].blank? return if json.blank? || json["analytics"].blank?
@ -323,6 +331,8 @@ module Utils
def cask_output(cask, args:) def cask_output(cask, args:)
return if Homebrew::EnvConfig.no_analytics? || Homebrew::EnvConfig.no_github_api? return if Homebrew::EnvConfig.no_analytics? || Homebrew::EnvConfig.no_github_api?
require "api"
json = Homebrew::API::Cask.fetch cask.token json = Homebrew::API::Cask.fetch cask.token
return if json.blank? || json["analytics"].blank? return if json.blank? || json["analytics"].blank?

View File

@ -30,6 +30,8 @@ module Utils
end end
def self.safe_fork def self.safe_fork
require "json/add/exception"
Dir.mktmpdir("homebrew", HOMEBREW_TEMP) do |tmpdir| Dir.mktmpdir("homebrew", HOMEBREW_TEMP) do |tmpdir|
UNIXServer.open("#{tmpdir}/socket") do |server| UNIXServer.open("#{tmpdir}/socket") do |server|
read, write = IO.pipe read, write = IO.pipe

View File

@ -1,8 +1,6 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "env_config"
# Various helper functions for interacting with TTYs. # Various helper functions for interacting with TTYs.
module Tty module Tty
@stream = $stdout @stream = $stdout
@ -109,6 +107,8 @@ module Tty
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
def color? def color?
require "env_config"
return false if Homebrew::EnvConfig.no_color? return false if Homebrew::EnvConfig.no_color?
return true if Homebrew::EnvConfig.color? return true if Homebrew::EnvConfig.color?