brew/Library/Homebrew/readall.rb
apainintheneck bea2dc65fe Clean up files that use to include cachable
These were changed to extend to make it easier to determine
where the classes come to in the extended callback but that
means that the file is somewhat inconsistent. On the one
hand we're using class methods and on the other we're extend
self. This cleans that up but now the diff is atrocious and
the blame is even worse. Oh well...
2024-02-26 21:21:38 -08:00

134 lines
4.1 KiB
Ruby

# typed: true
# frozen_string_literal: true
require "formula"
require "cask/cask_loader"
require "system_command"
# Helper module for validating syntax in taps.
#
# @api private
module Readall
extend Cachable
extend SystemCommand::Mixin
# TODO: remove this once the `MacOS` module is undefined on Linux
MACOS_MODULE_REGEX = /\b(MacOS|OS::Mac)(\.|::)\b/
private_constant :MACOS_MODULE_REGEX
private_class_method :cache
def self.valid_ruby_syntax?(ruby_files)
failed = T.let(false, T::Boolean)
ruby_files.each do |ruby_file|
# As a side effect, print syntax errors/warnings to `$stderr`.
failed = true if syntax_errors_or_warnings?(ruby_file)
end
!failed
end
def self.valid_aliases?(alias_dir, formula_dir)
return true unless alias_dir.directory?
failed = T.let(false, T::Boolean)
alias_dir.each_child do |f|
if !f.symlink?
onoe "Non-symlink alias: #{f}"
failed = true
elsif !f.file?
onoe "Non-file alias: #{f}"
failed = true
end
if formula_dir.glob("**/#{f.basename}.rb").any?(&:exist?)
onoe "Formula duplicating alias: #{f}"
failed = true
end
end
!failed
end
def self.valid_formulae?(tap, bottle_tag: nil)
cache[:valid_formulae] ||= {}
success = T.let(true, T::Boolean)
tap.formula_files.each do |file|
valid = cache[:valid_formulae][file]
next if valid == true || valid&.include?(bottle_tag)
formula_name = file.basename(".rb").to_s
formula_contents = file.read(encoding: "UTF-8")
readall_namespace = "ReadallNamespace"
readall_formula_class = Formulary.load_formula(formula_name, file, formula_contents, readall_namespace,
flags: [], ignore_errors: false)
readall_formula = readall_formula_class.new(formula_name, file, :stable, tap: tap)
readall_formula.to_hash
# TODO: Remove check for MACOS_MODULE_REGEX once the `MacOS` module is undefined on Linux
cache[:valid_formulae][file] = if readall_formula.on_system_blocks_exist? ||
formula_contents.match?(MACOS_MODULE_REGEX)
[bottle_tag, *cache[:valid_formulae][file]]
else
true
end
rescue Interrupt
raise
rescue Exception => e # rubocop:disable Lint/RescueException
onoe "Invalid formula (#{bottle_tag}): #{file}"
$stderr.puts e
success = false
end
success
end
def self.valid_casks?(_tap, os_name: nil, arch: nil)
true
end
def self.valid_tap?(tap, aliases: false, no_simulate: false,
os_arch_combinations: OnSystem::ALL_OS_ARCH_COMBINATIONS)
success = true
if aliases
valid_aliases = valid_aliases?(tap.alias_dir, tap.formula_dir)
success = false unless valid_aliases
end
if no_simulate
success = false unless valid_formulae?(tap)
success = false unless valid_casks?(tap)
else
os_arch_combinations.each do |os, arch|
bottle_tag = Utils::Bottles::Tag.new(system: os, arch: arch)
next unless bottle_tag.valid_combination?
Homebrew::SimulateSystem.with os: os, arch: arch do
success = false unless valid_formulae?(tap, bottle_tag: bottle_tag)
success = false unless valid_casks?(tap, os_name: os, arch: arch)
end
end
end
success
end
private_class_method def self.syntax_errors_or_warnings?(filename)
# Retrieve messages about syntax errors/warnings printed to `$stderr`.
_, err, status = system_command(RUBY_PATH, args: ["-c", "-w", filename], print_stderr: false)
# Ignore unnecessary warning about named capture conflicts.
# See https://bugs.ruby-lang.org/issues/12359.
messages = err.lines
.grep_v(/named capture conflicts a local variable/)
.join
$stderr.print messages
# Only syntax errors result in a non-zero status code. To detect syntax
# warnings we also need to inspect the output to `$stderr`.
!status.success? || !messages.chomp.empty?
end
end
require "extend/os/readall"