Enable types in dev-cmd

This commit is contained in:
Douglas Eichelberger 2023-03-13 18:31:26 -07:00
parent d993167fae
commit f4c9a96c70
12 changed files with 118 additions and 120 deletions

View File

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

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "formula" require "formula"
@ -22,10 +22,8 @@ require "tap_auditor"
module Homebrew module Homebrew
extend T::Sig extend T::Sig
module_function
sig { returns(CLI::Parser) } sig { returns(CLI::Parser) }
def audit_args def self.audit_args
Homebrew::CLI::Parser.new do Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Check <formula> for Homebrew coding style violations. This should be run before Check <formula> for Homebrew coding style violations. This should be run before
@ -103,7 +101,7 @@ module Homebrew
end end
sig { void } sig { void }
def audit def self.audit
args = audit_args.parse args = audit_args.parse
Homebrew.auditing = true Homebrew.auditing = true
@ -117,7 +115,7 @@ module Homebrew
strict = new_formula || args.strict? strict = new_formula || args.strict?
online = new_formula || args.online? online = new_formula || args.online?
skip_style = args.skip_style? || args.no_named? || args.tap skip_style = args.skip_style? || args.no_named? || args.tap
no_named_args = false no_named_args = T.let(false, T::Boolean)
ENV.activate_extensions! ENV.activate_extensions!
ENV.setup_build_environment ENV.setup_build_environment
@ -195,7 +193,7 @@ module Homebrew
# load licenses # load licenses
spdx_license_data = SPDX.license_data spdx_license_data = SPDX.license_data
spdx_exception_data = SPDX.exception_data spdx_exception_data = SPDX.exception_data
new_formula_problem_lines = [] new_formula_problem_lines = T.let([], T::Array[String])
formula_results = audit_formulae.sort.to_h do |f| formula_results = audit_formulae.sort.to_h do |f|
only = only_cops ? ["style"] : args.only only = only_cops ? ["style"] : args.only
options = { options = {
@ -320,16 +318,16 @@ module Homebrew
end end
end end
def format_problem_lines(problems) def self.format_problem_lines(problems)
problems.uniq problems.uniq
.map { |message:, location:| format_problem(message, location) } .map { |message:, location:| format_problem(message, location) }
end end
def format_problem(message, location) def self.format_problem(message, location)
"* #{location&.to_s&.dup&.concat(": ")}#{message.chomp.gsub("\n", "\n ")}" "* #{location&.to_s&.dup&.concat(": ")}#{message.chomp.gsub("\n", "\n ")}"
end end
def without_api(&block) def self.without_api(&block)
return yield if Homebrew::EnvConfig.no_install_from_api? return yield if Homebrew::EnvConfig.no_install_from_api?
with_env(HOMEBREW_NO_INSTALL_FROM_API: "1", HOMEBREW_AUTOMATICALLY_SET_NO_INSTALL_FROM_API: "1", &block) with_env(HOMEBREW_NO_INSTALL_FROM_API: "1", HOMEBREW_AUTOMATICALLY_SET_NO_INSTALL_FROM_API: "1", &block)

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "formula" require "formula"
@ -38,10 +38,8 @@ ALLOWABLE_HOMEBREW_REPOSITORY_LINKS = [
module Homebrew module Homebrew
extend T::Sig extend T::Sig
module_function
sig { returns(CLI::Parser) } sig { returns(CLI::Parser) }
def bottle_args def self.bottle_args
Homebrew::CLI::Parser.new do Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Generate a bottle (binary package) from a formula that was installed with Generate a bottle (binary package) from a formula that was installed with
@ -94,7 +92,7 @@ module Homebrew
end end
end end
def bottle def self.bottle
args = bottle_args.parse args = bottle_args.parse
if args.merge? if args.merge?
@ -107,7 +105,7 @@ module Homebrew
end end
end end
def keg_contain?(string, keg, ignores, formula_and_runtime_deps_names = nil, args:) def self.keg_contain?(string, keg, ignores, formula_and_runtime_deps_names = nil, args:)
@put_string_exists_header, @put_filenames = nil @put_string_exists_header, @put_filenames = nil
print_filename = lambda do |str, filename| print_filename = lambda do |str, filename|
@ -124,7 +122,7 @@ module Homebrew
@put_filenames << filename @put_filenames << filename
end end
result = false result = T.let(false, T::Boolean)
keg.each_unique_file_matching(string) do |file| keg.each_unique_file_matching(string) do |file|
next if Metafiles::EXTENSIONS.include?(file.extname) # Skip document files. next if Metafiles::EXTENSIONS.include?(file.extname) # Skip document files.
@ -157,7 +155,7 @@ module Homebrew
keg_contain_absolute_symlink_starting_with?(string, keg, args: args) || result keg_contain_absolute_symlink_starting_with?(string, keg, args: args) || result
end end
def keg_contain_absolute_symlink_starting_with?(string, keg, args:) def self.keg_contain_absolute_symlink_starting_with?(string, keg, args:)
absolute_symlinks_start_with_string = [] absolute_symlinks_start_with_string = []
keg.find do |pn| keg.find do |pn|
next if !pn.symlink? || !(link = pn.readlink).absolute? next if !pn.symlink? || !(link = pn.readlink).absolute?
@ -175,7 +173,7 @@ module Homebrew
!absolute_symlinks_start_with_string.empty? !absolute_symlinks_start_with_string.empty?
end end
def cellar_parameter_needed?(cellar) def self.cellar_parameter_needed?(cellar)
default_cellars = [ default_cellars = [
Homebrew::DEFAULT_MACOS_CELLAR, Homebrew::DEFAULT_MACOS_CELLAR,
Homebrew::DEFAULT_MACOS_ARM_CELLAR, Homebrew::DEFAULT_MACOS_ARM_CELLAR,
@ -184,7 +182,7 @@ 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) def self.generate_sha256_line(tag, digest, cellar, tag_column, digest_column)
line = "sha256 " line = "sha256 "
tag_column += line.length tag_column += line.length
digest_column += line.length digest_column += line.length
@ -199,7 +197,7 @@ module Homebrew
%Q(#{line}"#{digest}") %Q(#{line}"#{digest}")
end end
def bottle_output(bottle, root_url_using) def self.bottle_output(bottle, root_url_using)
cellars = bottle.checksums.map do |checksum| cellars = bottle.checksums.map do |checksum|
cellar = checksum["cellar"] cellar = checksum["cellar"]
next unless cellar_parameter_needed? cellar next unless cellar_parameter_needed? cellar
@ -227,13 +225,13 @@ module Homebrew
erb.result(erb_binding).gsub(/^\s*$\n/, "") erb.result(erb_binding).gsub(/^\s*$\n/, "")
end end
def sudo_purge def self.sudo_purge
return unless ENV["HOMEBREW_BOTTLE_SUDO_PURGE"] return unless ENV["HOMEBREW_BOTTLE_SUDO_PURGE"]
system "/usr/bin/sudo", "--non-interactive", "/usr/sbin/purge" system "/usr/bin/sudo", "--non-interactive", "/usr/sbin/purge"
end end
def setup_tar_and_args!(args, mtime) def self.setup_tar_and_args!(args, mtime)
# Without --only-json-tab bottles are never reproducible # Without --only-json-tab bottles are never reproducible
default_tar_args = ["tar", [].freeze].freeze default_tar_args = ["tar", [].freeze].freeze
return default_tar_args unless args.only_json_tab? return default_tar_args unless args.only_json_tab?
@ -261,7 +259,7 @@ module Homebrew
["#{gnu_tar.opt_bin}/gtar", gnutar_args].freeze ["#{gnu_tar.opt_bin}/gtar", gnutar_args].freeze
end end
def formula_ignores(formula) def self.formula_ignores(formula)
ignores = [] ignores = []
cellar_regex = Regexp.escape(HOMEBREW_CELLAR) cellar_regex = Regexp.escape(HOMEBREW_CELLAR)
prefix_regex = Regexp.escape(HOMEBREW_PREFIX) prefix_regex = Regexp.escape(HOMEBREW_PREFIX)
@ -291,7 +289,7 @@ module Homebrew
ignores.compact ignores.compact
end end
def bottle_formula(formula, args:) def self.bottle_formula(formula, args:)
local_bottle_json = args.json? && formula.local_bottle_path.present? local_bottle_json = args.json? && formula.local_bottle_path.present?
unless local_bottle_json unless local_bottle_json
@ -425,7 +423,7 @@ module Homebrew
sudo_purge sudo_purge
# Set filename as it affects the tarball checksum. # Set filename as it affects the tarball checksum.
relocatable_tar_path = "#{formula}-bottle.tar" relocatable_tar_path = "#{formula}-bottle.tar"
mv tar_path, relocatable_tar_path mv T.must(tar_path), relocatable_tar_path
# Use gzip, faster to compress than bzip2, faster to uncompress than bzip2 # Use gzip, faster to compress than bzip2, faster to uncompress than bzip2
# or an uncompressed tarball (and more bandwidth friendly). # or an uncompressed tarball (and more bandwidth friendly).
Utils::Gzip.compress_with_options(relocatable_tar_path, Utils::Gzip.compress_with_options(relocatable_tar_path,
@ -572,13 +570,13 @@ module Homebrew
json_path.write(JSON.pretty_generate(json)) json_path.write(JSON.pretty_generate(json))
end end
def parse_json_files(filenames) def self.parse_json_files(filenames)
filenames.map do |filename| filenames.map do |filename|
JSON.parse(File.read(filename)) JSON.parse(File.read(filename))
end end
end end
def merge_json_files(json_files) def self.merge_json_files(json_files)
json_files.reduce({}) do |hash, json_file| json_files.reduce({}) do |hash, json_file|
json_file.each_value do |json_hash| json_file.each_value do |json_hash|
json_bottle = json_hash["bottle"] json_bottle = json_hash["bottle"]
@ -591,7 +589,7 @@ module Homebrew
end end
end end
def merge(args:) def self.merge(args:)
bottles_hash = merge_json_files(parse_json_files(args.named)) bottles_hash = merge_json_files(parse_json_files(args.named))
any_cellars = ["any", "any_skip_relocation"] any_cellars = ["any", "any_skip_relocation"]
@ -660,7 +658,7 @@ module Homebrew
end end
end end
all_bottle_hash = nil all_bottle_hash = T.let(nil, T.nilable(Hash))
bottle_hash["bottle"]["tags"].each do |tag, tag_hash| bottle_hash["bottle"]["tags"].each do |tag, tag_hash|
filename = Bottle::Filename.new( filename = Bottle::Filename.new(
formula_name, formula_name,
@ -745,7 +743,7 @@ module Homebrew
end end
end end
def merge_bottle_spec(old_keys, old_bottle_spec, new_bottle_hash) def self.merge_bottle_spec(old_keys, old_bottle_spec, new_bottle_hash)
mismatches = [] mismatches = []
checksums = [] checksums = []
@ -785,12 +783,12 @@ module Homebrew
[mismatches, checksums] [mismatches, checksums]
end end
def old_checksums(formula, formula_ast, bottle_hash, args:) def self.old_checksums(formula, formula_ast, bottle_hash, args:)
bottle_node = formula_ast.bottle_block bottle_node = formula_ast.bottle_block
return if bottle_node.nil? return if bottle_node.nil?
return [] unless args.keep_old? return [] unless args.keep_old?
old_keys = Utils::AST.body_children(bottle_node.body).map(&:method_name) old_keys = T.cast(Utils::AST.body_children(bottle_node.body), T::Array[RuboCop::AST::SendNode]).map(&:method_name)
old_bottle_spec = formula.bottle_specification old_bottle_spec = formula.bottle_specification
mismatches, checksums = merge_bottle_spec(old_keys, old_bottle_spec, bottle_hash["bottle"]) mismatches, checksums = merge_bottle_spec(old_keys, old_bottle_spec, bottle_hash["bottle"])
if mismatches.present? if mismatches.present?

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "cask" require "cask"
@ -158,7 +158,7 @@ module Homebrew
m = /^ +url "(.+?)"\n/m.match(old_contents) m = /^ +url "(.+?)"\n/m.match(old_contents)
odie "Could not find old URL in cask!" if m.nil? odie "Could not find old URL in cask!" if m.nil?
old_base_url = m.captures.first old_base_url = m.captures.fetch(0)
replacement_pairs << [ replacement_pairs << [
/#{Regexp.escape(old_base_url)}/, /#{Regexp.escape(old_base_url)}/,

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "cli/parser"
@ -6,10 +6,8 @@ require "cli/parser"
module Homebrew module Homebrew
extend T::Sig extend T::Sig
module_function
sig { returns(CLI::Parser) } sig { returns(CLI::Parser) }
def cat_args def self.cat_args
Homebrew::CLI::Parser.new do Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Display the source of a <formula> or <cask>. Display the source of a <formula> or <cask>.
@ -26,10 +24,10 @@ module Homebrew
end end
end end
def cat def self.cat
args = cat_args.parse args = cat_args.parse
cd HOMEBREW_REPOSITORY cd HOMEBREW_REPOSITORY do
pager = if Homebrew::EnvConfig.bat? pager = if Homebrew::EnvConfig.bat?
ENV["BAT_CONFIG_PATH"] = Homebrew::EnvConfig.bat_config_path ENV["BAT_CONFIG_PATH"] = Homebrew::EnvConfig.bat_config_path
ENV["BAT_THEME"] = Homebrew::EnvConfig.bat_theme ENV["BAT_THEME"] = Homebrew::EnvConfig.bat_theme
@ -62,4 +60,5 @@ module Homebrew
safe_system pager, *args.named.to_paths safe_system pager, *args.named.to_paths
end end
end
end end

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "cli/parser"
@ -8,29 +8,30 @@ require "software_spec"
require "tap" require "tap"
def with_monkey_patch def with_monkey_patch
# Since `method_defined?` is not a supported type guard, the use of `alias_method` below is not typesafe:
BottleSpecification.class_eval do BottleSpecification.class_eval do
alias_method :old_method_missing, :method_missing if method_defined?(:method_missing) T.unsafe(self).alias_method :old_method_missing, :method_missing if method_defined?(:method_missing)
define_method(:method_missing) do |*| define_method(:method_missing) do |*|
# do nothing # do nothing
end end
end end
Module.class_eval do Module.class_eval do
alias_method :old_method_missing, :method_missing if method_defined?(:method_missing) T.unsafe(self).alias_method :old_method_missing, :method_missing if method_defined?(:method_missing)
define_method(:method_missing) do |*| define_method(:method_missing) do |*|
# do nothing # do nothing
end end
end end
Resource.class_eval do Resource.class_eval do
alias_method :old_method_missing, :method_missing if method_defined?(:method_missing) T.unsafe(self).alias_method :old_method_missing, :method_missing if method_defined?(:method_missing)
define_method(:method_missing) do |*| define_method(:method_missing) do |*|
# do nothing # do nothing
end end
end end
DependencyCollector.class_eval do DependencyCollector.class_eval do
alias_method :old_parse_symbol_spec, :parse_symbol_spec if method_defined?(:parse_symbol_spec) T.unsafe(self).alias_method :old_parse_symbol_spec, :parse_symbol_spec if method_defined?(:parse_symbol_spec)
define_method(:parse_symbol_spec) do |*| define_method(:parse_symbol_spec) do |*|
# do nothing # do nothing
end end
@ -40,28 +41,28 @@ def with_monkey_patch
ensure ensure
BottleSpecification.class_eval do BottleSpecification.class_eval do
if method_defined?(:old_method_missing) if method_defined?(:old_method_missing)
alias_method :method_missing, :old_method_missing T.unsafe(self).alias_method :method_missing, :old_method_missing
undef :old_method_missing undef :old_method_missing
end end
end end
Module.class_eval do Module.class_eval do
if method_defined?(:old_method_missing) if method_defined?(:old_method_missing)
alias_method :method_missing, :old_method_missing T.unsafe(self).alias_method :method_missing, :old_method_missing
undef :old_method_missing undef :old_method_missing
end end
end end
Resource.class_eval do Resource.class_eval do
if method_defined?(:old_method_missing) if method_defined?(:old_method_missing)
alias_method :method_missing, :old_method_missing T.unsafe(self).alias_method :method_missing, :old_method_missing
undef :old_method_missing undef :old_method_missing
end end
end end
DependencyCollector.class_eval do DependencyCollector.class_eval do
if method_defined?(:old_parse_symbol_spec) if method_defined?(:old_parse_symbol_spec)
alias_method :parse_symbol_spec, :old_parse_symbol_spec T.unsafe(self).alias_method :parse_symbol_spec, :old_parse_symbol_spec
undef :old_parse_symbol_spec undef :old_parse_symbol_spec
end end
end end
@ -70,12 +71,10 @@ end
module Homebrew module Homebrew
extend T::Sig extend T::Sig
module_function
BOTTLE_BLOCK_REGEX = / bottle (?:do.+?end|:[a-z]+)\n\n/m.freeze BOTTLE_BLOCK_REGEX = / bottle (?:do.+?end|:[a-z]+)\n\n/m.freeze
sig { returns(CLI::Parser) } sig { returns(CLI::Parser) }
def extract_args def self.extract_args
Homebrew::CLI::Parser.new do Homebrew::CLI::Parser.new do
usage_banner "`extract` [`--version=`] [`--force`] <formula> <tap>" usage_banner "`extract` [`--version=`] [`--force`] <formula> <tap>"
description <<~EOS description <<~EOS
@ -95,7 +94,7 @@ module Homebrew
end end
end end
def extract def self.extract
args = extract_args.parse args = extract_args.parse
if (match = args.named.first.match(HOMEBREW_TAP_FORMULA_REGEX)) if (match = args.named.first.match(HOMEBREW_TAP_FORMULA_REGEX))
@ -126,8 +125,8 @@ module Homebrew
ohai "Searching repository history" ohai "Searching repository history"
version = args.version version = args.version
version_segments = Gem::Version.new(version).segments if Gem::Version.correct?(version) version_segments = Gem::Version.new(version).segments if Gem::Version.correct?(version)
rev = nil rev = T.let(nil, T.nilable(String))
test_formula = nil test_formula = T.let(nil, T.nilable(Formula))
result = "" result = ""
loop do loop do
rev = rev.nil? ? "HEAD" : "#{rev}~1" rev = rev.nil? ? "HEAD" : "#{rev}~1"
@ -166,7 +165,7 @@ module Homebrew
else else
# Search in the root directory of <repo> as well as recursively in all of its subdirectories # Search in the root directory of <repo> as well as recursively in all of its subdirectories
files = Dir[repo/"{,**/}"].map do |dir| files = Dir[repo/"{,**/}"].map do |dir|
Pathname.glob(["#{dir}/#{name}.rb"]).find(&:file?) Pathname.glob("#{dir}/#{name}.rb").find(&:file?)
end.compact end.compact
if files.empty? if files.empty?
@ -174,11 +173,11 @@ module Homebrew
rev, (path,) = Utils::Git.last_revision_commit_of_files(repo, pattern) rev, (path,) = Utils::Git.last_revision_commit_of_files(repo, pattern)
odie "Could not find #{name}! The formula or version may not have existed." if rev.nil? odie "Could not find #{name}! The formula or version may not have existed." if rev.nil?
file = repo/path file = repo/path
version = formula_at_revision(repo, name, file, rev).version version = T.must(formula_at_revision(repo, name, file, rev)).version
result = Utils::Git.last_revision_of_file(repo, file) result = Utils::Git.last_revision_of_file(repo, file)
else else
file = files.first.realpath file = files.fetch(0).realpath
rev = "HEAD" rev = T.let("HEAD", T.nilable(String))
version = Formulary.factory(file).version version = Formulary.factory(file).version
result = File.read(file) result = File.read(file)
end end
@ -214,7 +213,8 @@ module Homebrew
end end
# @private # @private
def formula_at_revision(repo, name, file, rev) sig { params(repo: Pathname, name: String, file: Pathname, rev: String).returns(T.nilable(Formula)) }
def self.formula_at_revision(repo, name, file, rev)
return if rev.empty? return if rev.empty?
contents = Utils::Git.last_revision_of_file(repo, file, before_commit: rev) contents = Utils::Git.last_revision_of_file(repo, file, before_commit: rev)

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "cli/parser" require "cli/parser"
@ -51,7 +51,7 @@ module Homebrew
url_match = arg.match HOMEBREW_PULL_OR_COMMIT_URL_REGEX url_match = arg.match HOMEBREW_PULL_OR_COMMIT_URL_REGEX
_, user, repo, issue = *url_match _, user, repo, issue = *url_match
odie "Not a GitHub pull request: #{arg}" unless issue odie "Not a GitHub pull request: #{arg}" unless issue
if args.tap.present? && !"#{user}/#{repo}".casecmp(tap.full_name).zero? if args.tap.present? && !T.must("#{user}/#{repo}".casecmp(tap.full_name)).zero?
odie "Pull request URL is for #{user}/#{repo} but `--tap=#{tap.full_name}` was specified!" odie "Pull request URL is for #{user}/#{repo} but `--tap=#{tap.full_name}` was specified!"
end end

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "download_strategy" require "download_strategy"
@ -10,10 +10,8 @@ require "formula"
module Homebrew module Homebrew
extend T::Sig extend T::Sig
module_function
sig { returns(CLI::Parser) } sig { returns(CLI::Parser) }
def pr_pull_args def self.pr_pull_args
Homebrew::CLI::Parser.new do Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Download and publish bottles, and apply the bottle commit from a Download and publish bottles, and apply the bottle commit from a
@ -69,7 +67,7 @@ module Homebrew
end end
# Separates a commit message into subject, body, and trailers. # Separates a commit message into subject, body, and trailers.
def separate_commit_message(message) def self.separate_commit_message(message)
subject = message.lines.first.strip subject = message.lines.first.strip
# Skip the subject and separate lines that look like trailers (e.g. "Co-authored-by") # Skip the subject and separate lines that look like trailers (e.g. "Co-authored-by")
@ -82,7 +80,7 @@ module Homebrew
[subject, body, trailers] [subject, body, trailers]
end end
def signoff!(path, pr: nil, dry_run: false) def self.signoff!(path, pr: nil, dry_run: false)
subject, body, trailers = separate_commit_message(path.git_commit_message) subject, body, trailers = separate_commit_message(path.git_commit_message)
if pr if pr
@ -108,7 +106,7 @@ module Homebrew
end end
end end
def get_package(tap, subject_name, subject_path, content) def self.get_package(tap, subject_name, subject_path, content)
if subject_path.dirname == tap.cask_dir if subject_path.dirname == tap.cask_dir
cask = begin cask = begin
Cask::CaskLoader.load(content.dup) Cask::CaskLoader.load(content.dup)
@ -125,7 +123,7 @@ module Homebrew
end end
end end
def determine_bump_subject(old_contents, new_contents, subject_path, reason: nil) def self.determine_bump_subject(old_contents, new_contents, subject_path, reason: nil)
subject_path = Pathname(subject_path) subject_path = Pathname(subject_path)
tap = Tap.from_path(subject_path) tap = Tap.from_path(subject_path)
subject_name = subject_path.basename.to_s.chomp(".rb") subject_name = subject_path.basename.to_s.chomp(".rb")
@ -153,7 +151,7 @@ module Homebrew
# Cherry picks a single commit that modifies a single file. # Cherry picks a single commit that modifies a single file.
# Potentially rewords this commit using {determine_bump_subject}. # Potentially rewords this commit using {determine_bump_subject}.
def reword_package_commit(commit, file, reason: "", verbose: false, resolve: false, path: ".") def self.reword_package_commit(commit, file, reason: "", verbose: false, resolve: false, path: ".")
package_file = Pathname.new(path) / file package_file = Pathname.new(path) / file
package_name = package_file.basename.to_s.chomp(".rb") package_name = package_file.basename.to_s.chomp(".rb")
@ -178,7 +176,7 @@ module Homebrew
# Cherry picks multiple commits that each modify a single file. # Cherry picks multiple commits that each modify a single file.
# Words the commit according to {determine_bump_subject} with the body # Words the commit according to {determine_bump_subject} with the body
# corresponding to all the original commit messages combined. # corresponding to all the original commit messages combined.
def squash_package_commits(commits, file, reason: "", verbose: false, resolve: false, path: ".") def self.squash_package_commits(commits, file, reason: "", verbose: false, resolve: false, path: ".")
odebug "Squashing #{file}: #{commits.join " "}" odebug "Squashing #{file}: #{commits.join " "}"
# Format commit messages into something similar to `git fmt-merge-message`. # Format commit messages into something similar to `git fmt-merge-message`.
@ -223,7 +221,7 @@ module Homebrew
ohai bump_subject ohai bump_subject
end end
def autosquash!(original_commit, tap:, reason: "", verbose: false, resolve: false) def self.autosquash!(original_commit, tap:, reason: "", verbose: false, resolve: false)
original_head = tap.path.git_head original_head = tap.path.git_head
commits = Utils.safe_popen_read("git", "-C", tap.path, "rev-list", commits = Utils.safe_popen_read("git", "-C", tap.path, "rev-list",
@ -257,7 +255,7 @@ module Homebrew
# Iterate over every commit in the pull request series, but if we have to squash # Iterate over every commit in the pull request series, but if we have to squash
# multiple commits into one, ensure that we skip over commits we've already squashed. # multiple commits into one, ensure that we skip over commits we've already squashed.
processed_commits = [] processed_commits = T.let([], T::Array[String])
commits.each do |commit| commits.each do |commit|
next if processed_commits.include? commit next if processed_commits.include? commit
@ -288,7 +286,7 @@ module Homebrew
raise raise
end end
def cherry_pick_pr!(user, repo, pr, args:, path: ".") def self.cherry_pick_pr!(user, repo, pr, args:, path: ".")
if args.dry_run? if args.dry_run?
puts <<~EOS puts <<~EOS
git fetch --force origin +refs/pull/#{pr}/head git fetch --force origin +refs/pull/#{pr}/head
@ -304,7 +302,7 @@ module Homebrew
Utils::Git.cherry_pick!(path, "--ff", "--allow-empty", *commits, verbose: args.verbose?, resolve: args.resolve?) Utils::Git.cherry_pick!(path, "--ff", "--allow-empty", *commits, verbose: args.verbose?, resolve: args.resolve?)
end end
def formulae_need_bottles?(tap, original_commit, user, repo, pr, args:) def self.formulae_need_bottles?(tap, original_commit, user, repo, pr, args:)
return if args.dry_run? return if args.dry_run?
labels = GitHub.pull_request_labels(user, repo, pr) labels = GitHub.pull_request_labels(user, repo, pr)
@ -316,7 +314,7 @@ module Homebrew
end end
end end
def changed_packages(tap, original_commit) def self.changed_packages(tap, original_commit)
formulae = Utils.popen_read("git", "-C", tap.path, "diff-tree", formulae = Utils.popen_read("git", "-C", tap.path, "diff-tree",
"-r", "--name-only", "--diff-filter=AM", "-r", "--name-only", "--diff-filter=AM",
original_commit, "HEAD", "--", tap.formula_dir) original_commit, "HEAD", "--", tap.formula_dir)
@ -352,7 +350,7 @@ module Homebrew
formulae + casks formulae + casks
end end
def download_artifact(url, dir, pr) def self.download_artifact(url, dir, pr)
odie "Credentials must be set to access the Artifacts API" if GitHub::API.credentials_type == :none odie "Credentials must be set to access the Artifacts API" if GitHub::API.credentials_type == :none
token = GitHub::API.credentials token = GitHub::API.credentials
@ -368,7 +366,7 @@ module Homebrew
end end
end end
def pr_check_conflicts(repo, pr) def self.pr_check_conflicts(repo, pr)
long_build_pr_files = GitHub.issues( long_build_pr_files = GitHub.issues(
repo: repo, state: "open", labels: "no long build conflict", repo: repo, state: "open", labels: "no long build conflict",
).each_with_object({}) do |long_build_pr, hash| ).each_with_object({}) do |long_build_pr, hash|
@ -415,7 +413,7 @@ module Homebrew
EOS EOS
end end
def pr_pull def self.pr_pull
args = pr_pull_args.parse args = pr_pull_args.parse
# Needed when extracting the CI artifact. # Needed when extracting the CI artifact.

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "extend/ENV" require "extend/ENV"
@ -38,7 +38,7 @@ module Homebrew
ENV.setup_build_environment ENV.setup_build_environment
if superenv?(args.env) if superenv?(args.env)
# superenv stopped adding brew's bin but generally users will want it # superenv stopped adding brew's bin but generally users will want it
ENV["PATH"] = PATH.new(ENV.fetch("PATH")).insert(1, HOMEBREW_PREFIX/"bin") ENV["PATH"] = PATH.new(ENV.fetch("PATH")).insert(1, HOMEBREW_PREFIX/"bin").to_s
end end
ENV["VERBOSE"] = "1" if args.verbose? ENV["VERBOSE"] = "1" if args.verbose?

View File

@ -1,4 +1,4 @@
# typed: false # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "tap" require "tap"
@ -7,10 +7,8 @@ require "cli/parser"
module Homebrew module Homebrew
extend T::Sig extend T::Sig
module_function
sig { returns(CLI::Parser) } sig { returns(CLI::Parser) }
def tap_new_args def self.tap_new_args
Homebrew::CLI::Parser.new do Homebrew::CLI::Parser.new do
usage_banner "`tap-new` [<options>] <user>`/`<repo>" usage_banner "`tap-new` [<options>] <user>`/`<repo>"
description <<~EOS description <<~EOS
@ -31,7 +29,7 @@ module Homebrew
end end
end end
def tap_new def self.tap_new
args = tap_new_args.parse args = tap_new_args.parse
label = args.pull_label || "pr-pull" label = args.pull_label || "pr-pull"
@ -176,7 +174,7 @@ module Homebrew
EOS EOS
end end
def write_path(tap, filename, content) def self.write_path(tap, filename, content)
path = tap.path/filename path = tap.path/filename
tap.path.mkpath tap.path.mkpath
odie "#{path} already exists" if path.exist? odie "#{path} already exists" if path.exist?

View File

@ -79,6 +79,7 @@ module Kernel
Homebrew.failed = true Homebrew.failed = true
end end
sig { params(error: T.any(String, Exception)).returns(T.noreturn) }
def odie(error) def odie(error)
onoe error onoe error
exit 1 exit 1

View File

@ -7,6 +7,8 @@ module Utils
# @see GitRepositoryExtension # @see GitRepositoryExtension
# @api private # @api private
module Git module Git
extend T::Sig
module_function module_function
def available? def available?
@ -76,6 +78,10 @@ module Utils
[rev, paths] [rev, paths]
end end
sig {
params(repo: T.any(Pathname, String), file: T.any(Pathname, String), before_commit: T.nilable(String))
.returns(String)
}
def last_revision_of_file(repo, file, before_commit: nil) def last_revision_of_file(repo, file, before_commit: nil)
relative_file = Pathname(file).relative_path_from(repo) relative_file = Pathname(file).relative_path_from(repo)
commit_hash = last_revision_commit_of_file(repo, relative_file, before_commit: before_commit) commit_hash = last_revision_commit_of_file(repo, relative_file, before_commit: before_commit)