Merge pull request #16975 from Homebrew/ported-cmds

Begin porting non-dev commands to use AbstractCommand
This commit is contained in:
Mike McQuaid 2024-03-31 19:28:30 +01:00 committed by GitHub
commit 21dd3c263f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
85 changed files with 2086 additions and 2109 deletions

View File

@ -1,12 +1,15 @@
# typed: strong # typed: strong
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser"
module Homebrew module Homebrew
# Subclass this to implement a `brew` command. This is preferred to declaring a named function in the `Homebrew` # Subclass this to implement a `brew` command. This is preferred to declaring a named function in the `Homebrew`
# module, because: # module, because:
# - Each Command lives in an isolated namespace. # - Each Command lives in an isolated namespace.
# - Each Command implements a defined interface. # - Each Command implements a defined interface.
# - `args` is available as an ivar, and thus does not need to be passed as an argument to helper methods. # - `args` is available as an ivar, and thus does not need to be passed as an argument to helper methods.
# - Subclasses no longer need to reference `CLI::Parser` or parse args explicitly.
# #
# To subclass, implement a `run` method and provide a `cmd_args` block to document the command and its allowed args. # To subclass, implement a `run` method and provide a `cmd_args` block to document the command and its allowed args.
# To generate method signatures for command args, run `brew typecheck --update`. # To generate method signatures for command args, run `brew typecheck --update`.

View File

@ -217,7 +217,7 @@ class Build
end end
begin begin
args = Homebrew.install_args.parse args = Homebrew::Cmd::InstallCmd.new.args
Context.current = args.context Context.current = args.context
error_pipe = UNIXSocket.open(ENV.fetch("HOMEBREW_ERROR_PIPE"), &:recv_io) error_pipe = UNIXSocket.open(ENV.fetch("HOMEBREW_ERROR_PIPE"), &:recv_io)

View File

@ -1,14 +1,12 @@
# typed: strict # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "abstract_command"
module Homebrew module Homebrew
module_function module Cmd
class Analytics < AbstractCommand
sig { returns(CLI::Parser) } cmd_args do
def analytics_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Control Homebrew's anonymous aggregate user behaviour analytics. Control Homebrew's anonymous aggregate user behaviour analytics.
Read more at <https://docs.brew.sh/Analytics>. Read more at <https://docs.brew.sh/Analytics>.
@ -22,12 +20,9 @@ module Homebrew
named_args %w[state on off regenerate-uuid], max: 1 named_args %w[state on off regenerate-uuid], max: 1
end end
end
sig { void }
def analytics
args = analytics_args.parse
sig { override.void }
def run
case args.named.first case args.named.first
when nil, "state" when nil, "state"
if Utils::Analytics.disabled? if Utils::Analytics.disabled?
@ -48,4 +43,6 @@ module Homebrew
raise UsageError, "unknown subcommand: #{args.named.first}" raise UsageError, "unknown subcommand: #{args.named.first}"
end end
end end
end
end
end end

View File

@ -1,13 +1,13 @@
# typed: strict # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "cleanup" require "cleanup"
require "cli/parser"
module Homebrew module Homebrew
sig { returns(CLI::Parser) } module Cmd
def self.autoremove_args class Autoremove < AbstractCommand
Homebrew::CLI::Parser.new do cmd_args do
description <<~EOS description <<~EOS
Uninstall formulae that were only installed as a dependency of another formula and are now no longer needed. Uninstall formulae that were only installed as a dependency of another formula and are now no longer needed.
EOS EOS
@ -16,12 +16,11 @@ module Homebrew
named_args :none named_args :none
end end
end
sig { void }
def self.autoremove
args = autoremove_args.parse
sig { override.void }
def run
Cleanup.autoremove(dry_run: args.dry_run?) Cleanup.autoremove(dry_run: args.dry_run?)
end end
end
end
end end

View File

@ -1,15 +1,13 @@
# typed: strict # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "cleanup" require "cleanup"
require "cli/parser"
module Homebrew module Homebrew
module_function module Cmd
class CleanupCmd < AbstractCommand
sig { returns(CLI::Parser) } cmd_args do
def cleanup_args
Homebrew::CLI::Parser.new do
days = Homebrew::EnvConfig::ENVS[:HOMEBREW_CLEANUP_MAX_AGE_DAYS][:default] days = Homebrew::EnvConfig::ENVS[:HOMEBREW_CLEANUP_MAX_AGE_DAYS][:default]
description <<~EOS description <<~EOS
Remove stale lock files and outdated downloads for all formulae and casks, Remove stale lock files and outdated downloads for all formulae and casks,
@ -31,12 +29,9 @@ module Homebrew
named_args [:formula, :cask] named_args [:formula, :cask]
end end
end
sig { void }
def cleanup
args = cleanup_args.parse
sig { override.void }
def run
days = args.prune.presence&.then do |prune| days = args.prune.presence&.then do |prune|
case prune case prune
when /\A\d+\Z/ when /\A\d+\Z/
@ -72,4 +67,6 @@ module Homebrew
#{cleanup.unremovable_kegs.join "\n "} #{cleanup.unremovable_kegs.join "\n "}
EOS EOS
end end
end
end
end end

View File

@ -1,14 +1,12 @@
# typed: strict # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "abstract_command"
module Homebrew module Homebrew
module_function module Cmd
class CommandsCmd < AbstractCommand
sig { returns(CLI::Parser) } cmd_args do
def commands_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Show lists of built-in and external commands. Show lists of built-in and external commands.
EOS EOS
@ -20,12 +18,9 @@ module Homebrew
named_args :none named_args :none
end end
end
sig { void }
def commands
args = commands_args.parse
sig { override.void }
def run
if args.quiet? if args.quiet?
puts Formatter.columns(Commands.commands(aliases: args.include_aliases?)) puts Formatter.columns(Commands.commands(aliases: args.include_aliases?))
return return
@ -46,4 +41,6 @@ module Homebrew
prepend_separator ||= true prepend_separator ||= true
end end
end end
end
end
end end

View File

@ -1,15 +1,13 @@
# typed: strict # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "abstract_command"
require "completions" require "completions"
module Homebrew module Homebrew
module_function module Cmd
class CompletionsCmd < AbstractCommand
sig { returns(CLI::Parser) } cmd_args do
def completions_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Control whether Homebrew automatically links external tap shell completion files. Control whether Homebrew automatically links external tap shell completion files.
Read more at <https://docs.brew.sh/Shell-Completion>. Read more at <https://docs.brew.sh/Shell-Completion>.
@ -23,12 +21,9 @@ module Homebrew
named_args %w[state link unlink], max: 1 named_args %w[state link unlink], max: 1
end end
end
sig { void }
def completions
args = completions_args.parse
sig { override.void }
def run
case args.named.first case args.named.first
when nil, "state" when nil, "state"
if Completions.link_completions? if Completions.link_completions?
@ -46,4 +41,6 @@ module Homebrew
raise UsageError, "unknown subcommand: #{args.named.first}" raise UsageError, "unknown subcommand: #{args.named.first}"
end end
end end
end
end
end end

View File

@ -1,15 +1,13 @@
# typed: strict # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "system_config" require "system_config"
require "cli/parser"
module Homebrew module Homebrew
module_function module Cmd
class Config < AbstractCommand
sig { returns(CLI::Parser) } cmd_args do
def config_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Show Homebrew and system configuration info useful for debugging. If you file Show Homebrew and system configuration info useful for debugging. If you file
a bug report, you will be required to provide this information. a bug report, you will be required to provide this information.
@ -17,12 +15,11 @@ module Homebrew
named_args :none named_args :none
end end
end
sig { void }
def config
config_args.parse
sig { override.void }
def run
SystemConfig.dump_verbose_config SystemConfig.dump_verbose_config
end end
end
end
end end

View File

@ -1,17 +1,16 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "formula" require "formula"
require "cli/parser"
require "cask/caskroom" require "cask/caskroom"
require "dependencies_helpers" require "dependencies_helpers"
module Homebrew module Homebrew
extend DependenciesHelpers module Cmd
class Deps < AbstractCommand
sig { returns(CLI::Parser) } include DependenciesHelpers
def self.deps_args cmd_args do
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Show dependencies for <formula>. When given multiple formula arguments, Show dependencies for <formula>. When given multiple formula arguments,
show the intersection of dependencies for each formula. By default, `deps` show the intersection of dependencies for each formula. By default, `deps`
@ -80,11 +79,9 @@ module Homebrew
named_args [:formula, :cask] named_args [:formula, :cask]
end end
end
def self.deps
args = deps_args.parse
sig { override.void }
def run
all = args.eval_all? all = args.eval_all?
Formulary.enable_factory_cache! Formulary.enable_factory_cache!
@ -119,7 +116,7 @@ module Homebrew
end end
if args.graph? if args.graph?
dot_code = dot_code(dependents, recursive:, args:) dot_code = dot_code(dependents, recursive:)
if args.dot? if args.dot?
puts dot_code puts dot_code
else else
@ -128,15 +125,15 @@ module Homebrew
return return
end end
puts_deps_tree(dependents, recursive:, args:) puts_deps_tree(dependents, recursive:)
return return
elsif all elsif all
puts_deps(sorted_dependents( puts_deps(sorted_dependents(
Formula.all(eval_all: args.eval_all?) + Cask::Cask.all(eval_all: args.eval_all?), Formula.all(eval_all: args.eval_all?) + Cask::Cask.all(eval_all: args.eval_all?),
), recursive:, args:) ), recursive:)
return return
elsif !args.no_named? && args.for_each? elsif !args.no_named? && args.for_each?
puts_deps(sorted_dependents(args.named.to_formulae_and_casks), recursive:, args:) puts_deps(sorted_dependents(args.named.to_formulae_and_casks), recursive:)
return return
end end
@ -151,31 +148,33 @@ module Homebrew
else else
sorted_dependents(Formula.installed + Cask::Caskroom.casks) sorted_dependents(Formula.installed + Cask::Caskroom.casks)
end end
puts_deps(sorted_dependents_formulae_and_casks, recursive:, args:) puts_deps(sorted_dependents_formulae_and_casks, recursive:)
return return
end end
dependents = dependents(args.named.to_formulae_and_casks) dependents = dependents(args.named.to_formulae_and_casks)
check_head_spec(dependents) if args.HEAD? check_head_spec(dependents) if args.HEAD?
all_deps = deps_for_dependents(dependents, recursive:, args:, &(args.union? ? :| : :&)) all_deps = deps_for_dependents(dependents, recursive:, &(args.union? ? :| : :&))
condense_requirements(all_deps, args:) condense_requirements(all_deps)
all_deps.map! { |d| dep_display_name(d, args:) } all_deps.map! { |d| dep_display_name(d) }
all_deps.uniq! all_deps.uniq!
all_deps.sort! unless args.topological? all_deps.sort! unless args.topological?
puts all_deps puts all_deps
end end
def self.sorted_dependents(formulae_or_casks) private
def sorted_dependents(formulae_or_casks)
dependents(formulae_or_casks).sort_by(&:name) dependents(formulae_or_casks).sort_by(&:name)
end end
def self.condense_requirements(deps, args:) def condense_requirements(deps)
deps.select! { |dep| dep.is_a?(Dependency) } unless args.include_requirements? deps.select! { |dep| dep.is_a?(Dependency) } unless args.include_requirements?
deps.select! { |dep| dep.is_a?(Requirement) || dep.installed? } if args.installed? deps.select! { |dep| dep.is_a?(Requirement) || dep.installed? } if args.installed?
end end
def self.dep_display_name(dep, args:) def dep_display_name(dep)
str = if dep.is_a? Requirement str = if dep.is_a? Requirement
if args.include_requirements? if args.include_requirements?
":#{dep.display_s}" ":#{dep.display_s}"
@ -201,7 +200,7 @@ module Homebrew
str str
end end
def self.deps_for_dependent(dependency, args:, recursive: false) def deps_for_dependent(dependency, recursive: false)
includes, ignores = args_includes_ignores(args) includes, ignores = args_includes_ignores(args)
deps = dependency.runtime_dependencies if @use_runtime_dependencies deps = dependency.runtime_dependencies if @use_runtime_dependencies
@ -217,31 +216,31 @@ module Homebrew
deps + reqs.to_a deps + reqs.to_a
end end
def self.deps_for_dependents(dependents, args:, recursive: false, &block) def deps_for_dependents(dependents, recursive: false, &block)
dependents.map { |d| deps_for_dependent(d, recursive:, args:) }.reduce(&block) dependents.map { |d| deps_for_dependent(d, recursive:) }.reduce(&block)
end end
def self.check_head_spec(dependents) def check_head_spec(dependents)
headless = dependents.select { |d| d.is_a?(Formula) && d.active_spec_sym != :head } headless = dependents.select { |d| d.is_a?(Formula) && d.active_spec_sym != :head }
.to_sentence two_words_connector: " or ", last_word_connector: " or " .to_sentence two_words_connector: " or ", last_word_connector: " or "
opoo "No head spec for #{headless}, using stable spec instead" unless headless.empty? opoo "No head spec for #{headless}, using stable spec instead" unless headless.empty?
end end
def self.puts_deps(dependents, args:, recursive: false) def puts_deps(dependents, recursive: false)
check_head_spec(dependents) if args.HEAD? check_head_spec(dependents) if args.HEAD?
dependents.each do |dependent| dependents.each do |dependent|
deps = deps_for_dependent(dependent, recursive:, args:) deps = deps_for_dependent(dependent, recursive:)
condense_requirements(deps, args:) condense_requirements(deps)
deps.sort_by!(&:name) deps.sort_by!(&:name)
deps.map! { |d| dep_display_name(d, args:) } deps.map! { |d| dep_display_name(d) }
puts "#{dependent.full_name}: #{deps.join(" ")}" puts "#{dependent.full_name}: #{deps.join(" ")}"
end end
end end
def self.dot_code(dependents, recursive:, args:) def dot_code(dependents, recursive:)
dep_graph = {} dep_graph = {}
dependents.each do |d| dependents.each do |d|
graph_deps(d, dep_graph:, recursive:, args:) graph_deps(d, dep_graph:, recursive:)
end end
dot_code = dep_graph.map do |d, deps| dot_code = dep_graph.map do |d, deps|
@ -261,10 +260,10 @@ module Homebrew
"digraph {\n#{dot_code}\n}" "digraph {\n#{dot_code}\n}"
end end
def self.graph_deps(formula, dep_graph:, recursive:, args:) def graph_deps(formula, dep_graph:, recursive:)
return if dep_graph.key?(formula) return if dep_graph.key?(formula)
dependables = dependables(formula, args:) dependables = dependables(formula)
dep_graph[formula] = dependables dep_graph[formula] = dependables
return unless recursive return unless recursive
@ -273,21 +272,20 @@ module Homebrew
graph_deps(Formulary.factory(dep.name), graph_deps(Formulary.factory(dep.name),
dep_graph:, dep_graph:,
recursive: true, recursive: true)
args:)
end end
end end
def self.puts_deps_tree(dependents, args:, recursive: false) def puts_deps_tree(dependents, recursive: false)
check_head_spec(dependents) if args.HEAD? check_head_spec(dependents) if args.HEAD?
dependents.each do |d| dependents.each do |d|
puts d.full_name puts d.full_name
recursive_deps_tree(d, dep_stack: [], prefix: "", recursive:, args:) recursive_deps_tree(d, dep_stack: [], prefix: "", recursive:)
puts puts
end end
end end
def self.dependables(formula, args:) def dependables(formula)
includes, ignores = args_includes_ignores(args) includes, ignores = args_includes_ignores(args)
deps = @use_runtime_dependencies ? formula.runtime_dependencies : formula.deps deps = @use_runtime_dependencies ? formula.runtime_dependencies : formula.deps
deps = select_includes(deps, ignores, includes) deps = select_includes(deps, ignores, includes)
@ -296,8 +294,8 @@ module Homebrew
reqs + deps reqs + deps
end end
def self.recursive_deps_tree(formula, dep_stack:, prefix:, recursive:, args:) def recursive_deps_tree(formula, dep_stack:, prefix:, recursive:)
dependables = dependables(formula, args:) dependables = dependables(formula)
max = dependables.length - 1 max = dependables.length - 1
dep_stack.push formula.name dep_stack.push formula.name
dependables.each_with_index do |dep, i| dependables.each_with_index do |dep, i|
@ -307,7 +305,7 @@ module Homebrew
"├──" "├──"
end end
display_s = "#{tree_lines} #{dep_display_name(dep, args:)}" display_s = "#{tree_lines} #{dep_display_name(dep)}"
# Detect circular dependencies and consider them a failure if present. # Detect circular dependencies and consider them a failure if present.
is_circular = dep_stack.include?(dep.name) is_circular = dep_stack.include?(dep.name)
@ -331,10 +329,11 @@ module Homebrew
recursive_deps_tree(Formulary.factory(dep.name), recursive_deps_tree(Formulary.factory(dep.name),
dep_stack:, dep_stack:,
prefix: prefix + prefix_addition, prefix: prefix + prefix_addition,
recursive: true, recursive: true)
args:)
end end
dep_stack.pop dep_stack.pop
end end
end
end
end end

View File

@ -1,17 +1,15 @@
# typed: true # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "descriptions" require "descriptions"
require "search" require "search"
require "description_cache_store" require "description_cache_store"
require "cli/parser"
module Homebrew module Homebrew
module_function module Cmd
class Desc < AbstractCommand
sig { returns(CLI::Parser) } cmd_args do
def desc_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Display <formula>'s name and one-line description. Display <formula>'s name and one-line description.
The cache is created on the first search, making that search slower than subsequent ones. The cache is created on the first search, making that search slower than subsequent ones.
@ -37,11 +35,9 @@ module Homebrew
named_args [:formula, :cask, :text_or_regex], min: 1 named_args [:formula, :cask, :text_or_regex], min: 1
end end
end
def desc
args = desc_args.parse
sig { override.void }
def run
if !args.eval_all? && !Homebrew::EnvConfig.eval_all? if !args.eval_all? && !Homebrew::EnvConfig.eval_all?
raise UsageError, "`brew desc` needs `--eval-all` passed or `HOMEBREW_EVAL_ALL` set!" raise UsageError, "`brew desc` needs `--eval-all` passed or `HOMEBREW_EVAL_ALL` set!"
end end
@ -57,11 +53,14 @@ module Homebrew
if search_type.blank? if search_type.blank?
desc = {} desc = {}
args.named.to_formulae_and_casks.each do |formula_or_cask| args.named.to_formulae_and_casks.each do |formula_or_cask|
if formula_or_cask.is_a? Formula case formula_or_cask
when Formula
desc[formula_or_cask.full_name] = formula_or_cask.desc desc[formula_or_cask.full_name] = formula_or_cask.desc
else when Cask::Cask
description = formula_or_cask.desc.presence || Formatter.warning("[no description]") description = formula_or_cask.desc.presence || Formatter.warning("[no description]")
desc[formula_or_cask.full_name] = "(#{formula_or_cask.name.join(", ")}) #{description}" desc[formula_or_cask.full_name] = "(#{formula_or_cask.name.join(", ")}) #{description}"
else
raise TypeError, "Unsupported formula_or_cask type: #{formula_or_cask.class}"
end end
end end
Descriptions.new(desc).print Descriptions.new(desc).print
@ -71,4 +70,6 @@ module Homebrew
Search.search_descriptions(string_or_regex, args, search_type:) Search.search_descriptions(string_or_regex, args, search_type:)
end end
end end
end
end
end end

View File

@ -1,14 +1,12 @@
# typed: true # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "abstract_command"
module Homebrew module Homebrew
module_function module Cmd
class Developer < AbstractCommand
sig { returns(CLI::Parser) } cmd_args do
def developer_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Control Homebrew's developer mode. When developer mode is enabled, Control Homebrew's developer mode. When developer mode is enabled,
`brew update` will update Homebrew to the latest commit on the `master` `brew update` will update Homebrew to the latest commit on the `master`
@ -23,11 +21,9 @@ module Homebrew
named_args %w[state on off], max: 1 named_args %w[state on off], max: 1
end end
end
def developer
args = developer_args.parse
sig { override.void }
def run
env_vars = [] env_vars = []
env_vars << "HOMEBREW_DEVELOPER" if Homebrew::EnvConfig.developer? env_vars << "HOMEBREW_DEVELOPER" if Homebrew::EnvConfig.developer?
env_vars << "HOMEBREW_UPDATE_TO_TAG" if Homebrew::EnvConfig.update_to_tag? env_vars << "HOMEBREW_UPDATE_TO_TAG" if Homebrew::EnvConfig.update_to_tag?
@ -38,7 +34,8 @@ module Homebrew
case args.named.first case args.named.first
when nil, "state" when nil, "state"
if env_vars.any? if env_vars.any?
puts "Developer mode is enabled because #{env_vars.to_sentence} #{(env_vars.count == 1) ? "is" : "are"} set." verb = (env_vars.count == 1) ? "is" : "are"
puts "Developer mode is enabled because #{env_vars.to_sentence} #{verb} set."
elsif Homebrew::Settings.read("devcmdrun") == "true" elsif Homebrew::Settings.read("devcmdrun") == "true"
puts "Developer mode is enabled." puts "Developer mode is enabled."
else else
@ -53,4 +50,6 @@ module Homebrew
raise UsageError, "unknown subcommand: #{args.named.first}" raise UsageError, "unknown subcommand: #{args.named.first}"
end end
end end
end
end
end end

View File

@ -1,22 +1,21 @@
# typed: strict # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "abstract_command"
module Homebrew module Homebrew
module_function module Cmd
class Docs < AbstractCommand
sig { returns(CLI::Parser) } cmd_args do
def docs_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Open Homebrew's online documentation at <#{HOMEBREW_DOCS_WWW}> in a browser. Open Homebrew's online documentation at <#{HOMEBREW_DOCS_WWW}> in a browser.
EOS EOS
end end
end
sig { void } sig { override.void }
def docs def run
exec_browser HOMEBREW_DOCS_WWW exec_browser HOMEBREW_DOCS_WWW
end end
end
end
end end

View File

@ -1,14 +1,14 @@
# typed: true # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "diagnostic" require "diagnostic"
require "cli/parser"
require "cask/caskroom" require "cask/caskroom"
module Homebrew module Homebrew
sig { returns(CLI::Parser) } module Cmd
def self.doctor_args class Doctor < AbstractCommand
Homebrew::CLI::Parser.new do cmd_args do
description <<~EOS description <<~EOS
Check your system for potential problems. Will exit with a non-zero status Check your system for potential problems. Will exit with a non-zero status
if any potential problems are found. if any potential problems are found.
@ -25,12 +25,10 @@ module Homebrew
named_args :diagnostic_check named_args :diagnostic_check
end end
end
def self.doctor sig { override.void }
args = doctor_args.parse def run
Homebrew.inject_dump_stats!(Diagnostic::Checks, /^check_*/) if args.audit_debug?
inject_dump_stats!(Diagnostic::Checks, /^check_*/) if args.audit_debug?
checks = Diagnostic::Checks.new(verbose: args.verbose?) checks = Diagnostic::Checks.new(verbose: args.verbose?)
@ -77,4 +75,6 @@ module Homebrew
puts "Your system is ready to brew." if !Homebrew.failed? && !args.quiet? puts "Your system is ready to brew." if !Homebrew.failed? && !args.quiet?
end end
end
end
end end

View File

@ -1,19 +1,18 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "formula" require "formula"
require "fetch" require "fetch"
require "cli/parser"
require "cask/download" require "cask/download"
module Homebrew module Homebrew
extend Fetch module Cmd
class FetchCmd < AbstractCommand
include Fetch
FETCH_MAX_TRIES = 5 FETCH_MAX_TRIES = 5
sig { returns(CLI::Parser) } cmd_args do
def self.fetch_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Download a bottle (if available) or source packages for <formula>e Download a bottle (if available) or source packages for <formula>e
and binaries for <cask>s. For files, also print SHA-256 checksums. and binaries for <cask>s. For files, also print SHA-256 checksums.
@ -67,11 +66,9 @@ module Homebrew
named_args [:formula, :cask], min: 1 named_args [:formula, :cask], min: 1
end end
end
def self.fetch
args = fetch_args.parse
sig { override.void }
def run
Formulary.enable_factory_cache! Formulary.enable_factory_cache!
bucket = if args.deps? bucket = if args.deps?
@ -131,10 +128,10 @@ module Homebrew
begin begin
bottle.fetch_tab bottle.fetch_tab
rescue DownloadError rescue DownloadError
retry if retry_fetch?(bottle, args:) retry if retry_fetch?(bottle)
raise raise
end end
fetch_formula(bottle, args:) fetch_formula(bottle)
rescue Interrupt rescue Interrupt
raise raise
rescue => e rescue => e
@ -150,14 +147,14 @@ module Homebrew
next if fetched_bottle next if fetched_bottle
fetch_formula(formula, args:) fetch_formula(formula)
formula.resources.each do |r| formula.resources.each do |r|
fetch_resource(r, args:) fetch_resource(r)
r.patches.each { |p| fetch_patch(p, args:) if p.external? } r.patches.each { |p| fetch_patch(p) if p.external? }
end end
formula.patchlist.each { |p| fetch_patch(p, args:) if p.external? } formula.patchlist.each { |p| fetch_patch(p) if p.external? }
end end
end end
else else
@ -179,43 +176,45 @@ module Homebrew
quarantine = true if quarantine.nil? quarantine = true if quarantine.nil?
download = Cask::Download.new(cask, quarantine:) download = Cask::Download.new(cask, quarantine:)
fetch_cask(download, args:) fetch_cask(download)
end end
end end
end end
end end
end end
def self.fetch_resource(resource, args:) private
def fetch_resource(resource)
puts "Resource: #{resource.name}" puts "Resource: #{resource.name}"
fetch_fetchable resource, args: fetch_fetchable resource
rescue ChecksumMismatchError => e rescue ChecksumMismatchError => e
retry if retry_fetch?(resource, args:) retry if retry_fetch?(resource)
opoo "Resource #{resource.name} reports different sha256: #{e.expected}" opoo "Resource #{resource.name} reports different sha256: #{e.expected}"
end end
def self.fetch_formula(formula, args:) def fetch_formula(formula)
fetch_fetchable(formula, args:) fetch_fetchable(formula)
rescue ChecksumMismatchError => e rescue ChecksumMismatchError => e
retry if retry_fetch?(formula, args:) retry if retry_fetch?(formula)
opoo "Formula reports different sha256: #{e.expected}" opoo "Formula reports different sha256: #{e.expected}"
end end
def self.fetch_cask(cask_download, args:) def fetch_cask(cask_download)
fetch_fetchable(cask_download, args:) fetch_fetchable(cask_download)
rescue ChecksumMismatchError => e rescue ChecksumMismatchError => e
retry if retry_fetch?(cask_download, args:) retry if retry_fetch?(cask_download)
opoo "Cask reports different sha256: #{e.expected}" opoo "Cask reports different sha256: #{e.expected}"
end end
def self.fetch_patch(patch, args:) def fetch_patch(patch)
fetch_fetchable(patch, args:) fetch_fetchable(patch)
rescue ChecksumMismatchError => e rescue ChecksumMismatchError => e
opoo "Patch reports different sha256: #{e.expected}" opoo "Patch reports different sha256: #{e.expected}"
Homebrew.failed = true Homebrew.failed = true
end end
def self.retry_fetch?(formula, args:) def retry_fetch?(formula)
@fetch_tries ||= Hash.new { |h, k| h[k] = 1 } @fetch_tries ||= Hash.new { |h, k| h[k] = 1 }
if args.retry? && (@fetch_tries[formula] < FETCH_MAX_TRIES) if args.retry? && (@fetch_tries[formula] < FETCH_MAX_TRIES)
wait = 2 ** @fetch_tries[formula] wait = 2 ** @fetch_tries[formula]
@ -234,7 +233,7 @@ module Homebrew
end end
end end
def self.fetch_fetchable(formula, args:) def fetch_fetchable(formula)
formula.clear_cache if args.force? formula.clear_cache if args.force?
already_fetched = formula.cached_download.exist? already_fetched = formula.cached_download.exist?
@ -242,7 +241,7 @@ module Homebrew
begin begin
download = formula.fetch(verify_download_integrity: false) download = formula.fetch(verify_download_integrity: false)
rescue DownloadError rescue DownloadError
retry if retry_fetch?(formula, args:) retry if retry_fetch?(formula)
raise raise
end end
@ -253,4 +252,6 @@ module Homebrew
formula.verify_download_integrity(download) formula.verify_download_integrity(download)
end end
end
end
end end

View File

@ -1,21 +1,18 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "formula" require "formula"
require "install" require "install"
require "system_config" require "system_config"
require "stringio" require "stringio"
require "socket" require "socket"
require "cli/parser"
module Homebrew module Homebrew
extend Install module Cmd
class GistLogs < AbstractCommand
module_function include Install
cmd_args do
sig { returns(CLI::Parser) }
def gist_logs_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Upload logs for a failed build of <formula> to a new Gist. Presents an Upload logs for a failed build of <formula> to a new Gist. Presents an
error message if no logs are found. error message if no logs are found.
@ -31,9 +28,17 @@ module Homebrew
named_args :formula, number: 1 named_args :formula, number: 1
end end
sig { override.void }
def run
Install.perform_preinstall_checks(all_fatal: true)
Install.perform_build_from_source_checks(all_fatal: true)
gistify_logs(args.named.to_resolved_formulae.first)
end end
def gistify_logs(formula, args:) private
def gistify_logs(formula)
files = load_logs(formula.logs) files = load_logs(formula.logs)
build_time = formula.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")
@ -73,7 +78,10 @@ module Homebrew
EOS EOS
end end
url = GitHub.create_issue(formula.tap, "#{formula.name} failed to build on #{OS_VERSION}", url) if args.new_issue? if args.new_issue?
url = GitHub.create_issue(formula.tap, "#{formula.name} failed to build on #{OS_VERSION}",
url)
end
puts url if url puts url if url
end end
@ -119,12 +127,6 @@ module Homebrew
logs logs
end end
end
def gist_logs
args = gist_logs_args.parse
Install.perform_preinstall_checks(all_fatal: true)
Install.perform_build_from_source_checks(all_fatal: true)
gistify_logs(args.named.to_resolved_formulae.first, args:)
end end
end end

View File

@ -1,11 +1,16 @@
# typed: strict # typed: strong
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "help" require "help"
module Homebrew module Homebrew
sig { returns(T.noreturn) } module Cmd
def help class HelpCmd < AbstractCommand
sig { override.void }
def run
Help.help Help.help
end end
end
end
end end

View File

@ -1,15 +1,13 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "abstract_command"
require "formula" require "formula"
module Homebrew module Homebrew
module_function module Cmd
class Home < AbstractCommand
sig { returns(CLI::Parser) } cmd_args do
def home_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Open a <formula> or <cask>'s homepage in a browser, or open Open a <formula> or <cask>'s homepage in a browser, or open
Homebrew's own homepage if no argument is provided. Homebrew's own homepage if no argument is provided.
@ -23,12 +21,9 @@ module Homebrew
named_args [:formula, :cask] named_args [:formula, :cask]
end end
end
sig { void }
def home
args = home_args.parse
sig { override.void }
def run
if args.no_named? if args.no_named?
exec_browser HOMEBREW_WWW exec_browser HOMEBREW_WWW
return return
@ -44,6 +39,8 @@ module Homebrew
exec_browser(*T.unsafe(homepages)) exec_browser(*T.unsafe(homepages))
end end
private
def name_of(formula_or_cask) def name_of(formula_or_cask)
if formula_or_cask.is_a? Formula if formula_or_cask.is_a? Formula
"Formula #{formula_or_cask.name}" "Formula #{formula_or_cask.name}"
@ -51,4 +48,6 @@ module Homebrew
"Cask #{formula_or_cask.token}" "Cask #{formula_or_cask.token}"
end end
end end
end
end
end end

View File

@ -1,9 +1,9 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "missing_formula" require "missing_formula"
require "caveats" require "caveats"
require "cli/parser"
require "options" require "options"
require "formula" require "formula"
require "keg" require "keg"
@ -14,15 +14,13 @@ require "deprecate_disable"
require "api" require "api"
module Homebrew module Homebrew
module_function module Cmd
class Info < AbstractCommand
VALID_DAYS = %w[30 90 365].freeze VALID_DAYS = %w[30 90 365].freeze
VALID_FORMULA_CATEGORIES = %w[install install-on-request build-error].freeze VALID_FORMULA_CATEGORIES = %w[install install-on-request build-error].freeze
VALID_CATEGORIES = (VALID_FORMULA_CATEGORIES + %w[cask-install os-version]).freeze VALID_CATEGORIES = (VALID_FORMULA_CATEGORIES + %w[cask-install os-version]).freeze
sig { returns(CLI::Parser) } cmd_args do
def info_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Display brief statistics for your Homebrew installation. Display brief statistics for your Homebrew installation.
If a <formula> or <cask> is provided, show summary of information about it. If a <formula> or <cask> is provided, show summary of information about it.
@ -74,12 +72,9 @@ module Homebrew
named_args [:formula, :cask] named_args [:formula, :cask]
end end
end
sig { void }
def info
args = info_args.parse
sig { override.void }
def run
if args.analytics? if args.analytics?
if args.days.present? && VALID_DAYS.exclude?(args.days) if args.days.present? && VALID_DAYS.exclude?(args.days)
raise UsageError, "`--days` must be one of #{VALID_DAYS.join(", ")}." raise UsageError, "`--days` must be one of #{VALID_DAYS.join(", ")}."
@ -96,11 +91,11 @@ module Homebrew
end end
end end
print_analytics(args:) print_analytics
elsif args.json elsif args.json
all = args.eval_all? all = args.eval_all?
print_json(all, args:) print_json(all)
elsif args.github? elsif args.github?
raise FormulaOrCaskUnspecifiedError if args.no_named? raise FormulaOrCaskUnspecifiedError if args.no_named?
@ -108,10 +103,20 @@ module Homebrew
elsif args.no_named? elsif args.no_named?
print_statistics print_statistics
else else
print_info(args:) print_info
end end
end end
def github_remote_path(remote, path)
if remote =~ %r{^(?:https?://|git(?:@|://))github\.com[:/](.+)/(.+?)(?:\.git)?$}
"https://github.com/#{Regexp.last_match(1)}/#{Regexp.last_match(2)}/blob/HEAD/#{path}"
else
"#{remote}/#{path}"
end
end
private
sig { void } sig { void }
def print_statistics def print_statistics
return unless HOMEBREW_CELLAR.exist? return unless HOMEBREW_CELLAR.exist?
@ -120,8 +125,8 @@ module Homebrew
puts "#{Utils.pluralize("keg", count, include_count: true)}, #{HOMEBREW_CELLAR.dup.abv}" puts "#{Utils.pluralize("keg", count, include_count: true)}, #{HOMEBREW_CELLAR.dup.abv}"
end end
sig { params(args: CLI::Args).void } sig { void }
def print_analytics(args:) def print_analytics
if args.no_named? if args.no_named?
Utils::Analytics.output(args:) Utils::Analytics.output(args:)
return return
@ -143,16 +148,16 @@ module Homebrew
end end
end end
sig { params(args: CLI::Args).void } sig { void }
def print_info(args:) def print_info
args.named.to_formulae_and_casks_and_unavailable.each_with_index do |obj, i| args.named.to_formulae_and_casks_and_unavailable.each_with_index do |obj, i|
puts unless i.zero? puts unless i.zero?
case obj case obj
when Formula when Formula
info_formula(obj, args:) info_formula(obj)
when Cask::Cask when Cask::Cask
info_cask(obj, args:) info_cask(obj)
when FormulaUnreadableError, FormulaClassUnavailableError, when FormulaUnreadableError, FormulaClassUnavailableError,
TapFormulaUnreadableError, TapFormulaClassUnavailableError, TapFormulaUnreadableError, TapFormulaClassUnavailableError,
Cask::CaskUnreadableError Cask::CaskUnreadableError
@ -184,8 +189,8 @@ module Homebrew
version_hash[version] version_hash[version]
end end
sig { params(all: T::Boolean, args: T.untyped).void } sig { params(all: T::Boolean).void }
def print_json(all, args:) def print_json(all)
raise FormulaOrCaskUnspecifiedError if !(all || args.installed?) && args.no_named? raise FormulaOrCaskUnspecifiedError if !(all || args.installed?) && args.no_named?
json = case json_version(args.json) json = case json_version(args.json)
@ -235,14 +240,6 @@ module Homebrew
puts JSON.pretty_generate(json) puts JSON.pretty_generate(json)
end end
def github_remote_path(remote, path)
if remote =~ %r{^(?:https?://|git(?:@|://))github\.com[:/](.+)/(.+?)(?:\.git)?$}
"https://github.com/#{Regexp.last_match(1)}/#{Regexp.last_match(2)}/blob/HEAD/#{path}"
else
"#{remote}/#{path}"
end
end
def github_info(formula_or_cask) def github_info(formula_or_cask)
return formula_or_cask.path if formula_or_cask.tap.blank? || formula_or_cask.tap.remote.blank? return formula_or_cask.path if formula_or_cask.tap.blank? || formula_or_cask.tap.remote.blank?
@ -262,7 +259,7 @@ module Homebrew
github_remote_path(formula_or_cask.tap.remote, path) github_remote_path(formula_or_cask.tap.remote, path)
end end
def info_formula(formula, args:) def info_formula(formula)
specs = [] specs = []
if (stable = formula.stable) if (stable = formula.stable)
@ -369,9 +366,11 @@ module Homebrew
"#{dep.name} #{dep.option_tags.map { |o| "--#{o}" }.join(" ")}" "#{dep.name} #{dep.option_tags.map { |o| "--#{o}" }.join(" ")}"
end end
def info_cask(cask, args:) def info_cask(cask)
require "cask/info" require "cask/info"
Cask::Info.info(cask) Cask::Info.info(cask)
end end
end
end
end end

View File

@ -1,6 +1,7 @@
# typed: true # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "cask/config" require "cask/config"
require "cask/installer" require "cask/installer"
require "cask_dependent" require "cask_dependent"
@ -9,13 +10,12 @@ require "formula_installer"
require "development_tools" require "development_tools"
require "install" require "install"
require "cleanup" require "cleanup"
require "cli/parser"
require "upgrade" require "upgrade"
module Homebrew module Homebrew
sig { returns(CLI::Parser) } module Cmd
def self.install_args class InstallCmd < AbstractCommand
Homebrew::CLI::Parser.new do cmd_args do
description <<~EOS description <<~EOS
Install a <formula> or <cask>. Additional options specific to a <formula> may be Install a <formula> or <cask>. Additional options specific to a <formula> may be
appended to the command. appended to the command.
@ -50,8 +50,9 @@ module Homebrew
}], }],
[:switch, "--ignore-dependencies", { [:switch, "--ignore-dependencies", {
description: "An unsupported Homebrew development option to skip installing any dependencies of any " \ description: "An unsupported Homebrew development option to skip installing any dependencies of any " \
"kind. If the dependencies are not already present, the formula will have issues. If you're " \ "kind. If the dependencies are not already present, the formula will have issues. If " \
"not developing Homebrew, consider adjusting your PATH rather than using this option.", "you're not developing Homebrew, consider adjusting your PATH rather than using this " \
"option.",
}], }],
[:switch, "--only-dependencies", { [:switch, "--only-dependencies", {
description: "Install the dependencies with specified options but do not install the " \ description: "Install the dependencies with specified options but do not install the " \
@ -161,11 +162,9 @@ module Homebrew
named_args [:formula, :cask], min: 1 named_args [:formula, :cask], min: 1
end end
end
def self.install
args = install_args.parse
sig { override.void }
def run
if args.env.present? if args.env.present?
# Can't use `replacement: false` because `install_args` are used by # Can't use `replacement: false` because `install_args` are used by
# `build.rb`. Instead, `hide_from_man_page` and don't do anything with # `build.rb`. Instead, `hide_from_man_page` and don't do anything with
@ -194,8 +193,10 @@ module Homebrew
end end
begin begin
formulae, casks = args.named.to_formulae_and_casks(warn: false) formulae, casks = T.cast(
.partition { |formula_or_cask| formula_or_cask.is_a?(Formula) } args.named.to_formulae_and_casks(warn: false).partition { _1.is_a?(Formula) },
[T::Array[Formula], T::Array[Cask::Cask]],
)
rescue FormulaOrCaskUnavailableError, Cask::CaskUnavailableError rescue FormulaOrCaskUnavailableError, Cask::CaskUnavailableError
cask_tap = CoreCaskTap.instance cask_tap = CoreCaskTap.instance
if !cask_tap.installed? && (args.cask? || Tap.untapped_official_taps.exclude?(cask_tap.name)) if !cask_tap.installed? && (args.cask? || Tap.untapped_official_taps.exclude?(cask_tap.name))
@ -405,4 +406,6 @@ module Homebrew
odie "No #{package_types.join(" or ")} found for #{name}." odie "No #{package_types.join(" or ")} found for #{name}."
end end
end
end
end end

View File

@ -1,16 +1,14 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "formula" require "formula"
require "cask_dependent" require "cask_dependent"
require "cli/parser"
module Homebrew module Homebrew
module_function module Cmd
class Leaves < AbstractCommand
sig { returns(CLI::Parser) } cmd_args do
def leaves_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
List installed formulae that are not dependencies of another installed formula or cask. List installed formulae that are not dependencies of another installed formula or cask.
EOS EOS
@ -23,19 +21,9 @@ module Homebrew
named_args :none named_args :none
end end
end
def installed_on_request?(formula)
Tab.for_keg(formula.any_installed_keg).installed_on_request
end
def installed_as_dependency?(formula)
Tab.for_keg(formula.any_installed_keg).installed_as_dependency
end
def leaves
args = leaves_args.parse
sig { override.void }
def run
leaves_list = Formula.installed - Formula.installed.flat_map(&:runtime_formula_dependencies) leaves_list = Formula.installed - Formula.installed.flat_map(&:runtime_formula_dependencies)
casks_runtime_dependencies = Cask::Caskroom.casks.flat_map do |cask| casks_runtime_dependencies = Cask::Caskroom.casks.flat_map do |cask|
CaskDependent.new(cask).runtime_dependencies.map(&:to_formula) CaskDependent.new(cask).runtime_dependencies.map(&:to_formula)
@ -48,4 +36,16 @@ module Homebrew
.sort .sort
.each(&method(:puts)) .each(&method(:puts))
end end
private
def installed_on_request?(formula)
Tab.for_keg(formula.any_installed_keg).installed_on_request
end
def installed_as_dependency?(formula)
Tab.for_keg(formula.any_installed_keg).installed_as_dependency
end
end
end
end end

View File

@ -1,16 +1,14 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command"
require "caveats" require "caveats"
require "cli/parser"
require "unlink" require "unlink"
module Homebrew module Homebrew
module_function module Cmd
class Link < AbstractCommand
sig { returns(CLI::Parser) } cmd_args do
def link_args
Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Symlink all of <formula>'s installed files into Homebrew's prefix. Symlink all of <formula>'s installed files into Homebrew's prefix.
This is done automatically when you install formulae but can be useful This is done automatically when you install formulae but can be useful
@ -28,11 +26,9 @@ module Homebrew
named_args :installed_formula, min: 1 named_args :installed_formula, min: 1
end end
end
def link
args = link_args.parse
sig { override.void }
def run
options = { options = {
overwrite: args.overwrite?, overwrite: args.overwrite?,
dry_run: args.dry_run?, dry_run: args.dry_run?,
@ -86,7 +82,8 @@ module Homebrew
end end
if keg_only if keg_only
if HOMEBREW_PREFIX.to_s == HOMEBREW_DEFAULT_PREFIX && formula.present? && formula.keg_only_reason.by_macos? if HOMEBREW_PREFIX.to_s == HOMEBREW_DEFAULT_PREFIX && formula.present? &&
formula.keg_only_reason.by_macos?
caveats = Caveats.new(formula) caveats = Caveats.new(formula)
opoo <<~EOS opoo <<~EOS
Refusing to link macOS provided/shadowed software: #{keg.name} Refusing to link macOS provided/shadowed software: #{keg.name}
@ -122,6 +119,8 @@ module Homebrew
end end
end end
private
def puts_keg_only_path_message(keg) def puts_keg_only_path_message(keg)
bin = keg/"bin" bin = keg/"bin"
sbin = keg/"sbin" sbin = keg/"sbin"
@ -132,4 +131,6 @@ module Homebrew
puts " #{Utils::Shell.prepend_path_in_profile(opt/"bin")}" if bin.directory? puts " #{Utils::Shell.prepend_path_in_profile(opt/"bin")}" if bin.directory?
puts " #{Utils::Shell.prepend_path_in_profile(opt/"sbin")}" if sbin.directory? puts " #{Utils::Shell.prepend_path_in_profile(opt/"sbin")}" if sbin.directory?
end end
end
end
end end

View File

@ -177,7 +177,10 @@ module Commands
external_commands_file.atomic_write("#{external_commands.sort.join("\n")}\n") external_commands_file.atomic_write("#{external_commands.sort.join("\n")}\n")
end end
sig { params(command: String).returns(T.nilable(T::Array[[String, String]])) }
def self.command_options(command) def self.command_options(command)
return if command == "help"
path = self.path(command) path = self.path(command)
return if path.blank? return if path.blank?
@ -207,7 +210,7 @@ module Commands
if (cmd_parser = Homebrew::CLI::Parser.from_cmd_path(path)) if (cmd_parser = Homebrew::CLI::Parser.from_cmd_path(path))
if short if short
cmd_parser.description.split(DESCRIPTION_SPLITTING_PATTERN).first cmd_parser.description&.split(DESCRIPTION_SPLITTING_PATTERN)&.first
else else
cmd_parser.description cmd_parser.description
end end

View File

@ -15,7 +15,6 @@ require "style"
require "date" require "date"
require "missing_formula" require "missing_formula"
require "digest" require "digest"
require "cli/parser"
require "json" require "json"
require "formula_auditor" require "formula_auditor"
require "tap_auditor" require "tap_auditor"

View File

@ -8,7 +8,6 @@ require "utils/bottles"
require "tab" require "tab"
require "keg" require "keg"
require "formula_versions" require "formula_versions"
require "cli/parser"
require "utils/inreplace" require "utils/inreplace"
require "erb" require "erb"
require "utils/gzip" require "utils/gzip"
@ -108,6 +107,110 @@ module Homebrew
end end
end end
def generate_sha256_line(tag, digest, cellar, tag_column, digest_column)
line = "sha256 "
tag_column += line.length
digest_column += line.length
if cellar.is_a?(Symbol)
line += "cellar: :#{cellar},"
elsif cellar_parameter_needed?(cellar)
line += %Q(cellar: "#{cellar}",)
end
line += " " * (tag_column - line.length)
line += "#{tag}:"
line += " " * (digest_column - line.length)
%Q(#{line}"#{digest}")
end
def bottle_output(bottle, root_url_using)
cellars = bottle.checksums.filter_map do |checksum|
cellar = checksum["cellar"]
next unless cellar_parameter_needed? cellar
case cellar
when String
%Q("#{cellar}")
when Symbol
":#{cellar}"
end
end
tag_column = cellars.empty? ? 0 : "cellar: #{cellars.max_by(&:length)}, ".length
tags = bottle.checksums.map { |checksum| checksum["tag"] }
# Start where the tag ends, add the max length of the tag, add two for the `: `
digest_column = tag_column + tags.max_by(&:length).length + 2
sha256_lines = bottle.checksums.map do |checksum|
generate_sha256_line(checksum["tag"], checksum["digest"], checksum["cellar"], tag_column, digest_column)
end
erb_binding = bottle.instance_eval { binding }
erb_binding.local_variable_set(:sha256_lines, sha256_lines)
erb_binding.local_variable_set(:root_url_using, root_url_using)
erb = ERB.new BOTTLE_ERB
erb.result(erb_binding).gsub(/^\s*$\n/, "")
end
def parse_json_files(filenames)
filenames.map do |filename|
JSON.parse(File.read(filename))
end
end
def merge_json_files(json_files)
json_files.reduce({}) do |hash, json_file|
json_file.each_value do |json_hash|
json_bottle = json_hash["bottle"]
cellar = json_bottle.delete("cellar")
json_bottle["tags"].each_value do |json_platform|
json_platform["cellar"] ||= cellar
end
end
hash.deep_merge(json_file)
end
end
def merge_bottle_spec(old_keys, old_bottle_spec, new_bottle_hash)
mismatches = []
checksums = []
new_values = {
root_url: new_bottle_hash["root_url"],
rebuild: new_bottle_hash["rebuild"],
}
skip_keys = [:sha256, :cellar]
old_keys.each do |key|
next if skip_keys.include?(key)
old_value = old_bottle_spec.send(key).to_s
new_value = new_values[key].to_s
next if old_value.present? && new_value == old_value
mismatches << "#{key}: old: #{old_value.inspect}, new: #{new_value.inspect}"
end
return [mismatches, checksums] if old_keys.exclude? :sha256
old_bottle_spec.collector.each_tag do |tag|
old_tag_spec = old_bottle_spec.collector.specification_for(tag)
old_hexdigest = old_tag_spec.checksum.hexdigest
old_cellar = old_tag_spec.cellar
new_value = new_bottle_hash.dig("tags", tag.to_s)
if new_value.present? && new_value["sha256"] != old_hexdigest
mismatches << "sha256 #{tag}: old: #{old_hexdigest.inspect}, new: #{new_value["sha256"].inspect}"
elsif new_value.present? && new_value["cellar"] != old_cellar.to_s
mismatches << "cellar #{tag}: old: #{old_cellar.to_s.inspect}, new: #{new_value["cellar"].inspect}"
else
checksums << { cellar: old_cellar, tag.to_sym => old_hexdigest }
end
end
[mismatches, checksums]
end
private
def keg_contain?(string, keg, ignores, formula_and_runtime_deps_names = nil) def keg_contain?(string, keg, ignores, formula_and_runtime_deps_names = nil)
@put_string_exists_header, @put_filenames = nil @put_string_exists_header, @put_filenames = nil
@ -186,49 +289,6 @@ module Homebrew
cellar.present? && default_cellars.exclude?(cellar) cellar.present? && default_cellars.exclude?(cellar)
end end
def generate_sha256_line(tag, digest, cellar, tag_column, digest_column)
line = "sha256 "
tag_column += line.length
digest_column += line.length
if cellar.is_a?(Symbol)
line += "cellar: :#{cellar},"
elsif cellar_parameter_needed?(cellar)
line += %Q(cellar: "#{cellar}",)
end
line += " " * (tag_column - line.length)
line += "#{tag}:"
line += " " * (digest_column - line.length)
%Q(#{line}"#{digest}")
end
def bottle_output(bottle, root_url_using)
cellars = bottle.checksums.filter_map do |checksum|
cellar = checksum["cellar"]
next unless cellar_parameter_needed? cellar
case cellar
when String
%Q("#{cellar}")
when Symbol
":#{cellar}"
end
end
tag_column = cellars.empty? ? 0 : "cellar: #{cellars.max_by(&:length)}, ".length
tags = bottle.checksums.map { |checksum| checksum["tag"] }
# Start where the tag ends, add the max length of the tag, add two for the `: `
digest_column = tag_column + tags.max_by(&:length).length + 2
sha256_lines = bottle.checksums.map do |checksum|
generate_sha256_line(checksum["tag"], checksum["digest"], checksum["cellar"], tag_column, digest_column)
end
erb_binding = bottle.instance_eval { binding }
erb_binding.local_variable_set(:sha256_lines, sha256_lines)
erb_binding.local_variable_set(:root_url_using, root_url_using)
erb = ERB.new BOTTLE_ERB
erb.result(erb_binding).gsub(/^\s*$\n/, "")
end
def sudo_purge def sudo_purge
return unless ENV["HOMEBREW_BOTTLE_SUDO_PURGE"] return unless ENV["HOMEBREW_BOTTLE_SUDO_PURGE"]
@ -601,25 +661,6 @@ module Homebrew
json_path.write(JSON.pretty_generate(json)) json_path.write(JSON.pretty_generate(json))
end end
def parse_json_files(filenames)
filenames.map do |filename|
JSON.parse(File.read(filename))
end
end
def merge_json_files(json_files)
json_files.reduce({}) do |hash, json_file|
json_file.each_value do |json_hash|
json_bottle = json_hash["bottle"]
cellar = json_bottle.delete("cellar")
json_bottle["tags"].each_value do |json_platform|
json_platform["cellar"] ||= cellar
end
end
hash.deep_merge(json_file)
end
end
def merge def merge
bottles_hash = merge_json_files(parse_json_files(args.named)) bottles_hash = merge_json_files(parse_json_files(args.named))
@ -774,46 +815,6 @@ module Homebrew
end end
end end
def merge_bottle_spec(old_keys, old_bottle_spec, new_bottle_hash)
mismatches = []
checksums = []
new_values = {
root_url: new_bottle_hash["root_url"],
rebuild: new_bottle_hash["rebuild"],
}
skip_keys = [:sha256, :cellar]
old_keys.each do |key|
next if skip_keys.include?(key)
old_value = old_bottle_spec.send(key).to_s
new_value = new_values[key].to_s
next if old_value.present? && new_value == old_value
mismatches << "#{key}: old: #{old_value.inspect}, new: #{new_value.inspect}"
end
return [mismatches, checksums] if old_keys.exclude? :sha256
old_bottle_spec.collector.each_tag do |tag|
old_tag_spec = old_bottle_spec.collector.specification_for(tag)
old_hexdigest = old_tag_spec.checksum.hexdigest
old_cellar = old_tag_spec.cellar
new_value = new_bottle_hash.dig("tags", tag.to_s)
if new_value.present? && new_value["sha256"] != old_hexdigest
mismatches << "sha256 #{tag}: old: #{old_hexdigest.inspect}, new: #{new_value["sha256"].inspect}"
elsif new_value.present? && new_value["cellar"] != old_cellar.to_s
mismatches << "cellar #{tag}: old: #{old_cellar.to_s.inspect}, new: #{new_value["cellar"].inspect}"
else
checksums << { cellar: old_cellar, tag.to_sym => old_hexdigest }
end
end
[mismatches, checksums]
end
def old_checksums(formula, formula_ast, bottle_hash) def old_checksums(formula, formula_ast, bottle_hash)
bottle_node = formula_ast.bottle_block bottle_node = formula_ast.bottle_block
return if bottle_node.nil? return if bottle_node.nil?

View File

@ -5,7 +5,6 @@ require "abstract_command"
require "bump_version_parser" require "bump_version_parser"
require "cask" require "cask"
require "cask/download" require "cask/download"
require "cli/parser"
require "utils/tar" require "utils/tar"
module Homebrew module Homebrew

View File

@ -4,7 +4,6 @@
require "abstract_command" require "abstract_command"
require "fileutils" require "fileutils"
require "formula" require "formula"
require "cli/parser"
require "utils/pypi" require "utils/pypi"
require "utils/tar" require "utils/tar"

View File

@ -3,7 +3,6 @@
require "abstract_command" require "abstract_command"
require "formula" require "formula"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -5,7 +5,6 @@ require "timeout"
require "cask/download" require "cask/download"
require "cask/installer" require "cask/installer"
require "cask/cask_loader" require "cask/cask_loader"
require "cli/parser"
require "system_command" require "system_command"
require "tap" require "tap"
require "unversioned_cask_checker" require "unversioned_cask_checker"

View File

@ -3,7 +3,6 @@
require "abstract_command" require "abstract_command"
require "bump_version_parser" require "bump_version_parser"
require "cli/parser"
require "livecheck/livecheck" require "livecheck/livecheck"
module Homebrew module Homebrew

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "fileutils" require "fileutils"
module Homebrew module Homebrew

View File

@ -3,7 +3,6 @@
require "abstract_command" require "abstract_command"
require "commands" require "commands"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "csv" require "csv"
module Homebrew module Homebrew

View File

@ -4,7 +4,6 @@
require "formula" require "formula"
require "formula_creator" require "formula_creator"
require "missing_formula" require "missing_formula"
require "cli/parser"
require "utils/pypi" require "utils/pypi"
require "cask/cask_loader" require "cask/cask_loader"

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "test_runner_formula" require "test_runner_formula"
require "github_runner_matrix" require "github_runner_matrix"

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "utils/github" require "utils/github"
module Homebrew module Homebrew

View File

@ -3,7 +3,6 @@
require "abstract_command" require "abstract_command"
require "formula" require "formula"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "utils/git" require "utils/git"
require "formulary" require "formulary"
require "software_spec" require "software_spec"

View File

@ -3,7 +3,6 @@
require "abstract_command" require "abstract_command"
require "formula" require "formula"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "cask/cask" require "cask/cask"
require "fileutils" require "fileutils"
require "formula" require "formula"

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "fileutils" require "fileutils"
require "formula" require "formula"

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -4,7 +4,6 @@
require "abstract_command" require "abstract_command"
require "formulary" require "formulary"
require "cask/cask_loader" require "cask/cask_loader"
require "cli/parser"
class String class String
def f(*args) def f(*args)

View File

@ -4,7 +4,6 @@
require "abstract_command" require "abstract_command"
require "cache_store" require "cache_store"
require "linkage_checker" require "linkage_checker"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "formula" require "formula"
require "livecheck/livecheck" require "livecheck/livecheck"
require "livecheck/strategy" require "livecheck/strategy"

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "utils/github" require "utils/github"
module Homebrew module Homebrew

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "utils/github" require "utils/github"
module Homebrew module Homebrew

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "fileutils" require "fileutils"
require "utils/github" require "utils/github"
require "utils/github/artifacts" require "utils/github/artifacts"

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "formula" require "formula"
require "github_packages" require "github_packages"
require "github_releases" require "github_releases"

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -4,7 +4,6 @@
require "abstract_command" require "abstract_command"
require "extend/ENV" require "extend/ENV"
require "formula" require "formula"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -5,7 +5,6 @@ require "abstract_command"
require "json" require "json"
require "open3" require "open3"
require "style" require "style"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -4,7 +4,6 @@
require "abstract_command" require "abstract_command"
require "fileutils" require "fileutils"
require "tap" require "tap"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -5,7 +5,6 @@ require "abstract_command"
require "extend/ENV" require "extend/ENV"
require "sandbox" require "sandbox"
require "timeout" require "timeout"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "fileutils" require "fileutils"
require "system_command" require "system_command"

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "fileutils" require "fileutils"
module Homebrew module Homebrew

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "formula" require "formula"
require "api" require "api"
require "os/mac/xcode" require "os/mac/xcode"

View File

@ -5,7 +5,6 @@ require "abstract_command"
require "fileutils" require "fileutils"
require "stringio" require "stringio"
require "formula" require "formula"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "utils/spdx" require "utils/spdx"
require "system_command" require "system_command"

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "utils/github" require "utils/github"
require "manpages" require "manpages"
require "system_command" require "system_command"

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "utils/pypi" require "utils/pypi"
module Homebrew module Homebrew

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "utils/github" require "utils/github"
require "system_command" require "system_command"

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
require "fileutils" require "fileutils"
module Homebrew module Homebrew

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
require "cli/parser"
module Homebrew module Homebrew
module DevCmd module DevCmd

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/analytics"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew analytics" do RSpec.describe Homebrew::Cmd::Analytics do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
it "when HOMEBREW_NO_ANALYTICS is unset is disabled after running `brew analytics off`", :integration_test do it "when HOMEBREW_NO_ANALYTICS is unset is disabled after running `brew analytics off`", :integration_test do

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/autoremove"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew autoremove" do RSpec.describe Homebrew::Cmd::Autoremove do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
describe "integration test" do describe "integration test" do

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/cleanup"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew cleanup" do RSpec.describe Homebrew::Cmd::CleanupCmd do
before do before do
FileUtils.mkdir_p HOMEBREW_LIBRARY/"Homebrew/vendor/" FileUtils.mkdir_p HOMEBREW_LIBRARY/"Homebrew/vendor/"
FileUtils.touch HOMEBREW_LIBRARY/"Homebrew/vendor/portable-ruby-version" FileUtils.touch HOMEBREW_LIBRARY/"Homebrew/vendor/portable-ruby-version"

View File

@ -1,11 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/commands" require "cmd/commands"
require "fileutils"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew commands" do RSpec.describe Homebrew::Cmd::CommandsCmd do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
it "prints a list of all available commands", :integration_test do it "prints a list of all available commands", :integration_test do

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/completions"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew completions" do RSpec.describe Homebrew::Cmd::CompletionsCmd do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
it "runs the status subcommand correctly", :integration_test do it "runs the status subcommand correctly", :integration_test do

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/config"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew config" do RSpec.describe Homebrew::Cmd::Config do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
it "prints information about the current Homebrew configuration", :integration_test do it "prints information about the current Homebrew configuration", :integration_test do

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/deps"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew deps" do RSpec.describe Homebrew::Cmd::Deps do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
it "outputs all of a Formula's dependencies and their dependencies on separate lines", :integration_test do it "outputs all of a Formula's dependencies and their dependencies on separate lines", :integration_test do

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/desc"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew desc" do RSpec.describe Homebrew::Cmd::Desc do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
it "shows a given Formula's description", :integration_test do it "shows a given Formula's description", :integration_test do

View File

@ -1,7 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/developer"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew developer" do RSpec.describe Homebrew::Cmd::Developer do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
end end

View File

@ -1,6 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe "brew docs" do require "cmd/docs"
require "cmd/shared_examples/args_parse"
RSpec.describe Homebrew::Cmd::Docs do
it_behaves_like "parseable arguments"
it "opens the docs page", :integration_test do it "opens the docs page", :integration_test do
expect { brew "docs", "HOMEBREW_BROWSER" => "echo" } expect { brew "docs", "HOMEBREW_BROWSER" => "echo" }
.to output("https://docs.brew.sh\n").to_stdout .to output("https://docs.brew.sh\n").to_stdout

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/doctor"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew doctor" do RSpec.describe Homebrew::Cmd::Doctor do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
specify "check_integration_test", :integration_test do specify "check_integration_test", :integration_test do

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/fetch"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew fetch" do RSpec.describe Homebrew::Cmd::FetchCmd do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
it "downloads the Formula's URL", :integration_test do it "downloads the Formula's URL", :integration_test do

View File

@ -1,7 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/gist-logs"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew gist-logs" do RSpec.describe Homebrew::Cmd::GistLogs do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
end end

View File

@ -1,6 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe "brew", :integration_test do require "cmd/help"
require "cmd/shared_examples/args_parse"
RSpec.describe Homebrew::Cmd::HelpCmd, :integration_test do
it_behaves_like "parseable arguments"
describe "help" do describe "help" do
it "prints help for a documented Ruby command" do it "prints help for a documented Ruby command" do
expect { brew "help", "cat" } expect { brew "help", "cat" }

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/home"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew home" do RSpec.describe Homebrew::Cmd::Home do
let(:testballhome_homepage) do let(:testballhome_homepage) do
Formula["testballhome"].homepage Formula["testballhome"].homepage
end end

View File

@ -1,10 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/info" require "cmd/info"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew info" do RSpec.describe Homebrew::Cmd::Info do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
it "prints as json with the --json=v1 flag", :integration_test do it "prints as json with the --json=v1 flag", :integration_test do
@ -25,23 +24,21 @@ RSpec.describe "brew info" do
.and be_a_success .and be_a_success
end end
describe Homebrew do
describe "::github_remote_path" do describe "::github_remote_path" do
let(:remote) { "https://github.com/Homebrew/homebrew-core" } let(:remote) { "https://github.com/Homebrew/homebrew-core" }
specify "returns correct URLs" do specify "returns correct URLs" do
expect(described_class.github_remote_path(remote, "Formula/git.rb")) expect(described_class.new([]).github_remote_path(remote, "Formula/git.rb"))
.to eq("https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/git.rb") .to eq("https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/git.rb")
expect(described_class.github_remote_path("#{remote}.git", "Formula/git.rb")) expect(described_class.new([]).github_remote_path("#{remote}.git", "Formula/git.rb"))
.to eq("https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/git.rb") .to eq("https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/git.rb")
expect(described_class.github_remote_path("git@github.com:user/repo", "foo.rb")) expect(described_class.new([]).github_remote_path("git@github.com:user/repo", "foo.rb"))
.to eq("https://github.com/user/repo/blob/HEAD/foo.rb") .to eq("https://github.com/user/repo/blob/HEAD/foo.rb")
expect(described_class.github_remote_path("https://mywebsite.com", "foo/bar.rb")) expect(described_class.new([]).github_remote_path("https://mywebsite.com", "foo/bar.rb"))
.to eq("https://mywebsite.com/foo/bar.rb") .to eq("https://mywebsite.com/foo/bar.rb")
end end
end end
end
end end

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/install"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew install" do RSpec.describe Homebrew::Cmd::InstallCmd do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
it "installs formulae", :integration_test do it "installs formulae", :integration_test do

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/leaves"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew leaves" do RSpec.describe Homebrew::Cmd::Leaves do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
context "when there are no installed Formulae", :integration_test do context "when there are no installed Formulae", :integration_test do

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/link"
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
RSpec.describe "brew link" do RSpec.describe Homebrew::Cmd::Link do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
it "links a given Formula", :integration_test do it "links a given Formula", :integration_test do

View File

@ -70,7 +70,7 @@ RSpec.describe FormulaInstaller do
# rubocop:disable RSpec/NoExpectationExample # rubocop:disable RSpec/NoExpectationExample
specify "basic bottle install" do specify "basic bottle install" do
allow(DevelopmentTools).to receive(:installed?).and_return(false) allow(DevelopmentTools).to receive(:installed?).and_return(false)
Homebrew.install_args.parse(["testball_bottle"]) Homebrew::Cmd::InstallCmd.new(["testball_bottle"])
temporarily_install_bottle(TestballBottle.new) do |f| temporarily_install_bottle(TestballBottle.new) do |f|
test_basic_formula_setup(f) test_basic_formula_setup(f)
end end
@ -79,7 +79,7 @@ RSpec.describe FormulaInstaller do
specify "basic bottle install with cellar information on sha256 line" do specify "basic bottle install with cellar information on sha256 line" do
allow(DevelopmentTools).to receive(:installed?).and_return(false) allow(DevelopmentTools).to receive(:installed?).and_return(false)
Homebrew.install_args.parse(["testball_bottle_cellar"]) Homebrew::Cmd::InstallCmd.new(["testball_bottle_cellar"])
temporarily_install_bottle(TestballBottleCellar.new) do |f| temporarily_install_bottle(TestballBottleCellar.new) do |f|
test_basic_formula_setup(f) test_basic_formula_setup(f)