Refactor commands to remove "require cmd/help"

This commit is contained in:
Andrew Janke 2018-06-05 23:19:18 -04:00
parent 6a700cbfb6
commit 8b55cb5ecb
19 changed files with 346 additions and 312 deletions

View File

@ -78,8 +78,8 @@ begin
# - no arguments are passed
# - if cmd is Cask, let Cask handle the help command instead
if (empty_argv || help_flag) && cmd != "cask"
require "cmd/help"
Homebrew.help cmd, empty_argv: empty_argv
require "help"
Homebrew::Help.help cmd, empty_argv: empty_argv
# `Homebrew.help` never returns, except for external/unknown commands.
end
@ -119,8 +119,8 @@ begin
exec HOMEBREW_BREW_FILE, cmd, *ARGV
end
rescue UsageError => e
require "cmd/help"
Homebrew.help cmd, usage_error: e.message
require "help"
Homebrew::Help.help cmd, usage_error: e.message
rescue SystemExit => e
onoe "Kernel.exit" if ARGV.verbose? && !e.success?
$stderr.puts e.backtrace if ARGV.debug?

View File

@ -1,10 +1,10 @@
#: * `--cache`:
#: Display Homebrew's download cache. See also `HOMEBREW_CACHE`.
#:
#: * `--cache` <formula>:
#: * `--cache` [`--build-from-source`|`-s`] [`--force-bottle`] <formula>:
#: Display the file or directory used to cache <formula>.
require "cmd/fetch"
require "fetch"
module Homebrew
module_function
@ -14,7 +14,7 @@ module Homebrew
puts HOMEBREW_CACHE
else
ARGV.formulae.each do |f|
if fetch_bottle?(f)
if Fetch.fetch_bottle?(f)
puts f.bottle.cached_download
else
puts f.cached_download

View File

@ -23,6 +23,7 @@
#: installation.
require "formula"
require "fetch"
module Homebrew
module_function
@ -46,7 +47,7 @@ module Homebrew
f.print_tap_action verb: "Fetching"
fetched_bottle = false
if fetch_bottle?(f)
if Fetch.fetch_bottle?(f)
begin
fetch_formula(f.bottle)
rescue Interrupt
@ -73,14 +74,6 @@ module Homebrew
end
end
def fetch_bottle?(f)
return true if ARGV.force_bottle? && f.bottle
return false unless f.bottle && f.pour_bottle?
return false if ARGV.build_formula_from_source?(f)
return false unless f.bottle.compatible_cellar?
true
end
def fetch_resource(r)
puts "Resource: #{r.name}"
fetch_fetchable r

View File

@ -1,91 +1,7 @@
HOMEBREW_HELP = <<~EOS.freeze
Example usage:
brew search [TEXT|/REGEX/]
brew info [FORMULA...]
brew install FORMULA...
brew update
brew upgrade [FORMULA...]
brew uninstall FORMULA...
brew list [FORMULA...]
Troubleshooting:
brew config
brew doctor
brew install --verbose --debug FORMULA
Contributing:
brew create [URL [--no-fetch]]
brew edit [FORMULA...]
Further help:
brew commands
brew help [COMMAND]
man brew
https://docs.brew.sh
EOS
# NOTE Keep the lenth of vanilla --help less than 25 lines!
# This is because the default Terminal height is 25 lines. Scrolling sucks
# and concision is important. If more help is needed we should start
# specialising help like the gem command does.
# NOTE Keep lines less than 80 characters! Wrapping is just not cricket.
# NOTE The reason the string is at the top is so 25 lines is easy to measure!
require "commands"
require "help"
module Homebrew
module_function
def help(cmd = nil, flags = {})
# Resolve command aliases and find file containing the implementation.
if cmd
cmd = HOMEBREW_INTERNAL_COMMAND_ALIASES.fetch(cmd, cmd)
path = Commands.path(cmd)
path ||= which("brew-#{cmd}")
path ||= which("brew-#{cmd}.rb")
end
# Display command-specific (or generic) help in response to `UsageError`.
if (error_message = flags[:usage_error])
$stderr.puts path ? command_help(path) : HOMEBREW_HELP
$stderr.puts
onoe error_message
exit 1
end
# Handle `brew` (no arguments).
if flags[:empty_argv]
$stderr.puts HOMEBREW_HELP
exit 1
end
# Handle `brew (-h|--help|--usage|-?|help)` (no other arguments).
if cmd.nil?
puts HOMEBREW_HELP
exit 0
end
# Resume execution in `brew.rb` for unknown commands.
return if path.nil?
# Display help for internal command (or generic help if undocumented).
puts command_help(path)
exit 0
end
def command_help(path)
help_lines = command_help_lines(path)
if help_lines.empty?
opoo "No help text in: #{path}" if ARGV.homebrew_developer?
HOMEBREW_HELP
else
help_lines.map do |line|
line.sub(/^ \* /, "#{Tty.bold}brew#{Tty.reset} ")
.gsub(/`(.*?)`/, "#{Tty.bold}\\1#{Tty.reset}")
.gsub(%r{<([^\s]+?://[^\s]+?)>}) { |url| Formatter.url(url) }
.gsub(/<(.*?)>/, "#{Tty.underline}\\1#{Tty.reset}")
.gsub("@hide_from_man_page", "")
end.join.strip
end
Help.help(cmd, flags)
end
end

View File

@ -68,11 +68,10 @@
#: creating patches to the software.
require "missing_formula"
require "diagnostic"
require "cmd/search"
require "formula_installer"
require "hardware"
require "development_tools"
require "install"
module Homebrew
module_function
@ -238,7 +237,7 @@ module Homebrew
end
return if formulae.empty?
perform_preinstall_checks
Install.perform_preinstall_checks
formulae.each do |f|
Migrator.migrate_if_needed(f)
@ -298,47 +297,6 @@ module Homebrew
end
end
def check_ppc
case Hardware::CPU.type
when :ppc
abort <<~EOS
Sorry, Homebrew does not support your computer's CPU architecture.
For PPC support, see: https://github.com/mistydemeo/tigerbrew
EOS
end
end
def check_writable_install_location
raise "Cannot write to #{HOMEBREW_CELLAR}" if HOMEBREW_CELLAR.exist? && !HOMEBREW_CELLAR.writable_real?
raise "Cannot write to #{HOMEBREW_PREFIX}" unless HOMEBREW_PREFIX.writable_real? || HOMEBREW_PREFIX.to_s == "/usr/local"
end
def check_development_tools
checks = Diagnostic::Checks.new
checks.fatal_development_tools_checks.each do |check|
out = checks.send(check)
next if out.nil?
ofail out
end
exit 1 if Homebrew.failed?
end
def check_cellar
FileUtils.mkdir_p HOMEBREW_CELLAR unless File.exist? HOMEBREW_CELLAR
rescue
raise <<~EOS
Could not create #{HOMEBREW_CELLAR}
Check you have permission to write to #{HOMEBREW_CELLAR.parent}
EOS
end
def perform_preinstall_checks
check_ppc
check_writable_install_location
check_development_tools if DevelopmentTools.installed?
check_cellar
end
def install_formula(f)
f.print_tap_action
build_options = f.build

View File

@ -26,7 +26,7 @@ module Homebrew
mode.dry_run = true if ARGV.dry_run?
ARGV.kegs.each do |keg|
keg_only = keg_only?(keg.rack)
keg_only = Formulary.keg_only?(keg.rack)
if HOMEBREW_PREFIX.to_s == "/usr/local" && keg_only &&
keg.name.start_with?("openssl", "libressl")
opoo <<~EOS
@ -87,10 +87,4 @@ module Homebrew
puts " #{Utils::Shell.prepend_path_in_profile(opt/"bin")}" if bin.directory?
puts " #{Utils::Shell.prepend_path_in_profile(opt/"sbin")}" if sbin.directory?
end
def keg_only?(rack)
Formulary.from_rack(rack).keg_only?
rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError
false
end
end

View File

@ -21,6 +21,7 @@
require "json"
require "open3"
require "style"
module Homebrew
module_function
@ -53,153 +54,6 @@ module Homebrew
NewFormulaAudit]
end
Homebrew.failed = check_style_and_print(target, options)
end
# Checks style for a list of files, printing simple RuboCop output.
# Returns true if violations were found, false otherwise.
def check_style_and_print(files, options = {})
check_style_impl(files, :print, options)
end
# Checks style for a list of files, returning results as a RubocopResults
# object parsed from its JSON output.
def check_style_json(files, options = {})
check_style_impl(files, :json, options)
end
def check_style_impl(files, output_type, options = {})
fix = options[:fix]
Homebrew.install_gem_setup_path! "rubocop", HOMEBREW_RUBOCOP_VERSION
require "rubocop"
require_relative "../rubocops"
args = %w[
--force-exclusion
]
if fix
args << "--auto-correct"
else
args << "--parallel"
end
if ARGV.include?("--rspec")
Homebrew.install_gem! "rubocop-rspec"
args += %w[--require rubocop-rspec]
end
if options[:except_cops]
options[:except_cops].map! { |cop| RuboCop::Cop::Cop.registry.qualified_cop_name(cop.to_s, "") }
cops_to_exclude = options[:except_cops].select do |cop|
RuboCop::Cop::Cop.registry.names.include?(cop) ||
RuboCop::Cop::Cop.registry.departments.include?(cop.to_sym)
end
args << "--except" << cops_to_exclude.join(",") unless cops_to_exclude.empty?
elsif options[:only_cops]
options[:only_cops].map! { |cop| RuboCop::Cop::Cop.registry.qualified_cop_name(cop.to_s, "") }
cops_to_include = options[:only_cops].select do |cop|
RuboCop::Cop::Cop.registry.names.include?(cop) ||
RuboCop::Cop::Cop.registry.departments.include?(cop.to_sym)
end
if cops_to_include.empty?
odie "RuboCops #{options[:only_cops].join(",")} were not found"
end
args << "--only" << cops_to_include.join(",")
end
if files.nil?
config_file = ARGV.include?("--rspec") ? ".rubocop-rspec.yml" : ".rubocop.yml"
args << "--config" << HOMEBREW_LIBRARY_PATH/config_file
args << HOMEBREW_LIBRARY_PATH
else
args << "--config" << HOMEBREW_LIBRARY/".rubocop_audit.yml"
args += files
end
cache_env = { "XDG_CACHE_HOME" => "#{HOMEBREW_CACHE}/style" }
case output_type
when :print
args << "--debug" if ARGV.debug?
args << "--display-cop-names" if ARGV.include? "--display-cop-names"
args << "--format" << "simple" if files
system(cache_env, "rubocop", "_#{HOMEBREW_RUBOCOP_VERSION}_", *args)
!$CHILD_STATUS.success?
when :json
json, _, status = Open3.capture3(cache_env, "rubocop", "_#{HOMEBREW_RUBOCOP_VERSION}_", "--format", "json", *args)
# exit status of 1 just means violations were found; other numbers mean
# execution errors.
# exitstatus can also be nil if RuboCop process crashes, e.g. due to
# native extension problems.
# JSON needs to be at least 2 characters.
if !(0..1).cover?(status.exitstatus) || json.to_s.length < 2
raise "Error running `rubocop --format json #{args.join " "}`"
end
RubocopResults.new(JSON.parse(json))
else
raise "Invalid output_type for check_style_impl: #{output_type}"
end
end
class RubocopResults
def initialize(json)
@metadata = json["metadata"]
@file_offenses = {}
json["files"].each do |f|
next if f["offenses"].empty?
file = File.realpath(f["path"])
@file_offenses[file] = f["offenses"].map { |x| RubocopOffense.new(x) }
end
end
def file_offenses(path)
@file_offenses[path.to_s]
end
end
class RubocopOffense
attr_reader :severity, :message, :corrected, :location, :cop_name
def initialize(json)
@severity = json["severity"]
@message = json["message"]
@cop_name = json["cop_name"]
@corrected = json["corrected"]
@location = RubocopLineLocation.new(json["location"])
end
def severity_code
@severity[0].upcase
end
def to_s(options = {})
if options[:display_cop_name]
"#{severity_code}: #{location.to_short_s}: #{cop_name}: #{message}"
else
"#{severity_code}: #{location.to_short_s}: #{message}"
end
end
end
class RubocopLineLocation
attr_reader :line, :column, :length
def initialize(json)
@line = json["line"]
@column = json["column"]
@length = json["length"]
end
def to_s
"#{line}: col #{column} (#{length} chars)"
end
def to_short_s
"#{line}: col #{column}"
end
Homebrew.failed = Style.check_style_and_print(target, options)
end
end

View File

@ -3,7 +3,6 @@
require "formula"
require "keg"
require "cmd/link"
module Homebrew
module_function
@ -53,7 +52,7 @@ module Homebrew
keg = Keg.new(rack/version)
# Link new version, if not keg-only
if keg_only?(rack)
if Formulary.keg_only?(rack)
keg.optlink
puts "Opt link created for #{keg}"
else

View File

@ -17,7 +17,8 @@
#: If <formulae> are given, upgrade only the specified brews (unless they
#: are pinned; see `pin`, `unpin`).
require "cmd/install"
require "install"
require "formula_installer"
require "cleanup"
require "development_tools"
@ -27,7 +28,7 @@ module Homebrew
def upgrade
FormulaInstaller.prevent_build_flags unless DevelopmentTools.installed?
Homebrew.perform_preinstall_checks
Install.perform_preinstall_checks
odisabled "'brew upgrade --all'", "'brew upgrade'" if ARGV.include?("--all")

View File

@ -43,7 +43,7 @@ require "utils/curl"
require "extend/ENV"
require "formula_cellar_checks"
require "cmd/search"
require "cmd/style"
require "style"
require "date"
require "missing_formula"
require "digest"
@ -116,7 +116,7 @@ module Homebrew
options[:display_cop_names] = args.display_cop_names?
# Check style in a single batch run up front for performance
style_results = check_style_json(files, options)
style_results = Style.check_style_json(files, options)
new_formula_problem_lines = []
ff.sort.each do |f|

13
Library/Homebrew/fetch.rb Normal file
View File

@ -0,0 +1,13 @@
module Homebrew
module Fetch
module_function
def fetch_bottle?(f)
return true if ARGV.force_bottle? && f.bottle
return false unless f.bottle && f.pour_bottle?
return false if ARGV.build_formula_from_source?(f)
return false unless f.bottle.compatible_cellar?
true
end
end
end

View File

@ -298,6 +298,13 @@ module Formulary
end
end
# Return whether given rack is keg-only
def self.keg_only?(rack)
Formulary.from_rack(rack).keg_only?
rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError
false
end
# Return a Formula instance for the given keg.
# It will auto resolve formula's spec when requested spec is nil
def self.from_keg(keg, spec = nil, alias_path: nil)

93
Library/Homebrew/help.rb Normal file
View File

@ -0,0 +1,93 @@
HOMEBREW_HELP = <<~EOS.freeze
Example usage:
brew search [TEXT|/REGEX/]
brew info [FORMULA...]
brew install FORMULA...
brew update
brew upgrade [FORMULA...]
brew uninstall FORMULA...
brew list [FORMULA...]
Troubleshooting:
brew config
brew doctor
brew install --verbose --debug FORMULA
Contributing:
brew create [URL [--no-fetch]]
brew edit [FORMULA...]
Further help:
brew commands
brew help [COMMAND]
man brew
https://docs.brew.sh
EOS
# NOTE Keep the length of vanilla --help less than 25 lines!
# This is because the default Terminal height is 25 lines. Scrolling sucks
# and concision is important. If more help is needed we should start
# specialising help like the gem command does.
# NOTE Keep lines less than 80 characters! Wrapping is just not cricket.
# NOTE The reason the string is at the top is so 25 lines is easy to measure!
require "commands"
module Homebrew
module Help
module_function
def help(cmd = nil, flags = {})
# Resolve command aliases and find file containing the implementation.
if cmd
cmd = HOMEBREW_INTERNAL_COMMAND_ALIASES.fetch(cmd, cmd)
path = Commands.path(cmd)
path ||= which("brew-#{cmd}")
path ||= which("brew-#{cmd}.rb")
end
# Display command-specific (or generic) help in response to `UsageError`.
if (error_message = flags[:usage_error])
$stderr.puts path ? command_help(path) : HOMEBREW_HELP
$stderr.puts
onoe error_message
exit 1
end
# Handle `brew` (no arguments).
if flags[:empty_argv]
$stderr.puts HOMEBREW_HELP
exit 1
end
# Handle `brew (-h|--help|--usage|-?|help)` (no other arguments).
if cmd.nil?
puts HOMEBREW_HELP
exit 0
end
# Resume execution in `brew.rb` for unknown commands.
return if path.nil?
# Display help for internal command (or generic help if undocumented).
puts command_help(path)
exit 0
end
def command_help(path)
help_lines = command_help_lines(path)
if help_lines.empty?
opoo "No help text in: #{path}" if ARGV.homebrew_developer?
HOMEBREW_HELP
else
help_lines.map do |line|
line.sub(/^ \* /, "#{Tty.bold}brew#{Tty.reset} ")
.gsub(/`(.*?)`/, "#{Tty.bold}\\1#{Tty.reset}")
.gsub(%r{<([^\s]+?://[^\s]+?)>}) { |url| Formatter.url(url) }
.gsub(/<(.*?)>/, "#{Tty.underline}\\1#{Tty.reset}")
.gsub("@hide_from_man_page", "")
end.join.strip
end
end
end
end

View File

@ -0,0 +1,54 @@
require "diagnostic"
require "fileutils"
require "hardware"
require "development_tools"
module Homebrew
module Install
module_function
def check_ppc
case Hardware::CPU.type
when :ppc
abort <<~EOS
Sorry, Homebrew does not support your computer's CPU architecture.
For PPC support, see: https://github.com/mistydemeo/tigerbrew
EOS
end
end
def check_writable_install_location
if HOMEBREW_CELLAR.exist? && !HOMEBREW_CELLAR.writable_real?
raise "Cannot write to #{HOMEBREW_CELLAR}"
end
prefix_writable = HOMEBREW_PREFIX.writable_real? || HOMEBREW_PREFIX.to_s == "/usr/local"
raise "Cannot write to #{HOMEBREW_PREFIX}" unless prefix_writable
end
def check_development_tools
checks = Diagnostic::Checks.new
checks.fatal_development_tools_checks.each do |check|
out = checks.send(check)
next if out.nil?
ofail out
end
exit 1 if Homebrew.failed?
end
def check_cellar
FileUtils.mkdir_p HOMEBREW_CELLAR unless File.exist? HOMEBREW_CELLAR
rescue
raise <<~EOS
Could not create #{HOMEBREW_CELLAR}
Check you have permission to write to #{HOMEBREW_CELLAR.parent}
EOS
end
def perform_preinstall_checks
check_ppc
check_writable_install_location
check_development_tools if DevelopmentTools.installed?
check_cellar
end
end
end

152
Library/Homebrew/style.rb Normal file
View File

@ -0,0 +1,152 @@
module Homebrew
module Style
module_function
# Checks style for a list of files, printing simple RuboCop output.
# Returns true if violations were found, false otherwise.
def check_style_and_print(files, options = {})
check_style_impl(files, :print, options)
end
# Checks style for a list of files, returning results as a RubocopResults
# object parsed from its JSON output.
def check_style_json(files, options = {})
check_style_impl(files, :json, options)
end
def check_style_impl(files, output_type, options = {})
fix = options[:fix]
Homebrew.install_gem_setup_path! "rubocop", HOMEBREW_RUBOCOP_VERSION
require "rubocop"
require "rubocops"
args = %w[
--force-exclusion
]
if fix
args << "--auto-correct"
else
args << "--parallel"
end
if ARGV.include?("--rspec")
Homebrew.install_gem! "rubocop-rspec"
args += %w[--require rubocop-rspec]
end
if options[:except_cops]
options[:except_cops].map! { |cop| RuboCop::Cop::Cop.registry.qualified_cop_name(cop.to_s, "") }
cops_to_exclude = options[:except_cops].select do |cop|
RuboCop::Cop::Cop.registry.names.include?(cop) ||
RuboCop::Cop::Cop.registry.departments.include?(cop.to_sym)
end
args << "--except" << cops_to_exclude.join(",") unless cops_to_exclude.empty?
elsif options[:only_cops]
options[:only_cops].map! { |cop| RuboCop::Cop::Cop.registry.qualified_cop_name(cop.to_s, "") }
cops_to_include = options[:only_cops].select do |cop|
RuboCop::Cop::Cop.registry.names.include?(cop) ||
RuboCop::Cop::Cop.registry.departments.include?(cop.to_sym)
end
if cops_to_include.empty?
odie "RuboCops #{options[:only_cops].join(",")} were not found"
end
args << "--only" << cops_to_include.join(",")
end
if files.nil?
config_file = ARGV.include?("--rspec") ? ".rubocop-rspec.yml" : ".rubocop.yml"
args << "--config" << HOMEBREW_LIBRARY_PATH/config_file
args << HOMEBREW_LIBRARY_PATH
else
args << "--config" << HOMEBREW_LIBRARY/".rubocop_audit.yml"
args += files
end
cache_env = { "XDG_CACHE_HOME" => "#{HOMEBREW_CACHE}/style" }
case output_type
when :print
args << "--debug" if ARGV.debug?
args << "--display-cop-names" if ARGV.include? "--display-cop-names"
args << "--format" << "simple" if files
system(cache_env, "rubocop", "_#{HOMEBREW_RUBOCOP_VERSION}_", *args)
!$CHILD_STATUS.success?
when :json
json, _, status = Open3.capture3(cache_env, "rubocop", "_#{HOMEBREW_RUBOCOP_VERSION}_", "--format", "json", *args)
# exit status of 1 just means violations were found; other numbers mean
# execution errors.
# exitstatus can also be nil if RuboCop process crashes, e.g. due to
# native extension problems.
# JSON needs to be at least 2 characters.
if !(0..1).cover?(status.exitstatus) || json.to_s.length < 2
raise "Error running `rubocop --format json #{args.join " "}`"
end
RubocopResults.new(JSON.parse(json))
else
raise "Invalid output_type for check_style_impl: #{output_type}"
end
end
class RubocopResults
def initialize(json)
@metadata = json["metadata"]
@file_offenses = {}
json["files"].each do |f|
next if f["offenses"].empty?
file = File.realpath(f["path"])
@file_offenses[file] = f["offenses"].map { |x| RubocopOffense.new(x) }
end
end
def file_offenses(path)
@file_offenses[path.to_s]
end
end
class RubocopOffense
attr_reader :severity, :message, :corrected, :location, :cop_name
def initialize(json)
@severity = json["severity"]
@message = json["message"]
@cop_name = json["cop_name"]
@corrected = json["corrected"]
@location = RubocopLineLocation.new(json["location"])
end
def severity_code
@severity[0].upcase
end
def to_s(options = {})
if options[:display_cop_name]
"#{severity_code}: #{location.to_short_s}: #{cop_name}: #{message}"
else
"#{severity_code}: #{location.to_short_s}: #{message}"
end
end
end
class RubocopLineLocation
attr_reader :line, :column, :length
def initialize(json)
@line = json["line"]
@column = json["column"]
@length = json["length"]
end
def to_s
"#{line}: col #{column} (#{length} chars)"
end
def to_short_s
"#{line}: col #{column}"
end
end
end
end

View File

@ -25,7 +25,7 @@ describe "brew style" do
end
EOS
rubocop_result = Homebrew.check_style_json([formula])
rubocop_result = Homebrew::Style.check_style_json([formula])
expect(rubocop_result.file_offenses(formula.realpath.to_s).map(&:message))
.to include("Extra empty line detected at class body beginning.")

View File

@ -597,7 +597,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
* `--cache`:
Display Homebrew's download cache. See also `HOMEBREW_CACHE`.
* `--cache` `formula`:
* `--cache` [`--build-from-source`|`-s`] [`--force-bottle`] `formula`:
Display the file or directory used to cache `formula`.
* `--cellar`:

View File

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "BREW\-CASK" "1" "May 2018" "Homebrew" "brew-cask"
.TH "BREW\-CASK" "1" "June 2018" "Homebrew" "brew-cask"
.
.SH "NAME"
\fBbrew\-cask\fR \- a friendly binary installer for macOS

View File

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "BREW" "1" "May 2018" "Homebrew" "brew"
.TH "BREW" "1" "June 2018" "Homebrew" "brew"
.
.SH "NAME"
\fBbrew\fR \- The missing package manager for macOS
@ -610,7 +610,7 @@ By default, \fBuses\fR shows usage of \fIformulae\fR by stable builds\. To find
Display Homebrew\'s download cache\. See also \fBHOMEBREW_CACHE\fR\.
.
.TP
\fB\-\-cache\fR \fIformula\fR
\fB\-\-cache\fR [\fB\-\-build\-from\-source\fR|\fB\-s\fR] [\fB\-\-force\-bottle\fR] \fIformula\fR
Display the file or directory used to cache \fIformula\fR\.
.
.TP