Merge pull request #16921 from Homebrew/ported-cmds
Convert some dev commands to use AbstractCommand
This commit is contained in:
commit
0ac23c0690
@ -16,21 +16,21 @@ module Homebrew
|
|||||||
abstract!
|
abstract!
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
sig { returns(T.nilable(CLI::Parser)) }
|
|
||||||
attr_reader :parser
|
|
||||||
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def command_name = T.must(name).split("::").fetch(-1).downcase
|
def command_name = Utils.underscore(T.must(name).split("::").fetch(-1)).tr("_", "-")
|
||||||
|
|
||||||
# @return the AbstractCommand subclass associated with the brew CLI command name.
|
# @return the AbstractCommand subclass associated with the brew CLI command name.
|
||||||
sig { params(name: String).returns(T.nilable(T.class_of(AbstractCommand))) }
|
sig { params(name: String).returns(T.nilable(T.class_of(AbstractCommand))) }
|
||||||
def command(name) = subclasses.find { _1.command_name == name }
|
def command(name) = subclasses.find { _1.command_name == name }
|
||||||
|
|
||||||
|
sig { returns(CLI::Parser) }
|
||||||
|
def parser = CLI::Parser.new(self, &@parser_block)
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
sig { params(block: T.proc.bind(CLI::Parser).void).void }
|
sig { params(block: T.proc.bind(CLI::Parser).void).void }
|
||||||
def cmd_args(&block)
|
def cmd_args(&block)
|
||||||
@parser = T.let(CLI::Parser.new(&block), T.nilable(CLI::Parser))
|
@parser_block = T.let(block, T.nilable(T.proc.void))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -39,10 +39,7 @@ module Homebrew
|
|||||||
|
|
||||||
sig { params(argv: T::Array[String]).void }
|
sig { params(argv: T::Array[String]).void }
|
||||||
def initialize(argv = ARGV.freeze)
|
def initialize(argv = ARGV.freeze)
|
||||||
parser = self.class.parser
|
@args = T.let(self.class.parser.parse(argv), CLI::Args)
|
||||||
raise "Commands must include a `cmd_args` block" if parser.nil?
|
|
||||||
|
|
||||||
@args = T.let(parser.parse(argv), CLI::Args)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { abstract.void }
|
sig { abstract.void }
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# typed: true
|
# typed: true
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "abstract_command"
|
||||||
require "env_config"
|
require "env_config"
|
||||||
require "cask/config"
|
require "cask/config"
|
||||||
require "cli/args"
|
require "cli/args"
|
||||||
@ -19,9 +20,18 @@ module Homebrew
|
|||||||
|
|
||||||
def self.from_cmd_path(cmd_path)
|
def self.from_cmd_path(cmd_path)
|
||||||
cmd_args_method_name = Commands.args_method_name(cmd_path)
|
cmd_args_method_name = Commands.args_method_name(cmd_path)
|
||||||
|
cmd_name = cmd_args_method_name.to_s.delete_suffix("_args").tr("_", "-")
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Homebrew.send(cmd_args_method_name) if require?(cmd_path)
|
if require?(cmd_path)
|
||||||
|
cmd = Homebrew::AbstractCommand.command(cmd_name)
|
||||||
|
if cmd
|
||||||
|
cmd.parser
|
||||||
|
else
|
||||||
|
# FIXME: remove once commands are all subclasses of `AbstractCommand`:
|
||||||
|
Homebrew.send(cmd_args_method_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
rescue NoMethodError => e
|
rescue NoMethodError => e
|
||||||
raise if e.name.to_sym != cmd_args_method_name
|
raise if e.name.to_sym != cmd_args_method_name
|
||||||
|
|
||||||
@ -109,8 +119,10 @@ module Homebrew
|
|||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(block: T.nilable(T.proc.bind(Parser).void)).void }
|
sig {
|
||||||
def initialize(&block)
|
params(cmd: T.nilable(T.class_of(Homebrew::AbstractCommand)), block: T.nilable(T.proc.bind(Parser).void)).void
|
||||||
|
}
|
||||||
|
def initialize(cmd = nil, &block)
|
||||||
@parser = OptionParser.new
|
@parser = OptionParser.new
|
||||||
|
|
||||||
@parser.summary_indent = " " * 2
|
@parser.summary_indent = " " * 2
|
||||||
@ -123,12 +135,18 @@ module Homebrew
|
|||||||
|
|
||||||
@args = Homebrew::CLI::Args.new
|
@args = Homebrew::CLI::Args.new
|
||||||
|
|
||||||
|
if cmd
|
||||||
|
@command_name = cmd.command_name
|
||||||
|
@is_dev_cmd = cmd.name&.start_with?("Homebrew::DevCmd")
|
||||||
|
else
|
||||||
|
# FIXME: remove once commands are all subclasses of `AbstractCommand`:
|
||||||
# Filter out Sorbet runtime type checking method calls.
|
# Filter out Sorbet runtime type checking method calls.
|
||||||
cmd_location = T.must(caller_locations).select do |location|
|
cmd_location = T.must(caller_locations).select do |location|
|
||||||
T.must(location.path).exclude?("/gems/sorbet-runtime-")
|
T.must(location.path).exclude?("/gems/sorbet-runtime-")
|
||||||
end.fetch(1)
|
end.fetch(1)
|
||||||
@command_name = T.must(cmd_location.label).chomp("_args").tr("_", "-")
|
@command_name = T.must(cmd_location.label).chomp("_args").tr("_", "-")
|
||||||
@is_dev_cmd = T.must(cmd_location.absolute_path).start_with?(Commands::HOMEBREW_DEV_CMD_PATH)
|
@is_dev_cmd = T.must(cmd_location.absolute_path).start_with?(Commands::HOMEBREW_DEV_CMD_PATH)
|
||||||
|
end
|
||||||
|
|
||||||
@constraints = []
|
@constraints = []
|
||||||
@conflicts = []
|
@conflicts = []
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# typed: true
|
# typed: true
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "abstract_command"
|
||||||
require "formula"
|
require "formula"
|
||||||
require "formula_versions"
|
require "formula_versions"
|
||||||
require "utils/curl"
|
require "utils/curl"
|
||||||
@ -20,9 +21,9 @@ require "formula_auditor"
|
|||||||
require "tap_auditor"
|
require "tap_auditor"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
sig { returns(CLI::Parser) }
|
module DevCmd
|
||||||
def self.audit_args
|
class Audit < AbstractCommand
|
||||||
Homebrew::CLI::Parser.new do
|
cmd_args 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
|
||||||
submitting a new formula or cask. If no <formula>|<cask> are provided, check all
|
submitting a new formula or cask. If no <formula>|<cask> are provided, check all
|
||||||
@ -102,12 +103,9 @@ module Homebrew
|
|||||||
|
|
||||||
named_args [:formula, :cask], without_api: true
|
named_args [:formula, :cask], without_api: true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
sig { void }
|
|
||||||
def self.audit
|
|
||||||
args = audit_args.parse
|
|
||||||
|
|
||||||
|
sig { override.void }
|
||||||
|
def run
|
||||||
new_cask = args.new? || args.new_cask?
|
new_cask = args.new? || args.new_cask?
|
||||||
new_formula = args.new? || args.new_formula?
|
new_formula = args.new? || args.new_formula?
|
||||||
|
|
||||||
@ -116,7 +114,7 @@ module Homebrew
|
|||||||
os_arch_combinations = args.os_arch_combinations
|
os_arch_combinations = args.os_arch_combinations
|
||||||
|
|
||||||
Homebrew.auditing = true
|
Homebrew.auditing = true
|
||||||
inject_dump_stats!(FormulaAuditor, /^audit_/) if args.audit_debug?
|
Homebrew.inject_dump_stats!(FormulaAuditor, /^audit_/) if args.audit_debug?
|
||||||
|
|
||||||
strict = new_formula || args.strict?
|
strict = new_formula || args.strict?
|
||||||
online = new_formula || args.online?
|
online = new_formula || args.online?
|
||||||
@ -129,7 +127,7 @@ module Homebrew
|
|||||||
|
|
||||||
audit_formulae, audit_casks = Homebrew.with_no_api_env do # audit requires full Ruby source
|
audit_formulae, audit_casks = Homebrew.with_no_api_env do # audit requires full Ruby source
|
||||||
if args.tap
|
if args.tap
|
||||||
Tap.fetch(args.tap).then do |tap|
|
Tap.fetch(T.must(args.tap)).then do |tap|
|
||||||
[
|
[
|
||||||
tap.formula_files.map { |path| Formulary.factory(path) },
|
tap.formula_files.map { |path| Formulary.factory(path) },
|
||||||
tap.cask_files.map { |path| Cask::CaskLoader.load(path) },
|
tap.cask_files.map { |path| Cask::CaskLoader.load(path) },
|
||||||
@ -228,8 +226,8 @@ module Homebrew
|
|||||||
|
|
||||||
audit_proc = proc { FormulaAuditor.new(Formulary.factory(path), **options).tap(&:audit) }
|
audit_proc = proc { FormulaAuditor.new(Formulary.factory(path), **options).tap(&:audit) }
|
||||||
|
|
||||||
# Audit requires full Ruby source so disable API.
|
# Audit requires full Ruby source so disable API. We shouldn't do this for taps however so that we
|
||||||
# We shouldn't do this for taps however so that we don't unnecessarily require a full Homebrew/core clone.
|
# don't unnecessarily require a full Homebrew/core clone.
|
||||||
fa = if f.core_formula?
|
fa = if f.core_formula?
|
||||||
Homebrew.with_no_api_env(&audit_proc)
|
Homebrew.with_no_api_env(&audit_proc)
|
||||||
else
|
else
|
||||||
@ -278,9 +276,9 @@ module Homebrew
|
|||||||
problems[[cask.full_name, path]] = errors if errors.any?
|
problems[[cask.full_name, path]] = errors if errors.any?
|
||||||
end
|
end
|
||||||
|
|
||||||
print_problems(tap_problems, display_filename: args.display_filename?)
|
print_problems(tap_problems)
|
||||||
print_problems(formula_problems, display_filename: args.display_filename?)
|
print_problems(formula_problems)
|
||||||
print_problems(cask_problems, display_filename: args.display_filename?)
|
print_problems(cask_problems)
|
||||||
|
|
||||||
tap_count = tap_problems.keys.count
|
tap_count = tap_problems.keys.count
|
||||||
formula_count = formula_problems.keys.count
|
formula_count = formula_problems.keys.count
|
||||||
@ -309,7 +307,8 @@ module Homebrew
|
|||||||
errors_summary += " detected"
|
errors_summary += " detected"
|
||||||
|
|
||||||
if corrected_problem_count.positive?
|
if corrected_problem_count.positive?
|
||||||
errors_summary += ", #{Utils.pluralize("problem", corrected_problem_count, include_count: true)} corrected"
|
errors_summary +=
|
||||||
|
", #{Utils.pluralize("problem", corrected_problem_count, include_count: true)} corrected"
|
||||||
end
|
end
|
||||||
|
|
||||||
ofail "#{errors_summary}."
|
ofail "#{errors_summary}."
|
||||||
@ -334,11 +333,13 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.print_problems(results, display_filename:)
|
private
|
||||||
|
|
||||||
|
def print_problems(results)
|
||||||
results.each do |(name, path), problems|
|
results.each do |(name, path), problems|
|
||||||
problem_lines = format_problem_lines(problems)
|
problem_lines = format_problem_lines(problems)
|
||||||
|
|
||||||
if display_filename
|
if args.display_filename?
|
||||||
problem_lines.each do |l|
|
problem_lines.each do |l|
|
||||||
puts "#{path}: #{l}"
|
puts "#{path}: #{l}"
|
||||||
end
|
end
|
||||||
@ -348,13 +349,17 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.format_problem_lines(problems)
|
def format_problem_lines(problems)
|
||||||
problems.map do |problem|
|
problems.map do |problem|
|
||||||
status = " #{Formatter.success("[corrected]")}" if problem.fetch(:corrected)
|
status = " #{Formatter.success("[corrected]")}" if problem.fetch(:corrected)
|
||||||
location = problem.fetch(:location)
|
location = problem.fetch(:location)
|
||||||
location = "#{location.line&.to_s&.prepend("line ")}#{location.column&.to_s&.prepend(", col ")}: " if location
|
if location
|
||||||
|
location = "#{location.line&.to_s&.prepend("line ")}#{location.column&.to_s&.prepend(", col ")}: "
|
||||||
|
end
|
||||||
message = problem.fetch(:message)
|
message = problem.fetch(:message)
|
||||||
"* #{location}#{message.chomp.gsub("\n", "\n ")}#{status}"
|
"* #{location}#{message.chomp.gsub("\n", "\n ")}#{status}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# typed: true
|
# typed: true
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "abstract_command"
|
||||||
require "formula"
|
require "formula"
|
||||||
require "utils/bottles"
|
require "utils/bottles"
|
||||||
require "tab"
|
require "tab"
|
||||||
@ -13,7 +14,12 @@ require "utils/gzip"
|
|||||||
require "api"
|
require "api"
|
||||||
require "extend/hash/deep_merge"
|
require "extend/hash/deep_merge"
|
||||||
|
|
||||||
BOTTLE_ERB = <<-EOS.freeze
|
module Homebrew
|
||||||
|
module DevCmd
|
||||||
|
class Bottle < AbstractCommand
|
||||||
|
include FileUtils
|
||||||
|
|
||||||
|
BOTTLE_ERB = <<-EOS.freeze
|
||||||
bottle do
|
bottle do
|
||||||
<% if [HOMEBREW_BOTTLE_DEFAULT_DOMAIN.to_s,
|
<% if [HOMEBREW_BOTTLE_DEFAULT_DOMAIN.to_s,
|
||||||
"#{HOMEBREW_BOTTLE_DEFAULT_DOMAIN}/bottles"].exclude?(root_url) %>
|
"#{HOMEBREW_BOTTLE_DEFAULT_DOMAIN}/bottles"].exclude?(root_url) %>
|
||||||
@ -28,18 +34,15 @@ BOTTLE_ERB = <<-EOS.freeze
|
|||||||
<%= line %>
|
<%= line %>
|
||||||
<% end %>
|
<% end %>
|
||||||
end
|
end
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
MAXIMUM_STRING_MATCHES = 100
|
MAXIMUM_STRING_MATCHES = 100
|
||||||
|
|
||||||
ALLOWABLE_HOMEBREW_REPOSITORY_LINKS = [
|
ALLOWABLE_HOMEBREW_REPOSITORY_LINKS = [
|
||||||
%r{#{Regexp.escape(HOMEBREW_LIBRARY)}/Homebrew/os/(mac|linux)/pkgconfig},
|
%r{#{Regexp.escape(HOMEBREW_LIBRARY)}/Homebrew/os/(mac|linux)/pkgconfig},
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
module Homebrew
|
cmd_args do
|
||||||
sig { returns(CLI::Parser) }
|
|
||||||
def self.bottle_args
|
|
||||||
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
|
||||||
`--build-bottle`.
|
`--build-bottle`.
|
||||||
@ -89,24 +92,22 @@ module Homebrew
|
|||||||
|
|
||||||
named_args [:installed_formula, :file], min: 1, without_api: true
|
named_args [:installed_formula, :file], min: 1, without_api: true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def self.bottle
|
|
||||||
args = bottle_args.parse
|
|
||||||
|
|
||||||
|
sig { override.void }
|
||||||
|
def run
|
||||||
if args.merge?
|
if args.merge?
|
||||||
Homebrew.install_bundler_gems!(groups: ["ast"])
|
Homebrew.install_bundler_gems!(groups: ["ast"])
|
||||||
return merge(args:)
|
return merge
|
||||||
end
|
end
|
||||||
|
|
||||||
gnu_tar_formula_ensure_installed_if_needed!(only_json_tab: args.only_json_tab?)
|
gnu_tar_formula_ensure_installed_if_needed!
|
||||||
|
|
||||||
args.named.to_resolved_formulae(uniq: false).each do |formula|
|
args.named.to_resolved_formulae(uniq: false).each do |formula|
|
||||||
bottle_formula formula, args:
|
bottle_formula formula
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.keg_contain?(string, keg, ignores, formula_and_runtime_deps_names = nil, args:)
|
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
|
||||||
|
|
||||||
print_filename = lambda do |str, filename|
|
print_filename = lambda do |str, filename|
|
||||||
@ -138,7 +139,8 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
text_matches = Keg.text_matches_in_file(file, string, ignores, linked_libraries, formula_and_runtime_deps_names)
|
text_matches = Keg.text_matches_in_file(file, string, ignores, linked_libraries,
|
||||||
|
formula_and_runtime_deps_names)
|
||||||
result = true if text_matches.any?
|
result = true if text_matches.any?
|
||||||
|
|
||||||
next if !args.verbose? || text_matches.empty?
|
next if !args.verbose? || text_matches.empty?
|
||||||
@ -153,10 +155,10 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
keg_contain_absolute_symlink_starting_with?(string, keg, args:) || result
|
keg_contain_absolute_symlink_starting_with?(string, keg) || result
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.keg_contain_absolute_symlink_starting_with?(string, keg, args:)
|
def keg_contain_absolute_symlink_starting_with?(string, keg)
|
||||||
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?
|
||||||
@ -174,7 +176,7 @@ module Homebrew
|
|||||||
!absolute_symlinks_start_with_string.empty?
|
!absolute_symlinks_start_with_string.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.cellar_parameter_needed?(cellar)
|
def 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,
|
||||||
@ -183,7 +185,7 @@ module Homebrew
|
|||||||
cellar.present? && default_cellars.exclude?(cellar)
|
cellar.present? && default_cellars.exclude?(cellar)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.generate_sha256_line(tag, digest, cellar, tag_column, digest_column)
|
def 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
|
||||||
@ -198,7 +200,7 @@ module Homebrew
|
|||||||
%Q(#{line}"#{digest}")
|
%Q(#{line}"#{digest}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.bottle_output(bottle, root_url_using)
|
def bottle_output(bottle, root_url_using)
|
||||||
cellars = bottle.checksums.filter_map do |checksum|
|
cellars = bottle.checksums.filter_map do |checksum|
|
||||||
cellar = checksum["cellar"]
|
cellar = checksum["cellar"]
|
||||||
next unless cellar_parameter_needed? cellar
|
next unless cellar_parameter_needed? cellar
|
||||||
@ -226,24 +228,24 @@ module Homebrew
|
|||||||
erb.result(erb_binding).gsub(/^\s*$\n/, "")
|
erb.result(erb_binding).gsub(/^\s*$\n/, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.sudo_purge
|
def 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
|
||||||
|
|
||||||
sig { returns(T::Array[String]) }
|
sig { returns(T::Array[String]) }
|
||||||
def self.tar_args
|
def tar_args
|
||||||
[].freeze
|
[].freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(gnu_tar_formula: Formula).returns(String) }
|
sig { params(gnu_tar_formula: Formula).returns(String) }
|
||||||
def self.gnu_tar(gnu_tar_formula)
|
def gnu_tar(gnu_tar_formula)
|
||||||
"#{gnu_tar_formula.opt_bin}/tar"
|
"#{gnu_tar_formula.opt_bin}/tar"
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(mtime: String).returns(T::Array[String]) }
|
sig { params(mtime: String).returns(T::Array[String]) }
|
||||||
def self.reproducible_gnutar_args(mtime)
|
def reproducible_gnutar_args(mtime)
|
||||||
# Ensure gnu tar is set up for reproducibility.
|
# Ensure gnu tar is set up for reproducibility.
|
||||||
# https://reproducible-builds.org/docs/archives/
|
# https://reproducible-builds.org/docs/archives/
|
||||||
[
|
[
|
||||||
@ -260,8 +262,8 @@ module Homebrew
|
|||||||
].freeze
|
].freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(only_json_tab: T::Boolean).returns(T.nilable(Formula)) }
|
sig { returns(T.nilable(Formula)) }
|
||||||
def self.gnu_tar_formula_ensure_installed_if_needed!(only_json_tab:)
|
def gnu_tar_formula_ensure_installed_if_needed!
|
||||||
gnu_tar_formula = begin
|
gnu_tar_formula = begin
|
||||||
Formula["gnu-tar"]
|
Formula["gnu-tar"]
|
||||||
rescue FormulaUnavailableError
|
rescue FormulaUnavailableError
|
||||||
@ -274,21 +276,21 @@ module Homebrew
|
|||||||
gnu_tar_formula
|
gnu_tar_formula
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(args: T.untyped, mtime: String).returns([String, T::Array[String]]) }
|
sig { params(mtime: String).returns([String, T::Array[String]]) }
|
||||||
def self.setup_tar_and_args!(args, mtime)
|
def setup_tar_and_args!(mtime)
|
||||||
# Without --only-json-tab bottles are never reproducible
|
# Without --only-json-tab bottles are never reproducible
|
||||||
default_tar_args = ["tar", tar_args].freeze
|
default_tar_args = ["tar", tar_args].freeze
|
||||||
return default_tar_args unless args.only_json_tab?
|
return default_tar_args unless args.only_json_tab?
|
||||||
|
|
||||||
# Use gnu-tar as it can be set up for reproducibility better than libarchive
|
# Use gnu-tar as it can be set up for reproducibility better than libarchive
|
||||||
# and to be consistent between macOS and Linux.
|
# and to be consistent between macOS and Linux.
|
||||||
gnu_tar_formula = gnu_tar_formula_ensure_installed_if_needed!(only_json_tab: args.only_json_tab?)
|
gnu_tar_formula = gnu_tar_formula_ensure_installed_if_needed!
|
||||||
return default_tar_args if gnu_tar_formula.blank?
|
return default_tar_args if gnu_tar_formula.blank?
|
||||||
|
|
||||||
[gnu_tar(gnu_tar_formula), reproducible_gnutar_args(mtime)].freeze
|
[gnu_tar(gnu_tar_formula), reproducible_gnutar_args(mtime)].freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.formula_ignores(formula)
|
def 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)
|
||||||
@ -318,7 +320,7 @@ module Homebrew
|
|||||||
ignores.compact
|
ignores.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.bottle_formula(formula, args:)
|
def bottle_formula(formula)
|
||||||
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
|
||||||
@ -366,7 +368,7 @@ module Homebrew
|
|||||||
end || 0
|
end || 0
|
||||||
end
|
end
|
||||||
|
|
||||||
filename = Bottle::Filename.create(formula, bottle_tag, rebuild)
|
filename = ::Bottle::Filename.create(formula, bottle_tag, rebuild)
|
||||||
local_filename = filename.to_s
|
local_filename = filename.to_s
|
||||||
bottle_path = Pathname.pwd/local_filename
|
bottle_path = Pathname.pwd/local_filename
|
||||||
|
|
||||||
@ -395,7 +397,8 @@ module Homebrew
|
|||||||
tab_json = Utils::Bottles.file_from_bottle(bottle_path, tab_path)
|
tab_json = Utils::Bottles.file_from_bottle(bottle_path, tab_path)
|
||||||
tab = Tab.from_file_content(tab_json, tab_path)
|
tab = Tab.from_file_content(tab_json, tab_path)
|
||||||
|
|
||||||
tag_spec = Formula[formula.name].bottle_specification.tag_specification_for(bottle_tag, no_older_versions: true)
|
tag_spec = Formula[formula.name].bottle_specification
|
||||||
|
.tag_specification_for(bottle_tag, no_older_versions: true)
|
||||||
relocatable = [:any, :any_skip_relocation].include?(tag_spec.cellar)
|
relocatable = [:any, :any_skip_relocation].include?(tag_spec.cellar)
|
||||||
skip_relocation = tag_spec.cellar == :any_skip_relocation
|
skip_relocation = tag_spec.cellar == :any_skip_relocation
|
||||||
|
|
||||||
@ -445,7 +448,7 @@ module Homebrew
|
|||||||
sudo_purge
|
sudo_purge
|
||||||
# Tar then gzip for reproducible bottles.
|
# Tar then gzip for reproducible bottles.
|
||||||
tar_mtime = tab.source_modified_time.strftime("%Y-%m-%d %H:%M:%S")
|
tar_mtime = tab.source_modified_time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
tar, tar_args = setup_tar_and_args!(args, tar_mtime)
|
tar, tar_args = setup_tar_and_args!(tar_mtime)
|
||||||
safe_system tar, "--create", "--numeric-owner",
|
safe_system tar, "--create", "--numeric-owner",
|
||||||
*tar_args,
|
*tar_args,
|
||||||
"--file", tar_path, "#{formula.name}/#{formula.pkg_version}"
|
"--file", tar_path, "#{formula.name}/#{formula.pkg_version}"
|
||||||
@ -482,7 +485,7 @@ module Homebrew
|
|||||||
else
|
else
|
||||||
HOMEBREW_REPOSITORY
|
HOMEBREW_REPOSITORY
|
||||||
end.to_s
|
end.to_s
|
||||||
if keg_contain?(repository_reference, keg, ignores + ALLOWABLE_HOMEBREW_REPOSITORY_LINKS, args:)
|
if keg_contain?(repository_reference, keg, ignores + ALLOWABLE_HOMEBREW_REPOSITORY_LINKS)
|
||||||
odie "Bottle contains non-relocatable reference to #{repository_reference}!"
|
odie "Bottle contains non-relocatable reference to #{repository_reference}!"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -490,16 +493,14 @@ module Homebrew
|
|||||||
if args.skip_relocation?
|
if args.skip_relocation?
|
||||||
skip_relocation = true
|
skip_relocation = true
|
||||||
else
|
else
|
||||||
relocatable = false if keg_contain?(prefix_check, keg, ignores, formula_and_runtime_deps_names, args:)
|
relocatable = false if keg_contain?(prefix_check, keg, ignores, formula_and_runtime_deps_names)
|
||||||
relocatable = false if keg_contain?(cellar, keg, ignores, formula_and_runtime_deps_names, args:)
|
relocatable = false if keg_contain?(cellar, keg, ignores, formula_and_runtime_deps_names)
|
||||||
if keg_contain?(HOMEBREW_LIBRARY.to_s, keg, ignores, formula_and_runtime_deps_names, args:)
|
relocatable = false if keg_contain?(HOMEBREW_LIBRARY.to_s, keg, ignores, formula_and_runtime_deps_names)
|
||||||
relocatable = false
|
|
||||||
end
|
|
||||||
if prefix != prefix_check
|
if prefix != prefix_check
|
||||||
relocatable = false if keg_contain_absolute_symlink_starting_with?(prefix, keg, args:)
|
relocatable = false if keg_contain_absolute_symlink_starting_with?(prefix, keg)
|
||||||
relocatable = false if keg_contain?("#{prefix}/etc", keg, ignores, args:)
|
relocatable = false if keg_contain?("#{prefix}/etc", keg, ignores)
|
||||||
relocatable = false if keg_contain?("#{prefix}/var", keg, ignores, args:)
|
relocatable = false if keg_contain?("#{prefix}/var", keg, ignores)
|
||||||
relocatable = false if keg_contain?("#{prefix}/share/vim", keg, ignores, args:)
|
relocatable = false if keg_contain?("#{prefix}/share/vim", keg, ignores)
|
||||||
end
|
end
|
||||||
skip_relocation = relocatable && !keg.require_relocation?
|
skip_relocation = relocatable && !keg.require_relocation?
|
||||||
end
|
end
|
||||||
@ -599,13 +600,13 @@ module Homebrew
|
|||||||
json_path.write(JSON.pretty_generate(json))
|
json_path.write(JSON.pretty_generate(json))
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.parse_json_files(filenames)
|
def 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 self.merge_json_files(json_files)
|
def 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"]
|
||||||
@ -618,7 +619,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.merge(args:)
|
def merge
|
||||||
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"]
|
||||||
@ -689,7 +690,7 @@ module Homebrew
|
|||||||
|
|
||||||
all_bottle_hash = T.let(nil, T.nilable(Hash))
|
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,
|
||||||
PkgVersion.parse(bottle_hash["formula"]["pkg_version"]),
|
PkgVersion.parse(bottle_hash["formula"]["pkg_version"]),
|
||||||
Utils::Bottles::Tag.from_symbol(tag.to_sym),
|
Utils::Bottles::Tag.from_symbol(tag.to_sym),
|
||||||
@ -699,7 +700,7 @@ module Homebrew
|
|||||||
if all_bottle && all_bottle_hash.nil?
|
if all_bottle && all_bottle_hash.nil?
|
||||||
all_bottle_tag_hash = tag_hash.dup
|
all_bottle_tag_hash = tag_hash.dup
|
||||||
|
|
||||||
all_filename = Bottle::Filename.new(
|
all_filename = ::Bottle::Filename.new(
|
||||||
formula_name,
|
formula_name,
|
||||||
PkgVersion.parse(bottle_hash["formula"]["pkg_version"]),
|
PkgVersion.parse(bottle_hash["formula"]["pkg_version"]),
|
||||||
Utils::Bottles::Tag.from_symbol(:all),
|
Utils::Bottles::Tag.from_symbol(:all),
|
||||||
@ -735,7 +736,7 @@ module Homebrew
|
|||||||
|
|
||||||
require "utils/ast"
|
require "utils/ast"
|
||||||
formula_ast = Utils::AST::FormulaAST.new(path.read)
|
formula_ast = Utils::AST::FormulaAST.new(path.read)
|
||||||
checksums = old_checksums(formula, formula_ast, bottle_hash, args:)
|
checksums = old_checksums(formula, formula_ast, bottle_hash)
|
||||||
update_or_add = checksums.nil? ? "add" : "update"
|
update_or_add = checksums.nil? ? "add" : "update"
|
||||||
|
|
||||||
checksums&.each(&bottle.method(:sha256))
|
checksums&.each(&bottle.method(:sha256))
|
||||||
@ -772,7 +773,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.merge_bottle_spec(old_keys, old_bottle_spec, new_bottle_hash)
|
def merge_bottle_spec(old_keys, old_bottle_spec, new_bottle_hash)
|
||||||
mismatches = []
|
mismatches = []
|
||||||
checksums = []
|
checksums = []
|
||||||
|
|
||||||
@ -812,12 +813,13 @@ module Homebrew
|
|||||||
[mismatches, checksums]
|
[mismatches, checksums]
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.old_checksums(formula, formula_ast, bottle_hash, args:)
|
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?
|
||||||
return [] unless args.keep_old?
|
return [] unless args.keep_old?
|
||||||
|
|
||||||
old_keys = T.cast(Utils::AST.body_children(bottle_node.body), T::Array[RuboCop::AST::SendNode]).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?
|
||||||
@ -828,6 +830,8 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
checksums
|
checksums
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
require "extend/os/dev-cmd/bottle"
|
require "extend/os/dev-cmd/bottle"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# typed: strict
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "abstract_command"
|
||||||
require "bump_version_parser"
|
require "bump_version_parser"
|
||||||
require "cask"
|
require "cask"
|
||||||
require "cask/download"
|
require "cask/download"
|
||||||
@ -8,11 +9,9 @@ require "cli/parser"
|
|||||||
require "utils/tar"
|
require "utils/tar"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module DevCmd
|
||||||
|
class BumpCaskPr < AbstractCommand
|
||||||
sig { returns(CLI::Parser) }
|
cmd_args do
|
||||||
def bump_cask_pr_args
|
|
||||||
Homebrew::CLI::Parser.new do
|
|
||||||
description <<~EOS
|
description <<~EOS
|
||||||
Create a pull request to update <cask> with a new version.
|
Create a pull request to update <cask> with a new version.
|
||||||
|
|
||||||
@ -61,12 +60,9 @@ module Homebrew
|
|||||||
|
|
||||||
named_args :cask, number: 1, without_api: true
|
named_args :cask, number: 1, without_api: true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
sig { void }
|
|
||||||
def bump_cask_pr
|
|
||||||
args = bump_cask_pr_args.parse
|
|
||||||
|
|
||||||
|
sig { override.void }
|
||||||
|
def run
|
||||||
odeprecated "brew bump-cask-pr --online" if args.online?
|
odeprecated "brew bump-cask-pr --online" if args.online?
|
||||||
odisabled "brew bump-cask-pr --force" if args.force?
|
odisabled "brew bump-cask-pr --force" if args.force?
|
||||||
|
|
||||||
@ -123,7 +119,7 @@ module Homebrew
|
|||||||
raise UsageError, "No `--version`, `--url` or `--sha256` argument specified!"
|
raise UsageError, "No `--version`, `--url` or `--sha256` argument specified!"
|
||||||
end
|
end
|
||||||
|
|
||||||
check_pull_requests(cask, args:, new_version:)
|
check_pull_requests(cask, new_version:)
|
||||||
|
|
||||||
replacement_pairs ||= []
|
replacement_pairs ||= []
|
||||||
branch_name = "bump-#{cask.token}"
|
branch_name = "bump-#{cask.token}"
|
||||||
@ -166,8 +162,8 @@ module Homebrew
|
|||||||
read_only_run: args.dry_run?,
|
read_only_run: args.dry_run?,
|
||||||
silent: args.quiet?)
|
silent: args.quiet?)
|
||||||
|
|
||||||
run_cask_audit(cask, old_contents, args:)
|
run_cask_audit(cask, old_contents)
|
||||||
run_cask_style(cask, old_contents, args:)
|
run_cask_style(cask, old_contents)
|
||||||
|
|
||||||
pr_info = {
|
pr_info = {
|
||||||
branch_name:,
|
branch_name:,
|
||||||
@ -180,6 +176,8 @@ module Homebrew
|
|||||||
GitHub.create_bump_pr(pr_info, args:)
|
GitHub.create_bump_pr(pr_info, args:)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
sig { params(version: Cask::DSL::Version, cask: Cask::Cask).returns(Cask::DSL::Version) }
|
sig { params(version: Cask::DSL::Version, cask: Cask::Cask).returns(Cask::DSL::Version) }
|
||||||
def shortened_version(version, cask:)
|
def shortened_version(version, cask:)
|
||||||
if version.before_comma == cask.version.before_comma
|
if version.before_comma == cask.version.before_comma
|
||||||
@ -253,8 +251,8 @@ module Homebrew
|
|||||||
replacement_pairs
|
replacement_pairs
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(cask: Cask::Cask, args: CLI::Args, new_version: BumpVersionParser).void }
|
sig { params(cask: Cask::Cask, new_version: BumpVersionParser).void }
|
||||||
def check_pull_requests(cask, args:, new_version:)
|
def check_pull_requests(cask, new_version:)
|
||||||
tap_remote_repo = cask.tap.full_name || cask.tap.remote_repo
|
tap_remote_repo = cask.tap.full_name || cask.tap.remote_repo
|
||||||
|
|
||||||
GitHub.check_for_duplicate_pull_requests(cask.token, tap_remote_repo,
|
GitHub.check_for_duplicate_pull_requests(cask.token, tap_remote_repo,
|
||||||
@ -279,8 +277,8 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(cask: Cask::Cask, old_contents: String, args: T.untyped).void }
|
sig { params(cask: Cask::Cask, old_contents: String).void }
|
||||||
def run_cask_audit(cask, old_contents, args:)
|
def run_cask_audit(cask, old_contents)
|
||||||
if args.dry_run?
|
if args.dry_run?
|
||||||
if args.no_audit?
|
if args.no_audit?
|
||||||
ohai "Skipping `brew audit`"
|
ohai "Skipping `brew audit`"
|
||||||
@ -302,8 +300,8 @@ module Homebrew
|
|||||||
odie "`brew audit` failed!"
|
odie "`brew audit` failed!"
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(cask: Cask::Cask, old_contents: String, args: T.untyped).void }
|
sig { params(cask: Cask::Cask, old_contents: String).void }
|
||||||
def run_cask_style(cask, old_contents, args:)
|
def run_cask_style(cask, old_contents)
|
||||||
if args.dry_run?
|
if args.dry_run?
|
||||||
if args.no_style?
|
if args.no_style?
|
||||||
ohai "Skipping `brew style --fix`"
|
ohai "Skipping `brew style --fix`"
|
||||||
@ -324,4 +322,6 @@ module Homebrew
|
|||||||
cask.sourcefile_path.atomic_write(old_contents)
|
cask.sourcefile_path.atomic_write(old_contents)
|
||||||
odie "`brew style --fix` failed!"
|
odie "`brew style --fix` failed!"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -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 "cli/parser"
|
||||||
require "utils/pypi"
|
require "utils/pypi"
|
||||||
require "utils/tar"
|
require "utils/tar"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module DevCmd
|
||||||
|
class BumpFormulaPr < AbstractCommand
|
||||||
sig { returns(CLI::Parser) }
|
cmd_args do
|
||||||
def bump_formula_pr_args
|
|
||||||
Homebrew::CLI::Parser.new do
|
|
||||||
description <<~EOS
|
description <<~EOS
|
||||||
Create a pull request to update <formula> with a new URL or a new tag.
|
Create a pull request to update <formula> with a new URL or a new tag.
|
||||||
|
|
||||||
@ -89,11 +88,9 @@ module Homebrew
|
|||||||
|
|
||||||
named_args :formula, max: 1, without_api: true
|
named_args :formula, max: 1, without_api: true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def bump_formula_pr
|
|
||||||
args = bump_formula_pr_args.parse
|
|
||||||
|
|
||||||
|
sig { override.void }
|
||||||
|
def run
|
||||||
if args.revision.present? && args.tag.nil? && args.version.nil?
|
if args.revision.present? && args.tag.nil? && args.version.nil?
|
||||||
raise UsageError, "`--revision` must be passed with either `--tag` or `--version`!"
|
raise UsageError, "`--revision` must be passed with either `--tag` or `--version`!"
|
||||||
end
|
end
|
||||||
@ -134,10 +131,10 @@ module Homebrew
|
|||||||
remote_branch = formula.tap.git_repo.origin_branch_name
|
remote_branch = formula.tap.git_repo.origin_branch_name
|
||||||
previous_branch = "-"
|
previous_branch = "-"
|
||||||
|
|
||||||
check_open_pull_requests(formula, tap_remote_repo, args:)
|
check_open_pull_requests(formula, tap_remote_repo)
|
||||||
|
|
||||||
new_version = args.version
|
new_version = args.version
|
||||||
check_new_version(formula, tap_remote_repo, version: new_version, args:) if new_version.present?
|
check_new_version(formula, tap_remote_repo, version: new_version) if new_version.present?
|
||||||
|
|
||||||
opoo "This formula has patches that may be resolved upstream." if formula.patchlist.present?
|
opoo "This formula has patches that may be resolved upstream." if formula.patchlist.present?
|
||||||
if formula.resources.any? { |resource| !resource.name.start_with?("homebrew-") }
|
if formula.resources.any? { |resource| !resource.name.start_with?("homebrew-") }
|
||||||
@ -149,7 +146,7 @@ module Homebrew
|
|||||||
new_mirror ||= determine_mirror(new_url)
|
new_mirror ||= determine_mirror(new_url)
|
||||||
new_mirrors ||= [new_mirror] if new_mirror.present?
|
new_mirrors ||= [new_mirror] if new_mirror.present?
|
||||||
|
|
||||||
check_for_mirrors(formula, old_mirrors, new_mirrors, args:) if new_url.present?
|
check_for_mirrors(formula, old_mirrors, new_mirrors) if new_url.present?
|
||||||
|
|
||||||
old_hash = formula_spec.checksum&.hexdigest
|
old_hash = formula_spec.checksum&.hexdigest
|
||||||
new_hash = args.sha256
|
new_hash = args.sha256
|
||||||
@ -161,10 +158,10 @@ module Homebrew
|
|||||||
old_version = old_formula_version.to_s
|
old_version = old_formula_version.to_s
|
||||||
forced_version = new_version.present?
|
forced_version = new_version.present?
|
||||||
new_url_hash = if new_url.present? && new_hash.present?
|
new_url_hash = if new_url.present? && new_hash.present?
|
||||||
check_new_version(formula, tap_remote_repo, url: new_url, args:) if new_version.blank?
|
check_new_version(formula, tap_remote_repo, url: new_url) if new_version.blank?
|
||||||
true
|
true
|
||||||
elsif new_tag.present? && new_revision.present?
|
elsif new_tag.present? && new_revision.present?
|
||||||
check_new_version(formula, tap_remote_repo, url: old_url, tag: new_tag, args:) if new_version.blank?
|
check_new_version(formula, tap_remote_repo, url: old_url, tag: new_tag) if new_version.blank?
|
||||||
false
|
false
|
||||||
elsif old_hash.blank?
|
elsif old_hash.blank?
|
||||||
if new_tag.blank? && new_version.blank? && new_revision.blank?
|
if new_tag.blank? && new_version.blank? && new_revision.blank?
|
||||||
@ -179,8 +176,9 @@ module Homebrew
|
|||||||
and old tag are both #{new_tag}.
|
and old tag are both #{new_tag}.
|
||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
check_new_version(formula, tap_remote_repo, url: old_url, tag: new_tag, args:) if new_version.blank?
|
check_new_version(formula, tap_remote_repo, url: old_url, tag: new_tag) if new_version.blank?
|
||||||
resource_path, forced_version = fetch_resource_and_forced_version(formula, new_version, old_url, tag: new_tag)
|
resource_path, forced_version = fetch_resource_and_forced_version(formula, new_version, old_url,
|
||||||
|
tag: new_tag)
|
||||||
new_revision = Utils.popen_read("git", "-C", resource_path.to_s, "rev-parse", "-q", "--verify", "HEAD")
|
new_revision = Utils.popen_read("git", "-C", resource_path.to_s, "rev-parse", "-q", "--verify", "HEAD")
|
||||||
new_revision = new_revision.strip
|
new_revision = new_revision.strip
|
||||||
elsif new_revision.blank?
|
elsif new_revision.blank?
|
||||||
@ -190,12 +188,12 @@ module Homebrew
|
|||||||
elsif new_url.blank? && new_version.blank?
|
elsif new_url.blank? && new_version.blank?
|
||||||
raise UsageError, "#{formula}: no `--url` or `--version` argument specified!"
|
raise UsageError, "#{formula}: no `--url` or `--version` argument specified!"
|
||||||
else
|
else
|
||||||
new_url ||= PyPI.update_pypi_url(old_url, new_version)
|
new_url ||= PyPI.update_pypi_url(old_url, T.must(new_version))
|
||||||
if new_url.blank?
|
if new_url.blank?
|
||||||
new_url = update_url(old_url, old_version, new_version)
|
new_url = update_url(old_url, old_version, T.must(new_version))
|
||||||
if new_mirrors.blank? && old_mirrors.present?
|
if new_mirrors.blank? && old_mirrors.present?
|
||||||
new_mirrors = old_mirrors.map do |old_mirror|
|
new_mirrors = old_mirrors.map do |old_mirror|
|
||||||
update_url(old_mirror, old_version, new_version)
|
update_url(old_mirror, old_version, T.must(new_version))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -206,7 +204,7 @@ module Homebrew
|
|||||||
#{new_url}
|
#{new_url}
|
||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
check_new_version(formula, tap_remote_repo, url: new_url, args:) if new_version.blank?
|
check_new_version(formula, tap_remote_repo, url: new_url) if new_version.blank?
|
||||||
resource_path, forced_version = fetch_resource_and_forced_version(formula, new_version, new_url)
|
resource_path, forced_version = fetch_resource_and_forced_version(formula, new_version, new_url)
|
||||||
Utils::Tar.validate_file(resource_path)
|
Utils::Tar.validate_file(resource_path)
|
||||||
new_hash = resource_path.sha256
|
new_hash = resource_path.sha256
|
||||||
@ -273,7 +271,7 @@ module Homebrew
|
|||||||
|
|
||||||
if new_mirrors.present?
|
if new_mirrors.present?
|
||||||
replacement_pairs << [
|
replacement_pairs << [
|
||||||
/^( +)(url "#{Regexp.escape(new_url)}"[^\n]*?\n)/m,
|
/^( +)(url "#{Regexp.escape(T.must(new_url))}"[^\n]*?\n)/m,
|
||||||
"\\1\\2\\1mirror \"#{new_mirrors.join("\"\n\\1mirror \"")}\"\n",
|
"\\1\\2\\1mirror \"#{new_mirrors.join("\"\n\\1mirror \"")}\"\n",
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
@ -344,7 +342,7 @@ module Homebrew
|
|||||||
ignore_non_pypi_packages: true
|
ignore_non_pypi_packages: true
|
||||||
end
|
end
|
||||||
|
|
||||||
run_audit(formula, alias_rename, old_contents, args:)
|
run_audit(formula, alias_rename, old_contents)
|
||||||
|
|
||||||
pr_message = "Created with `brew bump-formula-pr`."
|
pr_message = "Created with `brew bump-formula-pr`."
|
||||||
if resources_checked.nil? && formula.resources.any? { |resource| !resource.name.start_with?("homebrew-") }
|
if resources_checked.nil? && formula.resources.any? { |resource| !resource.name.start_with?("homebrew-") }
|
||||||
@ -393,6 +391,8 @@ module Homebrew
|
|||||||
GitHub.create_bump_pr(pr_info, args:)
|
GitHub.create_bump_pr(pr_info, args:)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def determine_mirror(url)
|
def determine_mirror(url)
|
||||||
case url
|
case url
|
||||||
when %r{.*ftp\.gnu\.org/gnu.*}
|
when %r{.*ftp\.gnu\.org/gnu.*}
|
||||||
@ -406,7 +406,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_for_mirrors(formula, old_mirrors, new_mirrors, args:)
|
def check_for_mirrors(formula, old_mirrors, new_mirrors)
|
||||||
return if new_mirrors.present? || old_mirrors.empty?
|
return if new_mirrors.present? || old_mirrors.empty?
|
||||||
|
|
||||||
if args.force?
|
if args.force?
|
||||||
@ -451,14 +451,14 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_open_pull_requests(formula, tap_remote_repo, args:)
|
def check_open_pull_requests(formula, tap_remote_repo)
|
||||||
GitHub.check_for_duplicate_pull_requests(formula.name, tap_remote_repo,
|
GitHub.check_for_duplicate_pull_requests(formula.name, tap_remote_repo,
|
||||||
state: "open",
|
state: "open",
|
||||||
file: formula.path.relative_path_from(formula.tap.path).to_s,
|
file: formula.path.relative_path_from(formula.tap.path).to_s,
|
||||||
quiet: args.quiet?)
|
quiet: args.quiet?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_new_version(formula, tap_remote_repo, args:, version: nil, url: nil, tag: nil)
|
def check_new_version(formula, tap_remote_repo, version: nil, url: nil, tag: nil)
|
||||||
if version.nil?
|
if version.nil?
|
||||||
specs = {}
|
specs = {}
|
||||||
specs[:tag] = tag if tag.present?
|
specs[:tag] = tag if tag.present?
|
||||||
@ -467,7 +467,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
check_throttle(formula, version)
|
check_throttle(formula, version)
|
||||||
check_closed_pull_requests(formula, tap_remote_repo, args:, version:)
|
check_closed_pull_requests(formula, tap_remote_repo, version:)
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_throttle(formula, new_version)
|
def check_throttle(formula, new_version)
|
||||||
@ -480,7 +480,7 @@ module Homebrew
|
|||||||
odie "#{formula} should only be updated every #{throttled_rate} releases on multiples of #{throttled_rate}"
|
odie "#{formula} should only be updated every #{throttled_rate} releases on multiples of #{throttled_rate}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_closed_pull_requests(formula, tap_remote_repo, args:, version:)
|
def check_closed_pull_requests(formula, tap_remote_repo, version:)
|
||||||
# if we haven't already found open requests, try for an exact match across closed requests
|
# if we haven't already found open requests, try for an exact match across closed requests
|
||||||
GitHub.check_for_duplicate_pull_requests(formula.name, tap_remote_repo,
|
GitHub.check_for_duplicate_pull_requests(formula.name, tap_remote_repo,
|
||||||
version:,
|
version:,
|
||||||
@ -501,7 +501,7 @@ module Homebrew
|
|||||||
[versioned_alias, "#{name}@#{new_alias_version}"]
|
[versioned_alias, "#{name}@#{new_alias_version}"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_audit(formula, alias_rename, old_contents, args:)
|
def run_audit(formula, alias_rename, old_contents)
|
||||||
audit_args = ["--formula"]
|
audit_args = ["--formula"]
|
||||||
audit_args << "--strict" if args.strict?
|
audit_args << "--strict" if args.strict?
|
||||||
audit_args << "--online" if args.online?
|
audit_args << "--online" if args.online?
|
||||||
@ -532,4 +532,6 @@ module Homebrew
|
|||||||
FileUtils.mv alias_rename.last, alias_rename.first if alias_rename.present?
|
FileUtils.mv alias_rename.last, alias_rename.first if alias_rename.present?
|
||||||
odie "`brew audit` failed!"
|
odie "`brew audit` failed!"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
# typed: true
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "abstract_command"
|
||||||
require "formula"
|
require "formula"
|
||||||
require "cli/parser"
|
require "cli/parser"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module DevCmd
|
||||||
|
class BumpRevision < AbstractCommand
|
||||||
sig { returns(CLI::Parser) }
|
cmd_args do
|
||||||
def bump_revision_args
|
|
||||||
Homebrew::CLI::Parser.new do
|
|
||||||
description <<~EOS
|
description <<~EOS
|
||||||
Create a commit to increment the revision of <formula>. If no revision is
|
Create a commit to increment the revision of <formula>. If no revision is
|
||||||
present, "revision 1" will be added.
|
present, "revision 1" will be added.
|
||||||
@ -27,11 +26,9 @@ module Homebrew
|
|||||||
|
|
||||||
named_args :formula, min: 1, without_api: true
|
named_args :formula, min: 1, without_api: true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def bump_revision
|
|
||||||
args = bump_revision_args.parse
|
|
||||||
|
|
||||||
|
sig { override.void }
|
||||||
|
def run
|
||||||
# As this command is simplifying user-run commands then let's just use a
|
# As this command is simplifying user-run commands then let's just use a
|
||||||
# user path, too.
|
# user path, too.
|
||||||
ENV["PATH"] = PATH.new(ORIGINAL_PATHS).to_s
|
ENV["PATH"] = PATH.new(ORIGINAL_PATHS).to_s
|
||||||
@ -75,4 +72,6 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# typed: true
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "timeout"
|
require "timeout"
|
||||||
@ -11,11 +11,11 @@ require "tap"
|
|||||||
require "unversioned_cask_checker"
|
require "unversioned_cask_checker"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
extend SystemCommand::Mixin
|
module DevCmd
|
||||||
|
class BumpUnversionedCask < AbstractCommand
|
||||||
|
include SystemCommand::Mixin
|
||||||
|
|
||||||
sig { returns(CLI::Parser) }
|
cmd_args do
|
||||||
def self.bump_unversioned_casks_args
|
|
||||||
Homebrew::CLI::Parser.new do
|
|
||||||
description <<~EOS
|
description <<~EOS
|
||||||
Check all casks with unversioned URLs in a given <tap> for updates.
|
Check all casks with unversioned URLs in a given <tap> for updates.
|
||||||
EOS
|
EOS
|
||||||
@ -28,16 +28,13 @@ module Homebrew
|
|||||||
|
|
||||||
named_args [:cask, :tap], min: 1, without_api: true
|
named_args [:cask, :tap], min: 1, without_api: true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
sig { void }
|
|
||||||
def self.bump_unversioned_casks
|
|
||||||
args = bump_unversioned_casks_args.parse
|
|
||||||
|
|
||||||
|
sig { override.void }
|
||||||
|
def run
|
||||||
Homebrew.install_bundler_gems!(groups: ["bump_unversioned_casks"])
|
Homebrew.install_bundler_gems!(groups: ["bump_unversioned_casks"])
|
||||||
|
|
||||||
state_file = if args.state_file.present?
|
state_file = if args.state_file.present?
|
||||||
Pathname(args.state_file).expand_path
|
Pathname(T.must(args.state_file)).expand_path
|
||||||
else
|
else
|
||||||
HOMEBREW_CACHE/"bump_unversioned_casks.json"
|
HOMEBREW_CACHE/"bump_unversioned_casks.json"
|
||||||
end
|
end
|
||||||
@ -75,7 +72,7 @@ module Homebrew
|
|||||||
|
|
||||||
key = cask.full_name
|
key = cask.full_name
|
||||||
|
|
||||||
new_state = bump_unversioned_cask(cask, state: state.fetch(key, {}), dry_run: args.dry_run?)
|
new_state = bump_unversioned_cask(cask, state: state.fetch(key, {}))
|
||||||
|
|
||||||
next unless new_state
|
next unless new_state
|
||||||
|
|
||||||
@ -85,11 +82,13 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(cask: Cask::Cask, state: T::Hash[String, T.untyped], dry_run: T.nilable(T::Boolean))
|
params(cask: Cask::Cask, state: T::Hash[String, T.untyped])
|
||||||
.returns(T.nilable(T::Hash[String, T.untyped]))
|
.returns(T.nilable(T::Hash[String, T.untyped]))
|
||||||
}
|
}
|
||||||
def self.bump_unversioned_cask(cask, state:, dry_run:)
|
def bump_unversioned_cask(cask, state:)
|
||||||
ohai "Checking #{cask.full_name}"
|
ohai "Checking #{cask.full_name}"
|
||||||
|
|
||||||
unversioned_cask_checker = UnversionedCaskChecker.new(cask)
|
unversioned_cask_checker = UnversionedCaskChecker.new(cask)
|
||||||
@ -150,7 +149,7 @@ module Homebrew
|
|||||||
cask.sourcefile_path
|
cask.sourcefile_path
|
||||||
]
|
]
|
||||||
|
|
||||||
if dry_run
|
if args.dry_run?
|
||||||
bump_cask_pr_args << "--dry-run"
|
bump_cask_pr_args << "--dry-run"
|
||||||
oh1 "Would bump #{cask} from #{cask.version} to #{version}"
|
oh1 "Would bump #{cask} from #{cask.version} to #{version}"
|
||||||
else
|
else
|
||||||
@ -174,4 +173,6 @@ module Homebrew
|
|||||||
"file_size" => file_size,
|
"file_size" => file_size,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
# typed: strict
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "abstract_command"
|
||||||
require "bump_version_parser"
|
require "bump_version_parser"
|
||||||
require "cli/parser"
|
require "cli/parser"
|
||||||
require "livecheck/livecheck"
|
require "livecheck/livecheck"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module DevCmd
|
||||||
|
class Bump < AbstractCommand
|
||||||
class VersionBumpInfo < T::Struct
|
class VersionBumpInfo < T::Struct
|
||||||
const :type, Symbol
|
const :type, Symbol
|
||||||
const :multiple_versions, T::Boolean
|
const :multiple_versions, T::Boolean
|
||||||
@ -19,9 +20,7 @@ module Homebrew
|
|||||||
const :closed_pull_requests, T.nilable(T.any(T::Array[String], String))
|
const :closed_pull_requests, T.nilable(T.any(T::Array[String], String))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(CLI::Parser) }
|
cmd_args do
|
||||||
def bump_args
|
|
||||||
CLI::Parser.new do
|
|
||||||
description <<~EOS
|
description <<~EOS
|
||||||
Display out-of-date brew formulae and the latest version available. If the
|
Display out-of-date brew formulae and the latest version available. If the
|
||||||
returned current and livecheck versions differ or when querying specific
|
returned current and livecheck versions differ or when querying specific
|
||||||
@ -56,12 +55,9 @@ module Homebrew
|
|||||||
|
|
||||||
named_args [:formula, :cask], without_api: true
|
named_args [:formula, :cask], without_api: true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
sig { void }
|
|
||||||
def bump
|
|
||||||
args = bump_args.parse
|
|
||||||
|
|
||||||
|
sig { override.void }
|
||||||
|
def run
|
||||||
Homebrew.install_bundler_gems!(groups: ["livecheck"])
|
Homebrew.install_bundler_gems!(groups: ["livecheck"])
|
||||||
|
|
||||||
if args.limit.present? && !args.formula? && !args.cask?
|
if args.limit.present? && !args.formula? && !args.cask?
|
||||||
@ -72,7 +68,7 @@ module Homebrew
|
|||||||
|
|
||||||
Homebrew.with_no_api_env do
|
Homebrew.with_no_api_env do
|
||||||
formulae_and_casks = if args.tap
|
formulae_and_casks = if args.tap
|
||||||
tap = Tap.fetch(args.tap)
|
tap = Tap.fetch(T.must(args.tap))
|
||||||
raise UsageError, "`--tap` cannot be used with official taps." if tap.official?
|
raise UsageError, "`--tap` cannot be used with official taps." if tap.official?
|
||||||
|
|
||||||
formulae = args.cask? ? [] : tap.formula_files.map { |path| Formulary.factory(path) }
|
formulae = args.cask? ? [] : tap.formula_files.map { |path| Formulary.factory(path) }
|
||||||
@ -105,21 +101,23 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
if formulae_and_casks.present?
|
if formulae_and_casks.present?
|
||||||
handle_formula_and_casks(formulae_and_casks, args)
|
handle_formula_and_casks(formulae_and_casks)
|
||||||
else
|
else
|
||||||
handle_api_response(args)
|
handle_api_response
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(formula_or_cask: T.any(Formula, Cask::Cask), args: CLI::Args).returns(T::Boolean) }
|
private
|
||||||
def skip_repology?(formula_or_cask, args:)
|
|
||||||
|
sig { params(formula_or_cask: T.any(Formula, Cask::Cask)).returns(T::Boolean) }
|
||||||
|
def skip_repology?(formula_or_cask)
|
||||||
(ENV["CI"].present? && args.open_pr? && formula_or_cask.livecheckable?) ||
|
(ENV["CI"].present? && args.open_pr? && formula_or_cask.livecheckable?) ||
|
||||||
(formula_or_cask.is_a?(Formula) && formula_or_cask.versioned_formula?)
|
(formula_or_cask.is_a?(Formula) && formula_or_cask.versioned_formula?)
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(formulae_and_casks: T::Array[T.any(Formula, Cask::Cask)], args: CLI::Args).void }
|
sig { params(formulae_and_casks: T::Array[T.any(Formula, Cask::Cask)]).void }
|
||||||
def handle_formula_and_casks(formulae_and_casks, args)
|
def handle_formula_and_casks(formulae_and_casks)
|
||||||
Livecheck.load_other_tap_strategies(formulae_and_casks)
|
Livecheck.load_other_tap_strategies(formulae_and_casks)
|
||||||
|
|
||||||
ambiguous_casks = []
|
ambiguous_casks = []
|
||||||
@ -153,20 +151,19 @@ module Homebrew
|
|||||||
Repology::HOMEBREW_CASK
|
Repology::HOMEBREW_CASK
|
||||||
end
|
end
|
||||||
|
|
||||||
package_data = Repology.single_package_query(name, repository:) unless skip_repology?(formula_or_cask, args:)
|
package_data = Repology.single_package_query(name, repository:) unless skip_repology?(formula_or_cask)
|
||||||
|
|
||||||
retrieve_and_display_info_and_open_pr(
|
retrieve_and_display_info_and_open_pr(
|
||||||
formula_or_cask,
|
formula_or_cask,
|
||||||
name,
|
name,
|
||||||
package_data&.values&.first,
|
package_data&.values&.first,
|
||||||
args:,
|
|
||||||
ambiguous_cask: ambiguous_casks.include?(formula_or_cask),
|
ambiguous_cask: ambiguous_casks.include?(formula_or_cask),
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(args: CLI::Args).void }
|
sig { void }
|
||||||
def handle_api_response(args)
|
def handle_api_response
|
||||||
limit = args.limit.to_i if args.limit.present?
|
limit = args.limit.to_i if args.limit.present?
|
||||||
|
|
||||||
api_response = {}
|
api_response = {}
|
||||||
@ -220,7 +217,6 @@ module Homebrew
|
|||||||
formula_or_cask,
|
formula_or_cask,
|
||||||
name,
|
name,
|
||||||
repositories,
|
repositories,
|
||||||
args:,
|
|
||||||
ambiguous_cask:,
|
ambiguous_cask:,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@ -321,13 +317,16 @@ module Homebrew
|
|||||||
params(
|
params(
|
||||||
formula_or_cask: T.any(Formula, Cask::Cask),
|
formula_or_cask: T.any(Formula, Cask::Cask),
|
||||||
repositories: T::Array[T.untyped],
|
repositories: T::Array[T.untyped],
|
||||||
args: CLI::Args,
|
|
||||||
name: String,
|
name: String,
|
||||||
).returns(VersionBumpInfo)
|
).returns(VersionBumpInfo)
|
||||||
}
|
}
|
||||||
def retrieve_versions_by_arch(formula_or_cask:, repositories:, args:, name:)
|
def retrieve_versions_by_arch(formula_or_cask:, repositories:, name:)
|
||||||
is_cask_with_blocks = formula_or_cask.is_a?(Cask::Cask) && formula_or_cask.on_system_blocks_exist?
|
is_cask_with_blocks = formula_or_cask.is_a?(Cask::Cask) && formula_or_cask.on_system_blocks_exist?
|
||||||
type, version_name = formula_or_cask.is_a?(Formula) ? [:formula, "formula version:"] : [:cask, "cask version: "]
|
type, version_name = if formula_or_cask.is_a?(Formula)
|
||||||
|
[:formula, "formula version:"]
|
||||||
|
else
|
||||||
|
[:cask, "cask version: "]
|
||||||
|
end
|
||||||
|
|
||||||
old_versions = {}
|
old_versions = {}
|
||||||
new_versions = {}
|
new_versions = {}
|
||||||
@ -429,14 +428,12 @@ module Homebrew
|
|||||||
formula_or_cask: T.any(Formula, Cask::Cask),
|
formula_or_cask: T.any(Formula, Cask::Cask),
|
||||||
name: String,
|
name: String,
|
||||||
repositories: T::Array[T.untyped],
|
repositories: T::Array[T.untyped],
|
||||||
args: CLI::Args,
|
|
||||||
ambiguous_cask: T::Boolean,
|
ambiguous_cask: T::Boolean,
|
||||||
).void
|
).void
|
||||||
}
|
}
|
||||||
def retrieve_and_display_info_and_open_pr(formula_or_cask, name, repositories, args:, ambiguous_cask: false)
|
def retrieve_and_display_info_and_open_pr(formula_or_cask, name, repositories, ambiguous_cask: false)
|
||||||
version_info = retrieve_versions_by_arch(formula_or_cask:,
|
version_info = retrieve_versions_by_arch(formula_or_cask:,
|
||||||
repositories:,
|
repositories:,
|
||||||
args:,
|
|
||||||
name:)
|
name:)
|
||||||
|
|
||||||
current_version = version_info.current_version
|
current_version = version_info.current_version
|
||||||
@ -480,7 +477,7 @@ module Homebrew
|
|||||||
Current #{version_label} #{current_versions}
|
Current #{version_label} #{current_versions}
|
||||||
Latest livecheck version: #{new_versions}
|
Latest livecheck version: #{new_versions}
|
||||||
EOS
|
EOS
|
||||||
puts <<~EOS unless skip_repology?(formula_or_cask, args:)
|
puts <<~EOS unless skip_repology?(formula_or_cask)
|
||||||
Latest Repology version: #{repology_latest}
|
Latest Repology version: #{repology_latest}
|
||||||
EOS
|
EOS
|
||||||
if formula_or_cask.is_a?(Formula) && formula_or_cask.synced_with_other_formulae?
|
if formula_or_cask.is_a?(Formula) && formula_or_cask.synced_with_other_formulae?
|
||||||
@ -551,4 +548,6 @@ module Homebrew
|
|||||||
|
|
||||||
synced_with
|
synced_with
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
# typed: true
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "abstract_command"
|
||||||
require "cli/parser"
|
require "cli/parser"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
sig { returns(CLI::Parser) }
|
module DevCmd
|
||||||
def self.cat_args
|
class Cat < AbstractCommand
|
||||||
Homebrew::CLI::Parser.new do
|
include FileUtils
|
||||||
|
|
||||||
|
cmd_args do
|
||||||
description <<~EOS
|
description <<~EOS
|
||||||
Display the source of a <formula> or <cask>.
|
Display the source of a <formula> or <cask>.
|
||||||
EOS
|
EOS
|
||||||
@ -20,11 +23,9 @@ module Homebrew
|
|||||||
|
|
||||||
named_args [:formula, :cask], min: 1, without_api: true
|
named_args [:formula, :cask], min: 1, without_api: true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def self.cat
|
|
||||||
args = cat_args.parse
|
|
||||||
|
|
||||||
|
sig { override.void }
|
||||||
|
def run
|
||||||
cd HOMEBREW_REPOSITORY do
|
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
|
||||||
@ -59,4 +60,6 @@ module Homebrew
|
|||||||
safe_system pager, *args.named.to_paths
|
safe_system pager, *args.named.to_paths
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,30 +1,29 @@
|
|||||||
# typed: true
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "abstract_command"
|
||||||
require "commands"
|
require "commands"
|
||||||
require "cli/parser"
|
require "cli/parser"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module DevCmd
|
||||||
|
class Command < AbstractCommand
|
||||||
sig { returns(CLI::Parser) }
|
cmd_args do
|
||||||
def command_args
|
|
||||||
Homebrew::CLI::Parser.new do
|
|
||||||
description <<~EOS
|
description <<~EOS
|
||||||
Display the path to the file being used when invoking `brew` <cmd>.
|
Display the path to the file being used when invoking `brew` <cmd>.
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
named_args :command, min: 1
|
named_args :command, min: 1
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def command
|
|
||||||
args = command_args.parse
|
|
||||||
|
|
||||||
|
sig { override.void }
|
||||||
|
def run
|
||||||
args.named.each do |cmd|
|
args.named.each do |cmd|
|
||||||
path = Commands.path(cmd)
|
path = Commands.path(cmd)
|
||||||
odie "Unknown command: #{cmd}" unless path
|
odie "Unknown command: #{cmd}" unless path
|
||||||
puts path
|
puts path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -5,8 +5,8 @@ require "cli/parser"
|
|||||||
require "csv"
|
require "csv"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module DevCmd
|
||||||
|
class Contributions < AbstractCommand
|
||||||
PRIMARY_REPOS = %w[brew core cask].freeze
|
PRIMARY_REPOS = %w[brew core cask].freeze
|
||||||
SUPPORTED_REPOS = [
|
SUPPORTED_REPOS = [
|
||||||
PRIMARY_REPOS,
|
PRIMARY_REPOS,
|
||||||
@ -15,9 +15,7 @@ module Homebrew
|
|||||||
].flatten.freeze
|
].flatten.freeze
|
||||||
MAX_REPO_COMMITS = 1000
|
MAX_REPO_COMMITS = 1000
|
||||||
|
|
||||||
sig { returns(CLI::Parser) }
|
cmd_args do
|
||||||
def contributions_args
|
|
||||||
Homebrew::CLI::Parser.new do
|
|
||||||
usage_banner "`contributions` [--user=<email|username>] [<--repositories>`=`] [<--csv>]"
|
usage_banner "`contributions` [--user=<email|username>] [<--repositories>`=`] [<--csv>]"
|
||||||
description <<~EOS
|
description <<~EOS
|
||||||
Summarise contributions to Homebrew repositories.
|
Summarise contributions to Homebrew repositories.
|
||||||
@ -43,18 +41,15 @@ module Homebrew
|
|||||||
switch "--csv",
|
switch "--csv",
|
||||||
description: "Print a CSV of contributions across repositories over the time period."
|
description: "Print a CSV of contributions across repositories over the time period."
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
sig { void }
|
|
||||||
def contributions
|
|
||||||
args = contributions_args.parse
|
|
||||||
|
|
||||||
|
sig { override.void }
|
||||||
|
def run
|
||||||
results = {}
|
results = {}
|
||||||
grand_totals = {}
|
grand_totals = {}
|
||||||
|
|
||||||
repos = if args.repositories.blank? || args.repositories.include?("primary")
|
repos = if args.repositories.blank? || T.must(args.repositories).include?("primary")
|
||||||
PRIMARY_REPOS
|
PRIMARY_REPOS
|
||||||
elsif args.repositories.include?("all")
|
elsif T.must(args.repositories).include?("all")
|
||||||
SUPPORTED_REPOS
|
SUPPORTED_REPOS
|
||||||
else
|
else
|
||||||
args.repositories
|
args.repositories
|
||||||
@ -71,7 +66,7 @@ module Homebrew
|
|||||||
# committer details to match the ones on GitHub.
|
# committer details to match the ones on GitHub.
|
||||||
# TODO: Switch to using the GitHub APIs instead of `git log` if
|
# TODO: Switch to using the GitHub APIs instead of `git log` if
|
||||||
# they ever support trailers.
|
# they ever support trailers.
|
||||||
results[username] = scan_repositories(repos, username, args, from:)
|
results[username] = scan_repositories(repos, username, from:)
|
||||||
grand_totals[username] = total(results[username])
|
grand_totals[username] = total(results[username])
|
||||||
|
|
||||||
contributions = contribution_types.filter_map do |type|
|
contributions = contribution_types.filter_map do |type|
|
||||||
@ -80,7 +75,8 @@ module Homebrew
|
|||||||
|
|
||||||
"#{Utils.pluralize("time", type_count, include_count: true)} (#{type})"
|
"#{Utils.pluralize("time", type_count, include_count: true)} (#{type})"
|
||||||
end
|
end
|
||||||
contributions << "#{Utils.pluralize("time", grand_totals[username].values.sum, include_count: true)} (total)"
|
contributions <<
|
||||||
|
"#{Utils.pluralize("time", grand_totals[username].values.sum, include_count: true)} (total)"
|
||||||
|
|
||||||
puts [
|
puts [
|
||||||
"#{username} contributed",
|
"#{username} contributed",
|
||||||
@ -95,6 +91,8 @@ module Homebrew
|
|||||||
puts generate_csv(grand_totals)
|
puts generate_csv(grand_totals)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
sig { params(repo: String).returns(Pathname) }
|
sig { params(repo: String).returns(Pathname) }
|
||||||
def find_repo_path_for_repo(repo)
|
def find_repo_path_for_repo(repo)
|
||||||
return HOMEBREW_REPOSITORY if repo == "brew"
|
return HOMEBREW_REPOSITORY if repo == "brew"
|
||||||
@ -139,7 +137,7 @@ module Homebrew
|
|||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def scan_repositories(repos, person, args, from:)
|
def scan_repositories(repos, person, from:)
|
||||||
data = {}
|
data = {}
|
||||||
|
|
||||||
repos.each do |repo|
|
repos.each do |repo|
|
||||||
@ -168,7 +166,7 @@ module Homebrew
|
|||||||
author: author_commits,
|
author: author_commits,
|
||||||
committer: committer_commits,
|
committer: committer_commits,
|
||||||
coauthorship: git_log_trailers_cmd(T.must(repo_path), person, "Co-authored-by", from:, to: args.to),
|
coauthorship: git_log_trailers_cmd(T.must(repo_path), person, "Co-authored-by", from:, to: args.to),
|
||||||
review: count_reviews(repo_full_name, person, args),
|
review: count_reviews(repo_full_name, person),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -201,8 +199,8 @@ module Homebrew
|
|||||||
Utils.safe_popen_read(*cmd).lines.count { |l| l.include?(person) }
|
Utils.safe_popen_read(*cmd).lines.count { |l| l.include?(person) }
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(repo_full_name: String, person: String, args: Homebrew::CLI::Args).returns(Integer) }
|
sig { params(repo_full_name: String, person: String).returns(Integer) }
|
||||||
def count_reviews(repo_full_name, person, args)
|
def count_reviews(repo_full_name, person)
|
||||||
GitHub.count_issues("", is: "pr", repo: repo_full_name, reviewed_by: person, review: "approved", args:)
|
GitHub.count_issues("", is: "pr", repo: repo_full_name, reviewed_by: person, review: "approved", args:)
|
||||||
rescue GitHub::API::ValidationFailedError
|
rescue GitHub::API::ValidationFailedError
|
||||||
if args.verbose?
|
if args.verbose?
|
||||||
@ -210,4 +208,6 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
0 # Users who have made their contributions private are not searchable to determine counts.
|
0 # Users who have made their contributions private are not searchable to determine counts.
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
class << self
|
module DevCmd
|
||||||
|
class Bottle < AbstractCommand
|
||||||
undef tar_args
|
undef tar_args
|
||||||
|
|
||||||
sig { returns(T::Array[String]) }
|
sig { returns(T::Array[String]) }
|
||||||
@ -21,4 +22,5 @@ module Homebrew
|
|||||||
"#{gnu_tar_formula.opt_bin}/gtar"
|
"#{gnu_tar_formula.opt_bin}/gtar"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -49,7 +49,8 @@ module Tapioca
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
root.create_path(Homebrew::CLI::Args) do |klass|
|
root.create_path(Homebrew::CLI::Args) do |klass|
|
||||||
create_args_methods(klass, T.must(T.cast(constant, T.class_of(Homebrew::AbstractCommand)).parser))
|
parser = T.cast(constant, T.class_of(Homebrew::AbstractCommand)).parser
|
||||||
|
create_args_methods(klass, parser)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -583,7 +583,7 @@ RSpec.describe Homebrew::CLI::Parser do
|
|||||||
# commands for formulae and casks on Linux.
|
# commands for formulae and casks on Linux.
|
||||||
it "succeeds for developer commands" do
|
it "succeeds for developer commands" do
|
||||||
require "dev-cmd/cat"
|
require "dev-cmd/cat"
|
||||||
args = Homebrew.cat_args.parse(["--cask", "cask_name"])
|
args = Homebrew::DevCmd::Cat.new(["--cask", "cask_name"]).args
|
||||||
expect(args.cask?).to be(true)
|
expect(args.cask?).to be(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -5,7 +5,7 @@ require "formulary"
|
|||||||
require "cmd/shared_examples/args_parse"
|
require "cmd/shared_examples/args_parse"
|
||||||
require "utils/spdx"
|
require "utils/spdx"
|
||||||
|
|
||||||
RSpec.describe "brew audit" do
|
RSpec.describe Homebrew::DevCmd::Audit do
|
||||||
it_behaves_like "parseable arguments"
|
it_behaves_like "parseable arguments"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
require "cmd/shared_examples/args_parse"
|
require "cmd/shared_examples/args_parse"
|
||||||
require "dev-cmd/bottle"
|
require "dev-cmd/bottle"
|
||||||
|
|
||||||
RSpec.describe "brew bottle" do
|
RSpec.describe Homebrew::DevCmd::Bottle do
|
||||||
def stub_hash(parameters)
|
def stub_hash(parameters)
|
||||||
<<~EOS
|
<<~EOS
|
||||||
{
|
{
|
||||||
@ -30,7 +30,7 @@ RSpec.describe "brew bottle" do
|
|||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like "parseable arguments"
|
it_behaves_like "parseable arguments", argv: ["foo"]
|
||||||
|
|
||||||
it "builds a bottle for the given Formula", :integration_test do
|
it "builds a bottle for the given Formula", :integration_test do
|
||||||
install_test_formula "testball", build_bottle: true
|
install_test_formula "testball", build_bottle: true
|
||||||
@ -308,8 +308,8 @@ RSpec.describe "brew bottle" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe Homebrew do
|
describe "bottle_cmd" do
|
||||||
subject(:homebrew) { described_class }
|
subject(:homebrew) { described_class.new(["foo"]) }
|
||||||
|
|
||||||
let(:hello_hash_big_sur) do
|
let(:hello_hash_big_sur) do
|
||||||
JSON.parse stub_hash(
|
JSON.parse stub_hash(
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
require "cmd/shared_examples/args_parse"
|
require "cmd/shared_examples/args_parse"
|
||||||
require "dev-cmd/bump-cask-pr"
|
require "dev-cmd/bump-cask-pr"
|
||||||
|
|
||||||
RSpec.describe "brew bump-cask-pr" do
|
RSpec.describe Homebrew::DevCmd::BumpCaskPr do
|
||||||
it_behaves_like "parseable arguments"
|
it_behaves_like "parseable arguments", argv: ["foo"]
|
||||||
end
|
end
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "cmd/shared_examples/args_parse"
|
require "cmd/shared_examples/args_parse"
|
||||||
|
require "dev-cmd/bump-formula-pr"
|
||||||
|
|
||||||
RSpec.describe "brew bump-formula-pr" do
|
RSpec.describe Homebrew::DevCmd::BumpFormulaPr do
|
||||||
it_behaves_like "parseable arguments"
|
it_behaves_like "parseable arguments"
|
||||||
end
|
end
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "cmd/shared_examples/args_parse"
|
require "cmd/shared_examples/args_parse"
|
||||||
|
require "dev-cmd/bump-revision"
|
||||||
|
|
||||||
RSpec.describe "brew bump-revision" do
|
RSpec.describe Homebrew::DevCmd::BumpRevision do
|
||||||
it_behaves_like "parseable arguments"
|
it_behaves_like "parseable arguments", argv: ["foo"]
|
||||||
end
|
end
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "cmd/shared_examples/args_parse"
|
require "cmd/shared_examples/args_parse"
|
||||||
|
require "dev-cmd/bump-unversioned-casks"
|
||||||
|
|
||||||
RSpec.describe "brew bump-unversioned-casks" do
|
RSpec.describe Homebrew::DevCmd::BumpUnversionedCask do
|
||||||
it_behaves_like "parseable arguments"
|
it_behaves_like "parseable arguments", argv: ["foo"]
|
||||||
end
|
end
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "cmd/shared_examples/args_parse"
|
require "cmd/shared_examples/args_parse"
|
||||||
|
require "dev-cmd/bump"
|
||||||
|
|
||||||
RSpec.describe "brew bump" do
|
RSpec.describe Homebrew::DevCmd::Bump do
|
||||||
it_behaves_like "parseable arguments"
|
it_behaves_like "parseable arguments"
|
||||||
|
|
||||||
describe "formula", :integration_test, :needs_homebrew_curl, :needs_network do
|
describe "formula", :integration_test, :needs_homebrew_curl, :needs_network do
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "cmd/shared_examples/args_parse"
|
require "cmd/shared_examples/args_parse"
|
||||||
|
require "dev-cmd/cat"
|
||||||
|
|
||||||
RSpec.describe "brew cat" do
|
RSpec.describe Homebrew::DevCmd::Cat do
|
||||||
it_behaves_like "parseable arguments"
|
it_behaves_like "parseable arguments", argv: ["foo"]
|
||||||
|
|
||||||
it "prints the content of a given Formula", :integration_test do
|
it "prints the content of a given Formula", :integration_test do
|
||||||
formula_file = setup_test_formula "testball"
|
formula_file = setup_test_formula "testball"
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "cmd/shared_examples/args_parse"
|
require "cmd/shared_examples/args_parse"
|
||||||
|
require "dev-cmd/command"
|
||||||
|
|
||||||
RSpec.describe "brew command" do
|
RSpec.describe Homebrew::DevCmd::Command do
|
||||||
it_behaves_like "parseable arguments"
|
it_behaves_like "parseable arguments", argv: ["foo"]
|
||||||
|
|
||||||
it "returns the file for a given command", :integration_test do
|
it "returns the file for a given command", :integration_test do
|
||||||
expect { brew "command", "info" }
|
expect { brew "command", "info" }
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "cmd/shared_examples/args_parse"
|
require "cmd/shared_examples/args_parse"
|
||||||
|
require "dev-cmd/contributions"
|
||||||
|
|
||||||
RSpec.describe "brew contributions" do
|
RSpec.describe Homebrew::DevCmd::Contributions do
|
||||||
it_behaves_like "parseable arguments"
|
it_behaves_like "parseable arguments"
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user