diff --git a/Library/Homebrew/dev-cmd/typecheck.rb b/Library/Homebrew/dev-cmd/typecheck.rb index 1978fdb077..4789caa7df 100644 --- a/Library/Homebrew/dev-cmd/typecheck.rb +++ b/Library/Homebrew/dev-cmd/typecheck.rb @@ -1,95 +1,99 @@ -# typed: true +# typed: strict # frozen_string_literal: true +require "abstract_command" require "cli/parser" +require "fileutils" module Homebrew - sig { returns(CLI::Parser) } - def self.typecheck_args - Homebrew::CLI::Parser.new do - description <<~EOS - Check for typechecking errors using Sorbet. - EOS - switch "--fix", - description: "Automatically fix type errors." - switch "-q", "--quiet", - description: "Silence all non-critical errors." - switch "--update", - description: "Update RBI files." - switch "--update-all", - description: "Update all RBI files rather than just updated gems." - switch "--suggest-typed", - depends_on: "--update", - description: "Try upgrading `typed` sigils." - flag "--dir=", - description: "Typecheck all files in a specific directory." - flag "--file=", - description: "Typecheck a single file." - flag "--ignore=", - description: "Ignores input files that contain the given string " \ - "in their paths (relative to the input path passed to Sorbet)." + module DevCmd + class Typecheck < AbstractCommand + include FileUtils - conflicts "--dir", "--file" + cmd_args do + description <<~EOS + Check for typechecking errors using Sorbet. + EOS + switch "--fix", + description: "Automatically fix type errors." + switch "-q", "--quiet", + description: "Silence all non-critical errors." + switch "--update", + description: "Update RBI files." + switch "--update-all", + description: "Update all RBI files rather than just updated gems." + switch "--suggest-typed", + depends_on: "--update", + description: "Try upgrading `typed` sigils." + flag "--dir=", + description: "Typecheck all files in a specific directory." + flag "--file=", + description: "Typecheck a single file." + flag "--ignore=", + description: "Ignores input files that contain the given string " \ + "in their paths (relative to the input path passed to Sorbet)." - named_args :none - end - end + conflicts "--dir", "--file" - sig { void } - def self.typecheck - args = typecheck_args.parse - - update = args.update? || args.update_all? - groups = update ? Homebrew.valid_gem_groups : ["typecheck"] - Homebrew.install_bundler_gems!(groups:) - - HOMEBREW_LIBRARY_PATH.cd do - if update - safe_system "bundle", "exec", "tapioca", "dsl" - # Prefer adding args here: Library/Homebrew/sorbet/tapioca/config.yml - tapioca_args = args.update_all? ? ["--all"] : [] - - ohai "Updating homegrown RBI files..." - safe_system "bundle", "exec", "ruby", "sorbet/custom_generators/tty.rb" - safe_system "bundle", "exec", "ruby", "sorbet/custom_generators/env_config.rb" - - ohai "Updating Tapioca RBI files..." - safe_system "bundle", "exec", "tapioca", "gem", *tapioca_args - safe_system "bundle", "exec", "parlour" - - if args.suggest_typed? - ohai "Bumping Sorbet `typed` sigils..." - # --sorbet needed because of https://github.com/Shopify/spoom/issues/488 - safe_system "bundle", "exec", "spoom", "bump", "--dry", "--sorbet", "#{Gem.bin_path("sorbet", "srb")} tc" - end - - return + named_args :none end - srb_exec = %w[bundle exec srb tc] + sig { override.void } + def run + update = args.update? || args.update_all? + groups = update ? Homebrew.valid_gem_groups : ["typecheck"] + Homebrew.install_bundler_gems!(groups:) - srb_exec << "--quiet" if args.quiet? + HOMEBREW_LIBRARY_PATH.cd do + if update + safe_system "bundle", "exec", "tapioca", "dsl" + # Prefer adding args here: Library/Homebrew/sorbet/tapioca/config.yml + tapioca_args = args.update_all? ? ["--all"] : [] - if args.fix? - # Auto-correcting method names is almost always wrong. - srb_exec << "--suppress-error-code" << "7003" + ohai "Updating homegrown RBI files..." + safe_system "bundle", "exec", "ruby", "sorbet/custom_generators/tty.rb" + safe_system "bundle", "exec", "ruby", "sorbet/custom_generators/env_config.rb" - srb_exec << "--autocorrect" - end + ohai "Updating Tapioca RBI files..." + safe_system "bundle", "exec", "tapioca", "gem", *tapioca_args + safe_system "bundle", "exec", "parlour" - srb_exec += ["--ignore", args.ignore] if args.ignore.present? - if args.file.present? || args.dir.present? - cd("sorbet") do - srb_exec += ["--file", "../#{args.file}"] if args.file - srb_exec += ["--dir", "../#{args.dir}"] if args.dir + if args.suggest_typed? + ohai "Bumping Sorbet `typed` sigils..." + # --sorbet needed because of https://github.com/Shopify/spoom/issues/488 + safe_system "bundle", "exec", "spoom", "bump", "--dry", "--sorbet", + "#{Gem.bin_path("sorbet", "srb")} tc" + end + + return + end + + srb_exec = %w[bundle exec srb tc] + + srb_exec << "--quiet" if args.quiet? + + if args.fix? + # Auto-correcting method names is almost always wrong. + srb_exec << "--suppress-error-code" << "7003" + + srb_exec << "--autocorrect" + end + + srb_exec += ["--ignore", args.ignore] if args.ignore.present? + if args.file.present? || args.dir.present? + cd("sorbet") do + srb_exec += ["--file", "../#{args.file}"] if args.file + srb_exec += ["--dir", "../#{args.dir}"] if args.dir + end + end + success = system(*srb_exec) + return if success + + $stderr.puts "Check #{Formatter.url("https://docs.brew.sh/Typechecking")} for " \ + "more information on how to resolve these errors." + Homebrew.failed = true end end - success = system(*srb_exec) - return if success - - $stderr.puts "Check #{Formatter.url("https://docs.brew.sh/Typechecking")} for " \ - "more information on how to resolve these errors." - Homebrew.failed = true end end end diff --git a/Library/Homebrew/dev-cmd/unbottled.rb b/Library/Homebrew/dev-cmd/unbottled.rb index 8ac5fb9dbb..df18a3a21f 100644 --- a/Library/Homebrew/dev-cmd/unbottled.rb +++ b/Library/Homebrew/dev-cmd/unbottled.rb @@ -1,318 +1,318 @@ # typed: true # frozen_string_literal: true +require "abstract_command" require "cli/parser" require "formula" require "api" require "os/mac/xcode" module Homebrew - module_function + module DevCmd + class Unbottled < AbstractCommand + cmd_args do + description <<~EOS + Show the unbottled dependents of formulae. + EOS + flag "--tag=", + description: "Use the specified bottle tag (e.g. `big_sur`) instead of the current OS." + switch "--dependents", + description: "Skip getting analytics data and sort by number of dependents instead." + switch "--total", + description: "Print the number of unbottled and total formulae." + switch "--lost", + description: "Print the `homebrew/core` commits where bottles were lost in the last week." + switch "--eval-all", + description: "Evaluate all available formulae and casks, whether installed or not, to check them. " \ + "Implied if `HOMEBREW_EVAL_ALL` is set." - sig { returns(CLI::Parser) } - def unbottled_args - Homebrew::CLI::Parser.new do - description <<~EOS - Show the unbottled dependents of formulae. - EOS - flag "--tag=", - description: "Use the specified bottle tag (e.g. `big_sur`) instead of the current OS." - switch "--dependents", - description: "Skip getting analytics data and sort by number of dependents instead." - switch "--total", - description: "Print the number of unbottled and total formulae." - switch "--lost", - description: "Print the `homebrew/core` commits where bottles were lost in the last week." - switch "--eval-all", - description: "Evaluate all available formulae and casks, whether installed or not, to check them. " \ - "Implied if `HOMEBREW_EVAL_ALL` is set." + conflicts "--dependents", "--total", "--lost" - conflicts "--dependents", "--total", "--lost" - - named_args :formula - end - end - - sig { void } - def unbottled - args = unbottled_args.parse - - Formulary.enable_factory_cache! - - @bottle_tag = if (tag = args.tag) - Utils::Bottles::Tag.from_symbol(tag.to_sym) - else - Utils::Bottles.tag - end - - if args.lost? - if args.named.present? - raise UsageError, "`brew unbottled --lost` cannot be used with formula arguments!" - elsif !CoreTap.instance.installed? - raise UsageError, "`brew unbottled --lost` requires `homebrew/core` to be tapped locally!" - else - output_lost_bottles - return + named_args :formula end - end - os = @bottle_tag.system - arch = if Hardware::CPU::INTEL_ARCHS.include?(@bottle_tag.arch) - :intel - elsif Hardware::CPU::ARM_ARCHS.include?(@bottle_tag.arch) - :arm - else - raise "Unknown arch #{@bottle_tag.arch}." - end + sig { override.void } + def run + Formulary.enable_factory_cache! - Homebrew::SimulateSystem.with(os:, arch:) do - all = args.eval_all? - if args.total? - if !all && !Homebrew::EnvConfig.eval_all? - raise UsageError, "`brew unbottled --total` needs `--eval-all` passed or `HOMEBREW_EVAL_ALL` set!" + @bottle_tag = if (tag = args.tag) + Utils::Bottles::Tag.from_symbol(tag.to_sym) + else + Utils::Bottles.tag end - all = true - end - - if args.named.blank? - ohai "Getting formulae..." - elsif all - raise UsageError, "Cannot specify formulae when using `--eval-all`/`--total`." - end - - formulae, all_formulae, formula_installs = - formulae_all_installs_from_args(args, all) - deps_hash, uses_hash = deps_uses_from_formulae(all_formulae) - - if args.dependents? - formula_dependents = {} - formulae = formulae.sort_by do |f| - dependents = uses_hash[f.name]&.length || 0 - formula_dependents[f.name] ||= dependents - end.reverse - elsif all - output_total(formulae) - return - end - - noun, hash = if args.named.present? - [nil, {}] - elsif args.dependents? - ["dependents", formula_dependents] - else - ["installs", formula_installs] - end - - output_unbottled(formulae, deps_hash, noun, hash, args.named.present?) - end - end - - def formulae_all_installs_from_args(args, all) - if args.named.present? - formulae = all_formulae = args.named.to_formulae - elsif args.dependents? - if !args.eval_all? && !Homebrew::EnvConfig.eval_all? - raise UsageError, "`brew unbottled --dependents` needs `--eval-all` passed or `HOMEBREW_EVAL_ALL` set!" - end - - formulae = all_formulae = Formula.all(eval_all: args.eval_all?) - - @sort = " (sorted by number of dependents)" - elsif all - formulae = all_formulae = Formula.all(eval_all: args.eval_all?) - else - formula_installs = {} - - ohai "Getting analytics data..." - analytics = Homebrew::API::Analytics.fetch "install", 90 - - if analytics.blank? - raise UsageError, - "default sort by analytics data requires " \ - "`HOMEBREW_NO_GITHUB_API` and `HOMEBREW_NO_ANALYTICS` to be unset" - end - - formulae = analytics["items"].filter_map do |i| - f = i["formula"].split.first - next if f.include?("/") - next if formula_installs[f].present? - - formula_installs[f] = i["count"] - begin - Formula[f] - rescue FormulaUnavailableError - nil - end - end - @sort = " (sorted by installs in the last 90 days; top 10,000 only)" - - all_formulae = Formula.all(eval_all: args.eval_all?) - end - - # Remove deprecated formulae as we do not care if they are unbottled - formulae = Array(formulae).reject(&:deprecated?) if formulae.present? - all_formulae = Array(all_formulae).reject(&:deprecated?) if all_formulae.present? - - [formulae, all_formulae, formula_installs] - end - - def deps_uses_from_formulae(all_formulae) - ohai "Populating dependency tree..." - - deps_hash = {} - uses_hash = {} - - all_formulae.each do |f| - deps = Dependency.expand(f, cache_key: "unbottled") do |_, dep| - Dependency.prune if dep.optional? - end.map(&:to_formula) - deps_hash[f.name] = deps - - deps.each do |dep| - uses_hash[dep.name] ||= [] - uses_hash[dep.name] << f - end - end - - [deps_hash, uses_hash] - end - - def output_total(formulae) - ohai "Unbottled :#{@bottle_tag} formulae" - unbottled_formulae = 0 - - formulae.each do |f| - next if f.bottle_specification.tag?(@bottle_tag) - - unbottled_formulae += 1 - end - - puts "#{unbottled_formulae}/#{formulae.length} remaining." - end - - def output_unbottled(formulae, deps_hash, noun, hash, any_named_args) - ohai ":#{@bottle_tag} bottle status#{@sort}" - any_found = T.let(false, T::Boolean) - - formulae.each do |f| - name = f.name.downcase - - if f.disabled? - puts "#{Tty.bold}#{Tty.green}#{name}#{Tty.reset}: formula disabled" if any_named_args - next - end - - requirements = f.recursive_requirements - if @bottle_tag.linux? - if requirements.any? { |r| r.is_a?(MacOSRequirement) && !r.version } - puts "#{Tty.bold}#{Tty.red}#{name}#{Tty.reset}: requires macOS" if any_named_args - next - end - elsif requirements.any?(LinuxRequirement) - puts "#{Tty.bold}#{Tty.red}#{name}#{Tty.reset}: requires Linux" if any_named_args - next - else - macos_version = @bottle_tag.to_macos_version - macos_satisfied = requirements.all? do |r| - case r - when MacOSRequirement - next true unless r.version_specified? - - macos_version.compare(r.comparator, r.version) - when XcodeRequirement - next true unless r.version - - Version.new(MacOS::Xcode.latest_version(macos: macos_version)) >= r.version - when ArchRequirement - r.arch == @bottle_tag.arch + if args.lost? + if args.named.present? + raise UsageError, "`brew unbottled --lost` cannot be used with formula arguments!" + elsif !CoreTap.instance.installed? + raise UsageError, "`brew unbottled --lost` requires `homebrew/core` to be tapped locally!" else - true + output_lost_bottles + return end end - unless macos_satisfied - puts "#{Tty.bold}#{Tty.red}#{name}#{Tty.reset}: doesn't support this macOS" if any_named_args - next + + os = @bottle_tag.system + arch = if Hardware::CPU::INTEL_ARCHS.include?(@bottle_tag.arch) + :intel + elsif Hardware::CPU::ARM_ARCHS.include?(@bottle_tag.arch) + :arm + else + raise "Unknown arch #{@bottle_tag.arch}." + end + + Homebrew::SimulateSystem.with(os:, arch:) do + all = args.eval_all? + if args.total? + if !all && !Homebrew::EnvConfig.eval_all? + raise UsageError, "`brew unbottled --total` needs `--eval-all` passed or `HOMEBREW_EVAL_ALL` set!" + end + + all = true + end + + if args.named.blank? + ohai "Getting formulae..." + elsif all + raise UsageError, "Cannot specify formulae when using `--eval-all`/`--total`." + end + + formulae, all_formulae, formula_installs = formulae_all_installs_from_args(all) + deps_hash, uses_hash = deps_uses_from_formulae(all_formulae) + + if args.dependents? + formula_dependents = {} + formulae = formulae.sort_by do |f| + dependents = uses_hash[f.name]&.length || 0 + formula_dependents[f.name] ||= dependents + end.reverse + elsif all + output_total(formulae) + return + end + + noun, hash = if args.named.present? + [nil, {}] + elsif args.dependents? + ["dependents", formula_dependents] + else + ["installs", formula_installs] + end + + output_unbottled(formulae, deps_hash, noun, hash, args.named.present?) end end - if f.bottle_specification.tag?(@bottle_tag, no_older_versions: true) - puts "#{Tty.bold}#{Tty.green}#{name}#{Tty.reset}: already bottled" if any_named_args - next - end + private - deps = Array(deps_hash[f.name]).reject do |dep| - dep.bottle_specification.tag?(@bottle_tag, no_older_versions: true) - end + def formulae_all_installs_from_args(all) + if args.named.present? + formulae = all_formulae = args.named.to_formulae + elsif args.dependents? + if !args.eval_all? && !Homebrew::EnvConfig.eval_all? + raise UsageError, + "`brew unbottled --dependents` needs `--eval-all` passed or `HOMEBREW_EVAL_ALL` set!" + end - if deps.blank? - count = " (#{hash[f.name]} #{noun})" if noun - puts "#{Tty.bold}#{Tty.green}#{name}#{Tty.reset}#{count}: ready to bottle" - next - end + formulae = all_formulae = Formula.all(eval_all: args.eval_all?) - any_found ||= true - count = " (#{hash[f.name]} #{noun})" if noun - puts "#{Tty.bold}#{Tty.yellow}#{name}#{Tty.reset}#{count}: unbottled deps: #{deps.join(" ")}" - end - return if any_found - return if any_named_args + @sort = " (sorted by number of dependents)" + elsif all + formulae = all_formulae = Formula.all(eval_all: args.eval_all?) + else + formula_installs = {} - puts "No unbottled dependencies found!" - end + ohai "Getting analytics data..." + analytics = Homebrew::API::Analytics.fetch "install", 90 - def output_lost_bottles - ohai ":#{@bottle_tag} lost bottles" + if analytics.blank? + raise UsageError, + "default sort by analytics data requires " \ + "`HOMEBREW_NO_GITHUB_API` and `HOMEBREW_NO_ANALYTICS` to be unset" + end - bottle_tag_regex_fragment = " +sha256.* #{@bottle_tag}: " + formulae = analytics["items"].filter_map do |i| + f = i["formula"].split.first + next if f.include?("/") + next if formula_installs[f].present? - # $ git log --patch --no-ext-diff -G'^ +sha256.* sonoma:' --since=@{'1 week ago'} - git_log = %w[git log --patch --no-ext-diff] - git_log << "-G^#{bottle_tag_regex_fragment}" - git_log << "--since=@{'1 week ago'}" - - bottle_tag_sha_regex = /^[+-]#{bottle_tag_regex_fragment}/ - - processed_formulae = Set.new - commit = T.let(nil, T.nilable(String)) - formula = T.let(nil, T.nilable(String)) - lost_bottles = 0 - - CoreTap.instance.path.cd do - Utils.safe_popen_read(*git_log) do |io| - io.each_line do |line| - case line - when /^commit [0-9a-f]{40}$/ - # Example match: `commit 7289b409b96a752540befef1a56b8a818baf1db7` - if commit && formula && lost_bottles.positive? && processed_formulae.exclude?(formula) - puts "#{commit}: bottle lost for #{formula}" + formula_installs[f] = i["count"] + begin + Formula[f] + rescue FormulaUnavailableError + nil end - processed_formulae << formula - commit = line.split.last - formula = nil - when %r{^diff --git a/Formula/} - # Example match: `diff --git a/Formula/a/aws-cdk.rb b/Formula/a/aws-cdk.rb` - formula = line.split("/").last.chomp(".rb\n") - formula = CoreTap.instance.formula_renames.fetch(formula, formula) - lost_bottles = 0 - when bottle_tag_sha_regex - # Example match: `- sha256 cellar: :any_skip_relocation, sonoma: "f0a4..."` - next if processed_formulae.include?(formula) + end + @sort = " (sorted by installs in the last 90 days; top 10,000 only)" - case line.chr - when "+" then lost_bottles -= 1 - when "-" then lost_bottles += 1 - end - when /^[+] +sha256.* all: / - # Example match: `+ sha256 cellar: :any_skip_relocation, all: "9e35..."` - lost_bottles -= 1 + all_formulae = Formula.all(eval_all: args.eval_all?) + end + + # Remove deprecated formulae as we do not care if they are unbottled + formulae = Array(formulae).reject(&:deprecated?) if formulae.present? + all_formulae = Array(all_formulae).reject(&:deprecated?) if all_formulae.present? + + [formulae, all_formulae, formula_installs] + end + + def deps_uses_from_formulae(all_formulae) + ohai "Populating dependency tree..." + + deps_hash = {} + uses_hash = {} + + all_formulae.each do |f| + deps = Dependency.expand(f, cache_key: "unbottled") do |_, dep| + Dependency.prune if dep.optional? + end.map(&:to_formula) + deps_hash[f.name] = deps + + deps.each do |dep| + uses_hash[dep.name] ||= [] + uses_hash[dep.name] << f end end + + [deps_hash, uses_hash] + end + + def output_total(formulae) + ohai "Unbottled :#{@bottle_tag} formulae" + unbottled_formulae = 0 + + formulae.each do |f| + next if f.bottle_specification.tag?(@bottle_tag) + + unbottled_formulae += 1 + end + + puts "#{unbottled_formulae}/#{formulae.length} remaining." + end + + def output_unbottled(formulae, deps_hash, noun, hash, any_named_args) + ohai ":#{@bottle_tag} bottle status#{@sort}" + any_found = T.let(false, T::Boolean) + + formulae.each do |f| + name = f.name.downcase + + if f.disabled? + puts "#{Tty.bold}#{Tty.green}#{name}#{Tty.reset}: formula disabled" if any_named_args + next + end + + requirements = f.recursive_requirements + if @bottle_tag.linux? + if requirements.any? { |r| r.is_a?(MacOSRequirement) && !r.version } + puts "#{Tty.bold}#{Tty.red}#{name}#{Tty.reset}: requires macOS" if any_named_args + next + end + elsif requirements.any?(LinuxRequirement) + puts "#{Tty.bold}#{Tty.red}#{name}#{Tty.reset}: requires Linux" if any_named_args + next + else + macos_version = @bottle_tag.to_macos_version + macos_satisfied = requirements.all? do |r| + case r + when MacOSRequirement + next true unless r.version_specified? + + macos_version.compare(r.comparator, r.version) + when XcodeRequirement + next true unless r.version + + Version.new(MacOS::Xcode.latest_version(macos: macos_version)) >= r.version + when ArchRequirement + r.arch == @bottle_tag.arch + else + true + end + end + unless macos_satisfied + puts "#{Tty.bold}#{Tty.red}#{name}#{Tty.reset}: doesn't support this macOS" if any_named_args + next + end + end + + if f.bottle_specification.tag?(@bottle_tag, no_older_versions: true) + puts "#{Tty.bold}#{Tty.green}#{name}#{Tty.reset}: already bottled" if any_named_args + next + end + + deps = Array(deps_hash[f.name]).reject do |dep| + dep.bottle_specification.tag?(@bottle_tag, no_older_versions: true) + end + + if deps.blank? + count = " (#{hash[f.name]} #{noun})" if noun + puts "#{Tty.bold}#{Tty.green}#{name}#{Tty.reset}#{count}: ready to bottle" + next + end + + any_found ||= true + count = " (#{hash[f.name]} #{noun})" if noun + puts "#{Tty.bold}#{Tty.yellow}#{name}#{Tty.reset}#{count}: unbottled deps: #{deps.join(" ")}" + end + return if any_found + return if any_named_args + + puts "No unbottled dependencies found!" + end + + def output_lost_bottles + ohai ":#{@bottle_tag} lost bottles" + + bottle_tag_regex_fragment = " +sha256.* #{@bottle_tag}: " + + # $ git log --patch --no-ext-diff -G'^ +sha256.* sonoma:' --since=@{'1 week ago'} + git_log = %w[git log --patch --no-ext-diff] + git_log << "-G^#{bottle_tag_regex_fragment}" + git_log << "--since=@{'1 week ago'}" + + bottle_tag_sha_regex = /^[+-]#{bottle_tag_regex_fragment}/ + + processed_formulae = Set.new + commit = T.let(nil, T.nilable(String)) + formula = T.let(nil, T.nilable(String)) + lost_bottles = 0 + + CoreTap.instance.path.cd do + Utils.safe_popen_read(*git_log) do |io| + io.each_line do |line| + case line + when /^commit [0-9a-f]{40}$/ + # Example match: `commit 7289b409b96a752540befef1a56b8a818baf1db7` + if commit && formula && lost_bottles.positive? && processed_formulae.exclude?(formula) + puts "#{commit}: bottle lost for #{formula}" + end + processed_formulae << formula + commit = line.split.last + formula = nil + when %r{^diff --git a/Formula/} + # Example match: `diff --git a/Formula/a/aws-cdk.rb b/Formula/a/aws-cdk.rb` + formula = line.split("/").last.chomp(".rb\n") + formula = CoreTap.instance.formula_renames.fetch(formula, formula) + lost_bottles = 0 + when bottle_tag_sha_regex + # Example match: `- sha256 cellar: :any_skip_relocation, sonoma: "f0a4..."` + next if processed_formulae.include?(formula) + + case line.chr + when "+" then lost_bottles -= 1 + when "-" then lost_bottles += 1 + end + when /^[+] +sha256.* all: / + # Example match: `+ sha256 cellar: :any_skip_relocation, all: "9e35..."` + lost_bottles -= 1 + end + end + end + end + + return if !commit || !formula || !lost_bottles.positive? || processed_formulae.include?(formula) + + puts "#{commit}: bottle lost for #{formula}" end end - - return if !commit || !formula || !lost_bottles.positive? || processed_formulae.include?(formula) - - puts "#{commit}: bottle lost for #{formula}" end end diff --git a/Library/Homebrew/test/dev-cmd/typecheck_spec.rb b/Library/Homebrew/test/dev-cmd/typecheck_spec.rb index 1838b4bda1..dec2de42d2 100644 --- a/Library/Homebrew/test/dev-cmd/typecheck_spec.rb +++ b/Library/Homebrew/test/dev-cmd/typecheck_spec.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true require "cmd/shared_examples/args_parse" +require "dev-cmd/typecheck" -RSpec.describe "brew typecheck" do +RSpec.describe Homebrew::DevCmd::Typecheck do it_behaves_like "parseable arguments" end diff --git a/Library/Homebrew/test/dev-cmd/unbottled_spec.rb b/Library/Homebrew/test/dev-cmd/unbottled_spec.rb index 508574033e..f209b17ca6 100644 --- a/Library/Homebrew/test/dev-cmd/unbottled_spec.rb +++ b/Library/Homebrew/test/dev-cmd/unbottled_spec.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true require "cmd/shared_examples/args_parse" +require "dev-cmd/unbottled" -RSpec.describe "brew unbottled" do +RSpec.describe Homebrew::DevCmd::Unbottled do it_behaves_like "parseable arguments" end